void CPlayers::OnRender() { // update RenderInfo for ninja bool IsTeamplay = (m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) != 0; for(int i = 0; i < MAX_CLIENTS; ++i) { m_aRenderInfo[i] = m_pClient->m_aClients[i].m_RenderInfo; } // render other players in two passes, first pass we render the other, second pass we render our self for(int p = 0; p < 4; p++) { for(int i = 0; i < MAX_CLIENTS; i++) { // only render active characters if(!m_pClient->m_Snap.m_aCharacters[i].m_Active) continue; const void *pPrevInfo = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_PLAYERINFO, i); const void *pInfo = Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i); if(pPrevInfo && pInfo) { // bool Local = m_pClient->m_LocalClientID == i; if((p % 2) == 0 && Local) continue; if((p % 2) == 1 && !Local) continue; CNetObj_Character PrevChar = m_pClient->m_Snap.m_aCharacters[i].m_Prev; CNetObj_Character CurChar = m_pClient->m_Snap.m_aCharacters[i].m_Cur; if(p<2) RenderHook( &PrevChar, &CurChar, (const CNetObj_PlayerInfo *)pPrevInfo, (const CNetObj_PlayerInfo *)pInfo, i ); else RenderPlayer( &PrevChar, &CurChar, (const CNetObj_PlayerInfo *)pPrevInfo, (const CNetObj_PlayerInfo *)pInfo, i ); } } } }
void CPlayers::OnRender() { // render other players in two passes, first pass we render the other, second pass we render our self for(int p = 0; p < 4; p++) { for(int i = 0; i < MAX_CLIENTS; i++) { // only render active characters if(!m_pClient->m_Snap.m_aCharacters[i].m_Active) continue; const void *pPrevInfo = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_PLAYERINFO, i); const void *pInfo = Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i); if(pPrevInfo && pInfo) { // bool Local = ((const CNetObj_PlayerInfo *)pInfo)->m_Local !=0; if((p % 2) == 0 && Local) continue; if((p % 2) == 1 && !Local) continue; CNetObj_Character PrevChar = m_pClient->m_Snap.m_aCharacters[i].m_Prev; CNetObj_Character CurChar = m_pClient->m_Snap.m_aCharacters[i].m_Cur; if(p<2) RenderHook( &PrevChar, &CurChar, (const CNetObj_PlayerInfo *)pPrevInfo, (const CNetObj_PlayerInfo *)pInfo ); else RenderPlayer( &PrevChar, &CurChar, (const CNetObj_PlayerInfo *)pPrevInfo, (const CNetObj_PlayerInfo *)pInfo ); } } } }
void CPlayers::OnRender() { // update RenderInfo for ninja bool IsTeamplay = false; if(m_pClient->m_Snap.m_pGameInfoObj) IsTeamplay = (m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS) != 0; for(int i = 0; i < MAX_CLIENTS; ++i) { int FriendState = m_pClient->Friends()->IsFriend(m_pClient->m_aClients[i].m_aName, m_pClient->m_aClients[i].m_aClan, true); bool HasNinja = m_pClient->m_Snap.m_aCharacters[i].m_Cur.m_Weapon == WEAPON_NINJA; m_aRenderInfo[i] = m_pClient->m_aClients[i].m_RenderInfo; if(HasNinja) { // change the skin for the player to the ninja int Skin = m_pClient->m_pSkins->Find("x_ninja"); if(Skin != -1) { if(IsTeamplay) m_aRenderInfo[i].m_Texture = m_pClient->m_pSkins->Get(Skin)->m_ColorTexture; else { m_aRenderInfo[i].m_Texture = m_pClient->m_pSkins->Get(Skin)->m_OrgTexture; m_aRenderInfo[i].m_ColorBody = vec4(1, 1, 1, 1); m_aRenderInfo[i].m_ColorFeet = vec4(1, 1, 1, 1); } } } if(g_Config.m_XFriendHighlight && FriendState == IFriends::CONTACT_FRIEND && !m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS) { int Skin = m_pClient->m_pSkins->Find(g_Config.m_XFriendSkin); if(Skin == -1) Skin = m_pClient->m_pSkins->Find("default"); if(HasNinja) Skin = m_pClient->m_pSkins->Find("x_ninja"); m_aRenderInfo[i].m_ColorBody = vec4(0.2f, 1.0f, 0.2f, 1.0f); m_aRenderInfo[i].m_ColorFeet = vec4(0.2f, 1.0f, 0.2f, 1.0f); } if(g_Config.m_XEnemyHighlight && FriendState == IFriends::CONTACT_ENEMY && !m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS) { int Skin = m_pClient->m_pSkins->Find(g_Config.m_XEnemySkin); if(Skin == -1) Skin = m_pClient->m_pSkins->Find("default"); if(HasNinja) Skin = m_pClient->m_pSkins->Find("x_ninja"); m_aRenderInfo[i].m_Texture = m_pClient->m_pSkins->Get(Skin)->m_ColorTexture; m_aRenderInfo[i].m_ColorBody = vec4(1.0f, 0.2f, 0.2f, 1.0f); m_aRenderInfo[i].m_ColorFeet = vec4(1.0f, 0.2f, 0.2f, 1.0f); } } // render other players in two passes, first pass we render the other, second pass we render our self for(int p = 0; p < 4; p++) { for(int i = 0; i < MAX_CLIENTS; i++) { // only render active characters if(!m_pClient->m_Snap.m_aCharacters[i].m_Active) continue; const void *pPrevInfo = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_PLAYERINFO, i); const void *pInfo = Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i); if(pPrevInfo && pInfo) { // bool Local = ((const CNetObj_PlayerInfo *)pInfo)->m_Local !=0; if((p % 2) == 0 && Local) continue; if((p % 2) == 1 && !Local) continue; CNetObj_Character PrevChar = m_pClient->m_Snap.m_aCharacters[i].m_Prev; CNetObj_Character CurChar = m_pClient->m_Snap.m_aCharacters[i].m_Cur; if(p<2) RenderHook( &PrevChar, &CurChar, (const CNetObj_PlayerInfo *)pPrevInfo, (const CNetObj_PlayerInfo *)pInfo ); else RenderPlayer( &PrevChar, &CurChar, (const CNetObj_PlayerInfo *)pPrevInfo, (const CNetObj_PlayerInfo *)pInfo ); } } } }
void VMobileForwardRenderLoop::OnDoRenderLoop(void *pUserData) { INSERT_PERF_MARKER_SCOPE("VMobileForwardRenderLoop::OnDoRenderLoop"); m_iFrameCounter++; // just for arbitrary custom purposes #ifdef WIN32 // vForge specific: if (Vision::RenderLoopHelper.GetReplacementRenderLoop()) { // render with this render-loop instead Vision::RenderLoopHelper.GetReplacementRenderLoop()->OnDoRenderLoop(pUserData); return; } #endif m_pShaderProvider = Vision::GetApplication()->GetShaderProvider(); VASSERT(m_pShaderProvider); m_pShaderProvider->ResetCache(); VisRenderContext_cl *pContext = VisRenderContext_cl::GetCurrentContext(); IVisVisibilityCollector_cl *pVisCollector = pContext->GetVisibilityCollector(); if (pVisCollector==NULL) return; const int iRenderFlags = pContext->GetRenderFlags(); m_pCameraFrustum = pVisCollector->GetBaseFrustum(); const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesPrimaryOpaquePass = pVisCollector->GetVisibleStaticGeometryInstancesForPass(VPT_PrimaryOpaquePass); const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesSecondaryOpaquePass = pVisCollector->GetVisibleStaticGeometryInstancesForPass(VPT_SecondaryOpaquePass); const VisStaticGeometryInstanceCollection_cl *pVisibleGeoInstancesTransparentPass = pVisCollector->GetVisibleStaticGeometryInstancesForPass(VPT_TransparentPass); const VisEntityCollection_cl *pVisibleEntitiesPrimaryOpaquePass = pVisCollector->GetVisibleEntitiesForPass(VPT_PrimaryOpaquePass); const VisEntityCollection_cl *pVisibleEntitiesSecondaryOpaquePass = pVisCollector->GetVisibleEntitiesForPass(VPT_SecondaryOpaquePass); const VisEntityCollection_cl *pVisibleEntitiesTransparentPass = pVisCollector->GetVisibleEntitiesForPass(VPT_TransparentPass); const VisEntityCollection_cl *pVisibleForeGroundEntities = pVisCollector->GetVisibleForeGroundEntities(); HandleVisibleVisibilityObjects(); // Clear the screen if ((iRenderFlags&VIS_RENDERCONTEXT_FLAG_NO_CLEARSCREEN)==0) { const VFogParameters &fog = Vision::World.GetFogParameters(); VColorRef clearColor = fog.depthMode != VFogParameters::Off ? fog.iDepthColor : Vision::Renderer.GetDefaultClearColor(); Vision::RenderLoopHelper.ClearScreen(VisRenderLoopHelper_cl::VCTF_All, clearColor); } m_bHasRenderHookCallbacks = m_bTriggerCallbacks && Vision::Callbacks.OnRenderHook.HasCallbacks(); // Get a pointer to the collection of visible mesh buffer objects const VisMeshBufferObjectCollection_cl *pVisibleMeshBuffer = &m_VisibilityObjectCollector.GetMeshBufferObjectCollection(); // Get a pointer to the collection of visible particle groups const VisParticleGroupCollection_cl *pVisibleParticleGroups = &m_VisibilityObjectCollector.GetParticleGroupCollection(); // Determine which lights have to rendered in the current frame DetermineRelevantLights(); // Render all mesh buffer objects with the render order flag "VRH_PRE_RENDERING". RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_RENDERING, m_bTriggerCallbacks); // Render all mesh buffer objects with the render order flag "VRH_PRE_PRIMARY_OPAQUE_PASS_GEOMETRY". RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_PRIMARY_OPAQUE_PASS_GEOMETRY, m_bTriggerCallbacks); // Reset tags VisStaticGeometryInstance_cl::ResetTags(); VisBaseEntity_cl::ResetTags(); // Clear temporary collections for geometry that is lit by base pass light, but rendered in additive lighting pass m_AdditiveLitGeoInstanceCollection.Clear(); m_AdditiveLitEntityCollection.Clear(); // Prepare the initial lighting pass (one light collapsed with base lighting contribution) bool bUsesLightClippingVolume = false; IVShadowMapComponent *pShadowMap = PrepareLightingPass(m_pBasePassLight, true, bUsesLightClippingVolume); // Render lit geometry before actual base pass, whereby the geometry which has been rendered here will be tagged, in order // to avoid re-rendering later on. We first render static meshes lit base the base pass light, then static meshes not lit by the base pass light, // and then entities (with/without base pass light, respectively). { RenderLitGeometry(m_pBasePassLight, pShadowMap, true, bUsesLightClippingVolume, false, true); // Render all primary opaque pass surface shaders on opaque world geometry Vision::RenderLoopHelper.RenderStaticGeometrySurfaceShaders(*pVisibleGeoInstancesPrimaryOpaquePass, VPT_PrimaryOpaquePass, VTF_IGNORE_TAGGED_ENTRIES); // Render all mesh buffer objects with the render order flag "VRH_PRE_PRIMARY_OPAQUE_PASS_ENTITIES". RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_PRIMARY_OPAQUE_PASS_ENTITIES, m_bTriggerCallbacks); RenderLitGeometry(m_pBasePassLight, pShadowMap, true, bUsesLightClippingVolume, true, false); // Render all primary opaque pass shaders on entities (see "DrawEntitiesShaders") DrawEntitiesShaders(*pVisibleEntitiesPrimaryOpaquePass, VPT_PrimaryOpaquePass, VTF_IGNORE_TAGGED_ENTRIES); } // Finalize the initial pass FinalizeLightingPass(m_pBasePassLight, bUsesLightClippingVolume); RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_SECONDARY_OPAQUE_PASS_GEOMETRY, m_bTriggerCallbacks); // Render static geometry instances for secondary opaque pass Vision::RenderLoopHelper.RenderStaticGeometrySurfaceShaders(*pVisibleGeoInstancesSecondaryOpaquePass, VPT_SecondaryOpaquePass, VTF_IGNORE_TAGGED_ENTRIES); RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_SECONDARY_OPAQUE_PASS_ENTITIES, m_bTriggerCallbacks); // Render entities for secondary opaque pass DrawEntitiesShaders(*pVisibleEntitiesSecondaryOpaquePass, VPT_SecondaryOpaquePass, VTF_IGNORE_TAGGED_ENTRIES); // Start the hardware occlusion query. Note that this function always has to be called in render loops. // Also, the position of this call in the OnDoRenderLoop is important: The zBuffer contents at this stage of rendering will // act as occluders in the hardware occlusion queries. Vision::RenderLoopHelper.PerformHardwareOcclusionQuery(); // Render sky Vision::RenderLoopHelper.RenderSky(); // Render all mesh buffer objects with the render order flag "VRH_PRE_OCCLUSION_TESTS". RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_OCCLUSION_TESTS, m_bTriggerCallbacks); Vision::RenderLoopHelper.PerformHardwarePixelCounterQuery(); // Render all mesh buffer objects with the render order flag "VRH_POST_OCCLUSION_TESTS". RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_POST_OCCLUSION_TESTS, m_bTriggerCallbacks); // Draw dynamic light DrawDynamicLight(); // Render all mesh buffer objects with the render order flag "VRH_PRE_TRANSPARENT_PASS_GEOMETRY". RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_TRANSPARENT_PASS_GEOMETRY, m_bTriggerCallbacks); // Render transparent pass surface shaders on translucent lit world primitives Vision::RenderLoopHelper.RenderStaticGeometrySurfaceShaders(*pVisibleGeoInstancesTransparentPass, VPT_TransparentPass, VTF_IGNORE_TAGGED_ENTRIES); RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PRE_TRANSPARENT_PASS_ENTITIES, m_bTriggerCallbacks); // Render transparent pass shaders on entities DrawEntitiesShaders(*pVisibleEntitiesTransparentPass, VPT_TransparentPass, VTF_IGNORE_TAGGED_ENTRIES); // Render all mesh buffer objects with the render order flag "VRH_POST_TRANSPARENT_PASS_GEOMETRY". RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_POST_TRANSPARENT_PASS_GEOMETRY, m_bTriggerCallbacks); // Render all mesh buffer objects and particle systems with the render order flag "VRH_DECALS". RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_DECALS, m_bTriggerCallbacks); // Render all mesh buffer objects and particle systems with the render order flag "VRH_PARTICLES". RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_PARTICLES, m_bTriggerCallbacks); // Render all mesh buffer objects with the render order flag "VRH_ADDITIVE_PARTICLES" RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_ADDITIVE_PARTICLES, m_bTriggerCallbacks); RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_TRANSLUCENT_VOLUMES, m_bTriggerCallbacks); // Render visible foreground entities (see DrawForegroundEntities) DrawForegroundEntities(*pVisibleForeGroundEntities); // Render all mesh buffer objects with the render order flag "VRH_CORONAS_AND_FLARES" RenderHook(*pVisibleMeshBuffer, pVisibleParticleGroups, VRH_CORONAS_AND_FLARES, m_bTriggerCallbacks); m_pShaderProvider = NULL; }
void CPlayers::OnRender() { // update RenderInfo for ninja bool IsTeamplay = false; if(m_pClient->m_Snap.m_pGameInfoObj) IsTeamplay = (m_pClient->m_Snap.m_pGameInfoObj->m_GameFlags&GAMEFLAG_TEAMS) != 0; for(int i = 0; i < MAX_CLIENTS; ++i) { m_aRenderInfo[i] = m_pClient->m_aClients[i].m_RenderInfo; if(m_pClient->m_Snap.m_aCharacters[i].m_Cur.m_Weapon == WEAPON_NINJA && g_Config.m_ClShowNinja) { // change the skin for the player to the ninja int Skin = m_pClient->m_pSkins->Find("x_ninja"); if(Skin != -1) { if(IsTeamplay) m_aRenderInfo[i].m_Texture = m_pClient->m_pSkins->Get(Skin)->m_ColorTexture; else { m_aRenderInfo[i].m_Texture = m_pClient->m_pSkins->Get(Skin)->m_OrgTexture; m_aRenderInfo[i].m_ColorBody = vec4(1,1,1,1); m_aRenderInfo[i].m_ColorFeet = vec4(1,1,1,1); } } } } static vec2 PrevPos[MAX_CLIENTS]; static vec2 SmoothPos[MAX_CLIENTS]; static int MoveCnt[MAX_CLIENTS] = {0}; static vec2 PredictedPos[MAX_CLIENTS]; static int predcnt = 0; if (g_Config.m_ClAntiPingPlayers) { for(int i = 0; i < MAX_CLIENTS; i++) { if(!m_pClient->m_Snap.m_aCharacters[i].m_Active) continue; const void *pPrevInfo = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_PLAYERINFO, i); const void *pInfo = Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i); if(pPrevInfo && pInfo) { CNetObj_Character PrevChar = m_pClient->m_Snap.m_aCharacters[i].m_Prev; CNetObj_Character CurChar = m_pClient->m_Snap.m_aCharacters[i].m_Cur; Predict( &PrevChar, &CurChar, (const CNetObj_PlayerInfo *)pPrevInfo, (const CNetObj_PlayerInfo *)pInfo, PrevPos[i], SmoothPos[i], MoveCnt[i], PredictedPos[i] ); } } if(g_Config.m_ClAntiPingPlayers && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) if(m_pClient->m_Snap.m_pLocalCharacter && !(m_pClient->m_Snap.m_pGameInfoObj && m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER)) { // double ping = m_pClient->m_Snap.m_pLocalInfo->m_Latency; // static double fps; // fps = mix(fps, (1. / Client()->RenderFrameTime()), 0.1); // int predmax = (fps * ping / 1000.); int predmax = 19; // if( 0 <= predmax && predmax <= 100) predcnt = (predcnt + 1) % predmax; // else // predcnt = (predcnt + 1) % 2; } } // render other players in two passes, first pass we render the other, second pass we render our self for(int p = 0; p < 4; p++) { for(int i = 0; i < MAX_CLIENTS; i++) { // only render active characters if(!m_pClient->m_Snap.m_aCharacters[i].m_Active) continue; const void *pPrevInfo = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_PLAYERINFO, i); const void *pInfo = Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i); if(pPrevInfo && pInfo) { // bool Local = ((const CNetObj_PlayerInfo *)pInfo)->m_Local !=0; if((p % 2) == 0 && Local) continue; if((p % 2) == 1 && !Local) continue; CNetObj_Character PrevChar = m_pClient->m_Snap.m_aCharacters[i].m_Prev; CNetObj_Character CurChar = m_pClient->m_Snap.m_aCharacters[i].m_Cur; if(p<2) { if(PrevChar.m_HookedPlayer != -1) RenderHook( &PrevChar, &CurChar, (const CNetObj_PlayerInfo *)pPrevInfo, (const CNetObj_PlayerInfo *)pInfo, PredictedPos[i], PredictedPos[PrevChar.m_HookedPlayer] ); else RenderHook( &PrevChar, &CurChar, (const CNetObj_PlayerInfo *)pPrevInfo, (const CNetObj_PlayerInfo *)pInfo, PredictedPos[i], PredictedPos[i] ); } else { RenderPlayer( &PrevChar, &CurChar, (const CNetObj_PlayerInfo *)pPrevInfo, (const CNetObj_PlayerInfo *)pInfo, PredictedPos[i] ); } } } } }
void CPlayers::OnRender() { // update RenderInfo for ninja bool IsTeamplay = (m_pClient->m_GameInfo.m_GameFlags&GAMEFLAG_TEAMS) != 0; for(int i = 0; i < MAX_CLIENTS; ++i) { m_aRenderInfo[i] = m_pClient->m_aClients[i].m_RenderInfo; if(m_pClient->m_Snap.m_aCharacters[i].m_Cur.m_Weapon == WEAPON_NINJA) { // change the skin for the player to the ninja int Skin = m_pClient->m_pSkins->Find("x_ninja", true); if(Skin != -1) { const CSkins::CSkin *pNinja = m_pClient->m_pSkins->Get(Skin); for(int p = 0; p < CSkins::NUM_SKINPARTS; p++) { if(IsTeamplay) { m_aRenderInfo[i].m_aTextures[p] = pNinja->m_apParts[p]->m_ColorTexture; int ColorVal = m_pClient->m_pSkins->GetTeamColor(true, pNinja->m_aPartColors[p], m_pClient->m_aClients[i].m_Team, p); m_aRenderInfo[i].m_aColors[p] = m_pClient->m_pSkins->GetColorV4(ColorVal, p==CSkins::SKINPART_TATTOO); } else if(pNinja->m_aUseCustomColors[p]) { m_aRenderInfo[i].m_aTextures[p] = pNinja->m_apParts[p]->m_ColorTexture; m_aRenderInfo[i].m_aColors[p] = m_pClient->m_pSkins->GetColorV4(pNinja->m_aPartColors[p], p==CSkins::SKINPART_TATTOO); } else { m_aRenderInfo[i].m_aTextures[p] = pNinja->m_apParts[p]->m_OrgTexture; m_aRenderInfo[i].m_aColors[p] = vec4(1.0f, 1.0f, 1.0f, 1.0f); } } } } } // render other players in two passes, first pass we render the other, second pass we render our self for(int p = 0; p < 4; p++) { for(int i = 0; i < MAX_CLIENTS; i++) { // only render active characters if(!m_pClient->m_Snap.m_aCharacters[i].m_Active) continue; const void *pPrevInfo = Client()->SnapFindItem(IClient::SNAP_PREV, NETOBJTYPE_PLAYERINFO, i); const void *pInfo = Client()->SnapFindItem(IClient::SNAP_CURRENT, NETOBJTYPE_PLAYERINFO, i); if(pPrevInfo && pInfo) { // bool Local = m_pClient->m_LocalClientID == i; if((p % 2) == 0 && Local) continue; if((p % 2) == 1 && !Local) continue; CNetObj_Character PrevChar = m_pClient->m_Snap.m_aCharacters[i].m_Prev; CNetObj_Character CurChar = m_pClient->m_Snap.m_aCharacters[i].m_Cur; if(p<2) RenderHook( &PrevChar, &CurChar, (const CNetObj_PlayerInfo *)pPrevInfo, (const CNetObj_PlayerInfo *)pInfo, i ); else RenderPlayer( &PrevChar, &CurChar, (const CNetObj_PlayerInfo *)pPrevInfo, (const CNetObj_PlayerInfo *)pInfo, i ); } } } }