void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) { // get positions float Curvature = 0; float Speed = 0; if(pCurrent->m_Type == WEAPON_GRENADE) { Curvature = m_pClient->m_Tuning.m_GrenadeCurvature; Speed = m_pClient->m_Tuning.m_GrenadeSpeed; } else if(pCurrent->m_Type == WEAPON_SHOTGUN) { Curvature = m_pClient->m_Tuning.m_ShotgunCurvature; Speed = m_pClient->m_Tuning.m_ShotgunSpeed; } else if(pCurrent->m_Type == WEAPON_GUN) { Curvature = m_pClient->m_Tuning.m_GunCurvature; Speed = m_pClient->m_Tuning.m_GunSpeed; } static float s_LastGameTickTime = Client()->GameTickTime(); if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) s_LastGameTickTime = Client()->GameTickTime(); float Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime; if(Ct < 0) return; // projectile havn't been shot yet vec2 StartPos(pCurrent->m_X, pCurrent->m_Y); vec2 StartVel(pCurrent->m_VelX/100.0f, pCurrent->m_VelY/100.0f); vec2 Pos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct); vec2 PrevPos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct-0.001f); Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[clamp(pCurrent->m_Type, 0, NUM_WEAPONS-1)].m_pSpriteProj); vec2 Vel = Pos-PrevPos; //vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), Client()->IntraGameTick()); // add particle for this projectile if(pCurrent->m_Type == WEAPON_GRENADE) { m_pClient->m_pEffects->SmokeTrail(Pos, Vel*-1); static float s_Time = 0.0f; static float s_LastLocalTime = Client()->LocalTime(); if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); if(!pInfo->m_Paused) s_Time += (Client()->LocalTime()-s_LastLocalTime)*pInfo->m_Speed; } else { if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) s_Time += Client()->LocalTime()-s_LastLocalTime; } Graphics()->QuadsSetRotation(s_Time*pi*2*2 + ItemID); s_LastLocalTime = Client()->LocalTime(); } else { m_pClient->m_pEffects->BulletTrail(Pos); if(length(Vel) > 0.00001f) Graphics()->QuadsSetRotation(GetAngle(Vel)); else Graphics()->QuadsSetRotation(0); } IGraphics::CQuadItem QuadItem(Pos.x, Pos.y, 32, 32); Graphics()->QuadsDraw(&QuadItem, 1); Graphics()->QuadsSetRotation(0); Graphics()->QuadsEnd(); }
void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) { // get positions float Curvature = 0; float Speed = 0; if(pCurrent->m_Type == WEAPON_GRENADE) { Curvature = m_pClient->m_Tuning.m_GrenadeCurvature; Speed = m_pClient->m_Tuning.m_GrenadeSpeed; } else if(pCurrent->m_Type == WEAPON_SHOTGUN) { Curvature = m_pClient->m_Tuning.m_ShotgunCurvature; Speed = m_pClient->m_Tuning.m_ShotgunSpeed; } else if(pCurrent->m_Type == WEAPON_GUN) { Curvature = m_pClient->m_Tuning.m_GunCurvature; Speed = m_pClient->m_Tuning.m_GunSpeed; } float Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(); if(Ct < 0) return; // projectile havn't been shot yet vec2 StartPos(pCurrent->m_X, pCurrent->m_Y); vec2 StartVel(pCurrent->m_VelX/100.0f, pCurrent->m_VelY/100.0f); vec2 Pos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct); vec2 PrevPos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct-0.001f); // Draw shadows of grenades bool LocalPlayerInGame = m_pClient->m_aClients[m_pClient->m_Snap.m_LocalClientID].m_Team != -1; int explode = 0; // explode detecting if(g_Config.m_AntiPing && g_Config.m_AntiPingGrenade && g_Config.m_AntiPingOnlyIfBigLatency && (g_Config.m_AntiPingLatency <= m_pClient->m_Snap.m_pLocalInfo->m_Latency) && pCurrent->m_Type == WEAPON_GRENADE && LocalPlayerInGame && !m_pClient->m_Snap.m_pGameobj->m_GameOver) { Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); // Calculate average prediction offset, because client_predtick() gets varial values :((( // Must be there is a normal way to realize it, but I'm too lazy to find it. if (m_pClient->m_Average_Prediction_Offset == -1) { int Offset = Client()->PredGameTick() - Client()->GameTick(); m_pClient->m_Prediction_Offset_Summ += Offset; m_pClient->m_Prediction_Offset_Count++; if (m_pClient->m_Prediction_Offset_Count >= 100) { m_pClient->m_Average_Prediction_Offset = round((float)m_pClient->m_Prediction_Offset_Summ / m_pClient->m_Prediction_Offset_Count); } } // Draw shadow only if grenade directed to local player (optionaly) int LocalCid = m_pClient->m_Snap.m_LocalClientID; CNetObj_CharacterCore& CurChar = m_pClient->m_Snap.m_aCharacters[LocalCid].m_Cur; CNetObj_CharacterCore& PrevChar = m_pClient->m_Snap.m_aCharacters[LocalCid].m_Prev; vec2 ServerPos = mix(vec2(PrevChar.m_X, PrevChar.m_Y), vec2(CurChar.m_X, CurChar.m_Y), Client()->IntraGameTick()); bool GrenadeIsDirectedToLocalPlayer = true; if (g_Config.m_AntiPingGrenadeSide) { float d1 = fabs(distance(Pos, ServerPos)); float d2 = fabs(distance(PrevPos, ServerPos)); bool GrenadeIsDirectedToLocalPlayer = d1 < d2; } // Detect explode int PredictedTick = Client()->PrevGameTick() + m_pClient->m_Average_Prediction_Offset; float PredictedCt = (PredictedTick - pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(); vec2 PredictedPos; vec2 PrevPredictedPos; if (g_Config.m_AntiPingGrenadeExpl) { // grenade explode on collisions float eps=g_Config.m_AntiPingGrenadeEps*0.0001f; for (int i=0; (Ct+i*eps<PredictedCt)&&!explode; i++) { PredictedPos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct+i*eps); PrevPredictedPos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct+(i-1)*eps); if (Collision()->IntersectLine(PrevPredictedPos, PredictedPos, &PredictedPos, 0)) explode=1; } // grenade explode if TimeSpan>GrenadeLifetime if (((PredictedTick-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED)>m_pClient->m_Tuning.m_GrenadeLifetime) explode=2; // Render explode if (explode==1) { m_pClient->m_pEffects->FakeExplosion(PredictedPos); } else if (explode==2) { float ExplodeCt=m_pClient->m_Tuning.m_GrenadeLifetime; PredictedPos = CalcPos(StartPos, StartVel, Curvature, Speed, ExplodeCt); m_pClient->m_pEffects->FakeExplosion(PredictedPos); } } if (m_pClient->m_Average_Prediction_Offset != -1 && GrenadeIsDirectedToLocalPlayer && !explode && PredictedCt >= 0) { PredictedPos = CalcPos(StartPos, StartVel, Curvature, Speed, PredictedCt); PrevPredictedPos = CalcPos(StartPos, StartVel, Curvature, Speed, PredictedCt-0.001f); int shadow_type = pCurrent->m_Type; Graphics()->SetColor(0, 1, 0, 0.75f); RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[clamp(shadow_type, 0, NUM_WEAPONS-1)].m_pSpriteProj); IGraphics::CQuadItem QuadItem(PredictedPos.x, PredictedPos.y, 28, 28); Graphics()->QuadsDraw(&QuadItem, 1); } Graphics()->QuadsSetRotation(0); Graphics()->QuadsEnd(); } if (!(g_Config.m_AntiPingShowGrenadeIfExplode || explode==0 || pCurrent->m_Type != WEAPON_GRENADE)) return; // draw original particle Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[clamp(pCurrent->m_Type, 0, NUM_WEAPONS-1)].m_pSpriteProj); vec2 Vel = Pos-PrevPos; //vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), Client()->IntraGameTick()); // add particle for this projectile if(pCurrent->m_Type == WEAPON_GRENADE) { m_pClient->m_pEffects->SmokeTrail(Pos, Vel*-1); m_pClient->m_pFlow->Add(Pos, Vel*1000*Client()->FrameTime(), 10.0f); if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); static float Time = 0; static float LastLocalTime = Client()->LocalTime(); if(!pInfo->m_Paused) Time += (Client()->LocalTime()-LastLocalTime)*pInfo->m_Speed; Graphics()->QuadsSetRotation(Time*pi*2*2 + ItemID); LastLocalTime = Client()->LocalTime(); } else Graphics()->QuadsSetRotation(Client()->LocalTime()*pi*2*2 + ItemID); } else { if(pCurrent->m_Type != WEAPON_SHOTGUN) m_pClient->m_pEffects->SgBulletTrail(Pos); else m_pClient->m_pEffects->BulletTrail(Pos); m_pClient->m_pFlow->Add(Pos, Vel*1000*Client()->FrameTime(), 10.0f); if(length(Vel) > 0.00001f) Graphics()->QuadsSetRotation(GetAngle(Vel)); else Graphics()->QuadsSetRotation(0); } IGraphics::CQuadItem QuadItem(Pos.x, Pos.y, 32, 32); Graphics()->QuadsDraw(&QuadItem, 1); Graphics()->QuadsSetRotation(0); Graphics()->QuadsEnd(); }
void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemId) { // get positions float Curvature = 0; float Speed = 0; if(pCurrent->m_Type == WEAPON_GRENADE) { Curvature = m_pClient->m_Tuning.m_GrenadeCurvature; Speed = m_pClient->m_Tuning.m_GrenadeSpeed; } else if(pCurrent->m_Type == WEAPON_SHOTGUN) { Curvature = m_pClient->m_Tuning.m_ShotgunCurvature; Speed = m_pClient->m_Tuning.m_ShotgunSpeed; } else if(pCurrent->m_Type == WEAPON_GUN) { Curvature = m_pClient->m_Tuning.m_GunCurvature; Speed = m_pClient->m_Tuning.m_GunSpeed; } float Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(); if(Ct < 0) return; // projectile havn't been shot yet vec2 StartPos(pCurrent->m_X, pCurrent->m_Y); vec2 StartVel(pCurrent->m_VelX/100.0f, pCurrent->m_VelY/100.0f); vec2 Pos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct); vec2 PrevPos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct-0.001f); Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[clamp(pCurrent->m_Type, 0, NUM_WEAPONS-1)].m_pSpriteProj); vec2 Vel = Pos-PrevPos; //vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), Client()->IntraGameTick()); // add particle for this projectile if(pCurrent->m_Type == WEAPON_GRENADE) { m_pClient->m_pEffects->SmokeTrail(Pos, Vel*-1); m_pClient->m_pFlow->Add(Pos, Vel*1000*Client()->FrameTime(), 10.0f); Graphics()->QuadsSetRotation(Client()->LocalTime()*pi*2*2 + ItemId); } else { m_pClient->m_pEffects->BulletTrail(Pos); m_pClient->m_pFlow->Add(Pos, Vel*1000*Client()->FrameTime(), 10.0f); if(length(Vel) > 0.00001f) Graphics()->QuadsSetRotation(GetAngle(Vel)); else Graphics()->QuadsSetRotation(0); } IGraphics::CQuadItem QuadItem(Pos.x, Pos.y, 32, 32); Graphics()->QuadsDraw(&QuadItem, 1); Graphics()->QuadsSetRotation(0); Graphics()->QuadsEnd(); }
void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) { // get positions float Curvature = 0; float Speed = 0; if(pCurrent->m_Type == WEAPON_GRENADE) { Curvature = m_pClient->m_Tuning.m_GrenadeCurvature; Speed = m_pClient->m_Tuning.m_GrenadeSpeed; } else if(pCurrent->m_Type == WEAPON_SHOTGUN) { Curvature = m_pClient->m_Tuning.m_ShotgunCurvature; Speed = m_pClient->m_Tuning.m_ShotgunSpeed; } else if(pCurrent->m_Type == WEAPON_GUN) { Curvature = m_pClient->m_Tuning.m_GunCurvature; Speed = m_pClient->m_Tuning.m_GunSpeed; } float Ct = (Client()->PrevGameTick()-pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(); if(Ct < 0) return; // projectile havn't been shot yet vec2 StartPos(pCurrent->m_X, pCurrent->m_Y); vec2 StartVel(pCurrent->m_VelX/100.0f, pCurrent->m_VelY/100.0f); vec2 Pos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct); vec2 PrevPos = CalcPos(StartPos, StartVel, Curvature, Speed, Ct-0.001f); Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); Graphics()->QuadsBegin(); RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[clamp(pCurrent->m_Type, 0, NUM_WEAPONS-1)].m_pSpriteProj); vec2 Vel = Pos-PrevPos; //vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), Client()->IntraGameTick()); // add particle for this projectile if(pCurrent->m_Type == WEAPON_GRENADE) { m_pClient->m_pEffects->SmokeTrail(Pos, Vel*-1); m_pClient->m_pFlow->Add(Pos, Vel*1000*Client()->FrameTime(), 10.0f); if(Client()->State() == IClient::STATE_DEMOPLAYBACK) { const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); static float Time = 0; static float LastLocalTime = Client()->LocalTime(); if(!pInfo->m_Paused) Time += (Client()->LocalTime()-LastLocalTime)*pInfo->m_Speed; Graphics()->QuadsSetRotation(Time*pi*2*2 + ItemID); LastLocalTime = Client()->LocalTime(); } else Graphics()->QuadsSetRotation(Client()->LocalTime()*pi*2*2 + ItemID); } else { m_pClient->m_pEffects->BulletTrail(Pos); m_pClient->m_pFlow->Add(Pos, Vel*1000*Client()->FrameTime(), 10.0f); if(length(Vel) > 0.00001f) Graphics()->QuadsSetRotation(GetAngle(Vel)); else Graphics()->QuadsSetRotation(0); } IGraphics::CQuadItem QuadItem(Pos.x, Pos.y, 32, 32); Graphics()->QuadsDraw(&QuadItem, 1); //--- Antiping // Draw shadows of grenades bool LocalPlayerInGame = m_pClient->m_aClients[m_pClient->m_Snap.m_LocalCid].m_Team != -1; if(g_Config.m_AntiPing && pCurrent->m_Type == WEAPON_GRENADE && LocalPlayerInGame) { // Calculate average prediction offset, because client_predtick() gets varial values :((( // Must be there is a normal way to realize it, but I'm too lazy to find it. ^) if (m_pClient->m_Average_Prediction_Offset == -1) { int Offset = Client()->PredGameTick() - Client()->GameTick(); m_pClient->m_Prediction_Offset_Summ += Offset; m_pClient->m_Prediction_Offset_Count++; if (m_pClient->m_Prediction_Offset_Count >= 100) { m_pClient->m_Average_Prediction_Offset = round((float)m_pClient->m_Prediction_Offset_Summ / m_pClient->m_Prediction_Offset_Count); } } // Draw shadow only if grenade directed to local player CNetObj_CharacterCore& CurChar = m_pClient->m_Snap.m_aCharacters[m_pClient->m_Snap.m_LocalCid].m_Cur; CNetObj_CharacterCore& PrevChar = m_pClient->m_Snap.m_aCharacters[m_pClient->m_Snap.m_LocalCid].m_Prev; vec2 ServerPos = mix(vec2(PrevChar.m_X, PrevChar.m_Y), vec2(CurChar.m_X, CurChar.m_Y), Client()->IntraGameTick()); float d1 = distance(Pos, ServerPos); float d2 = distance(PrevPos, ServerPos); if (d1 < 0) d1 *= -1; if (d2 < 0) d2 *= -1; bool GrenadeIsDirectedToLocalPlayer = d1 < d2; if (m_pClient->m_Average_Prediction_Offset != -1 && GrenadeIsDirectedToLocalPlayer) { int PredictedTick = Client()->PrevGameTick() + m_pClient->m_Average_Prediction_Offset; float PredictedCt = (PredictedTick - pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(); if (PredictedCt >= 0) { int shadow_type = WEAPON_GUN; // Pistol bullet sprite is used for marker of shadow. TODO: use something custom. RenderTools()->SelectSprite(g_pData->m_Weapons.m_aId[clamp(shadow_type, 0, NUM_WEAPONS-1)].m_pSpriteProj); vec2 PredictedPos = CalcPos(StartPos, StartVel, Curvature, Speed, PredictedCt); IGraphics::CQuadItem QuadItem(PredictedPos.x, PredictedPos.y, 32, 32); Graphics()->QuadsDraw(&QuadItem, 1); } } } //--- Graphics()->QuadsSetRotation(0); Graphics()->QuadsEnd(); }