diff --git a/src/base/tl/algorithm.h b/src/base/tl/algorithm.h index 27d0db387..a9136d28a 100644 --- a/src/base/tl/algorithm.h +++ b/src/base/tl/algorithm.h @@ -4,6 +4,7 @@ #define BASE_TL_ALGORITHM_H #include "base/tl/range.h" +#include /* @@ -134,4 +135,17 @@ bool sort_verify(R range) return true; } +template +void for_each(R range, std::function fcn) +{ + concept_empty::check(range); + concept_forwarditeration::check(range); + + for(; !range.empty(); range.pop_front()) + { + typename R::type *cur = &range.front(); + fcn(*cur); + } +} + #endif // TL_FILE_ALGORITHMS_HPP diff --git a/src/engine/client.h b/src/engine/client.h index a71b95c33..1a4edd897 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -7,7 +7,6 @@ #include "message.h" #include "graphics.h" #include -#include enum { @@ -78,12 +77,12 @@ public: inline int State() const { return m_State; } // tick time access - inline int PrevGameTick() const { return m_PrevGameTick[g_Config.m_ClDummy]; } - inline int GameTick() const { return m_CurGameTick[g_Config.m_ClDummy]; } - inline int PredGameTick() const { return m_PredTick[g_Config.m_ClDummy]; } - inline float IntraGameTick() const { return m_GameIntraTick[g_Config.m_ClDummy]; } - inline float PredIntraGameTick() const { return m_PredIntraTick[g_Config.m_ClDummy]; } - inline float GameTickTime() const { return m_GameTickTime[g_Config.m_ClDummy]; } + inline int PrevGameTick(int Dummy) const { return m_PrevGameTick[Dummy]; } + inline int GameTick(int Dummy) const { return m_CurGameTick[Dummy]; } + inline int PredGameTick(int Dummy) const { return m_PredTick[Dummy]; } + inline float IntraGameTick(int Dummy) const { return m_GameIntraTick[Dummy]; } + inline float PredIntraGameTick(int Dummy) const { return m_PredIntraTick[Dummy]; } + inline float GameTickTime(int Dummy) const { return m_GameTickTime[Dummy]; } inline int GameTickSpeed() const { return m_GameTickSpeed; } // other time access diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 0f4c7e2b6..6f7e1c615 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -781,12 +781,12 @@ bool CClient::DummyConnected() bool CClient::DummyConnecting() { - return !m_DummyConnected && m_LastDummyConnectTime > 0 && m_LastDummyConnectTime + GameTickSpeed() * 5 > GameTick(); + return !m_DummyConnected && m_LastDummyConnectTime > 0 && m_LastDummyConnectTime + GameTickSpeed() * 5 > GameTick(g_Config.m_ClDummy); } void CClient::DummyConnect() { - if(m_LastDummyConnectTime > 0 && m_LastDummyConnectTime + GameTickSpeed() * 5 > GameTick()) + if(m_LastDummyConnectTime > 0 && m_LastDummyConnectTime + GameTickSpeed() * 5 > GameTick(g_Config.m_ClDummy)) return; if(m_NetClient[CLIENT_MAIN].State() != NET_CONNSTATE_ONLINE && m_NetClient[CLIENT_MAIN].State() != NET_CONNSTATE_PENDING) @@ -795,7 +795,7 @@ void CClient::DummyConnect() if(m_DummyConnected) return; - m_LastDummyConnectTime = GameTick(); + m_LastDummyConnectTime = GameTick(g_Config.m_ClDummy); m_RconAuthed[1] = 0; @@ -824,7 +824,7 @@ int CClient::GetCurrentRaceTime() { if(GameClient()->GetLastRaceTick() < 0) return 0; - return (GameTick() - GameClient()->GetLastRaceTick()) / 50; + return (GameTick(g_Config.m_ClDummy) - GameClient()->GetLastRaceTick()) / 50; } int CClient::SendMsgY(CMsgPacker *pMsg, int Flags, int NetClient) @@ -3443,7 +3443,7 @@ void CClient::SaveReplay(const int Length) char *pSrc = (&m_DemoRecorder[RECORDER_REPLAYS])->GetCurrentFilename(); // Slice the demo to get only the last cl_replay_length seconds - const int EndTick = GameTick(); + const int EndTick = GameTick(g_Config.m_ClDummy); const int StartTick = EndTick - Length * GameTickSpeed(); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "replay", "Saving replay..."); diff --git a/src/game/client/components/broadcast.cpp b/src/game/client/components/broadcast.cpp index 8b33994b7..7e923f03c 100644 --- a/src/game/client/components/broadcast.cpp +++ b/src/game/client/components/broadcast.cpp @@ -25,7 +25,7 @@ void CBroadcast::OnRender() Graphics()->MapScreen(0, 0, 300*Graphics()->ScreenAspect(), 300); - if(Client()->GameTick() < m_BroadcastTick) + if(Client()->GameTick(g_Config.m_ClDummy) < m_BroadcastTick) { CTextCursor Cursor; TextRender()->SetCursor(&Cursor, m_BroadcastRenderOffset, 40.0f, 12.0f, TEXTFLAG_RENDER|TEXTFLAG_STOP_AT_END); @@ -45,7 +45,7 @@ void CBroadcast::OnMessage(int MsgType, void *pRawMsg) Cursor.m_LineWidth = 300*Graphics()->ScreenAspect(); TextRender()->TextEx(&Cursor, m_aBroadcastText, -1); m_BroadcastRenderOffset = 150*Graphics()->ScreenAspect()-Cursor.m_X/2; - m_BroadcastTick = Client()->GameTick()+Client()->GameTickSpeed()*10; + m_BroadcastTick = Client()->GameTick(g_Config.m_ClDummy)+Client()->GameTickSpeed()*10; if (g_Config.m_ClPrintBroadcasts) { char aBuf[1024]; diff --git a/src/game/client/components/ghost.cpp b/src/game/client/components/ghost.cpp index 738bf769a..2c4595853 100644 --- a/src/game/client/components/ghost.cpp +++ b/src/game/client/components/ghost.cpp @@ -175,7 +175,7 @@ void CGhost::CheckStart() int RaceTick = -m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer; int RenderTick = m_NewRenderTick; - if(m_LastRaceTick != RaceTick && Client()->GameTick() - RaceTick < Client()->GameTickSpeed()) + if(m_LastRaceTick != RaceTick && Client()->GameTick(g_Config.m_ClDummy) - RaceTick < Client()->GameTickSpeed()) { if(m_Rendering && m_RenderingStartedByServer) // race restarted: stop rendering StopRender(); @@ -208,7 +208,7 @@ void CGhost::CheckStartLocal(bool Predicted) { if(m_Rendering && !m_RenderingStartedByServer) // race restarted: stop rendering StopRender(); - RenderTick = Client()->PredGameTick(); + RenderTick = Client()->PredGameTick(g_Config.m_ClDummy); } TryRenderStart(RenderTick, false); @@ -303,7 +303,7 @@ void CGhost::OnRender() if(!m_Rendering || !g_Config.m_ClRaceShowGhost) return; - int PlaybackTick = Client()->PredGameTick() - m_StartRenderTick; + int PlaybackTick = Client()->PredGameTick(g_Config.m_ClDummy) - m_StartRenderTick; for(int i = 0; i < MAX_ACTIVE_GHOSTS; i++) { @@ -335,9 +335,9 @@ void CGhost::OnRender() int TickDiff = Player.m_Tick - Prev.m_Tick; float IntraTick = 0.f; if(TickDiff > 0) - IntraTick = (GhostTick - Prev.m_Tick - 1 + Client()->PredIntraGameTick()) / TickDiff; + IntraTick = (GhostTick - Prev.m_Tick - 1 + Client()->PredIntraGameTick(g_Config.m_ClDummy)) / TickDiff; - Player.m_AttackTick += Client()->GameTick() - GhostTick; + Player.m_AttackTick += Client()->GameTick(g_Config.m_ClDummy) - GhostTick; m_pClient->m_pPlayers->RenderHook(&Prev, &Player, &pGhost->m_RenderInfo , -2, IntraTick); m_pClient->m_pPlayers->RenderPlayer(&Prev, &Player, &pGhost->m_RenderInfo, -2, IntraTick); @@ -562,7 +562,7 @@ void CGhost::SaveGhost(CMenus::CGhostItem *pItem) void CGhost::ConGPlay(IConsole::IResult *pResult, void *pUserData) { CGhost *pGhost = (CGhost *)pUserData; - pGhost->StartRender(pGhost->Client()->PredGameTick()); + pGhost->StartRender(pGhost->Client()->PredGameTick(g_Config.m_ClDummy)); } void CGhost::OnConsoleInit() @@ -584,7 +584,7 @@ void CGhost::OnMessage(int MsgType, void *pRawMsg) if(m_Recording) StopRecord(); StopRender(); - m_LastDeathTick = Client()->GameTick(); + m_LastDeathTick = Client()->GameTick(g_Config.m_ClDummy); } } else if(MsgType == NETMSGTYPE_SV_CHAT) diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index 32211a572..005626891 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -109,7 +109,7 @@ void CHud::RenderGameTimer() int Time = 0; if(m_pClient->m_Snap.m_pGameInfoObj->m_TimeLimit && (m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer <= 0)) { - Time = m_pClient->m_Snap.m_pGameInfoObj->m_TimeLimit*60 - ((Client()->GameTick()-m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick)/Client()->GameTickSpeed()); + Time = m_pClient->m_Snap.m_pGameInfoObj->m_TimeLimit*60 - ((Client()->GameTick(g_Config.m_ClDummy)-m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick)/Client()->GameTickSpeed()); if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER) Time = 0; @@ -117,10 +117,10 @@ void CHud::RenderGameTimer() else if(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_RACETIME) { //The Warmup timer is negative in this case to make sure that incompatible clients will not see a warmup timer - Time = (Client()->GameTick()+m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer)/Client()->GameTickSpeed(); + Time = (Client()->GameTick(g_Config.m_ClDummy)+m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer)/Client()->GameTickSpeed(); } else - Time = (Client()->GameTick()-m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick)/Client()->GameTickSpeed(); + Time = (Client()->GameTick(g_Config.m_ClDummy)-m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick)/Client()->GameTickSpeed(); if(Time <= 0 && g_Config.m_ClShowDecisecs) str_format(aBuf, sizeof(aBuf), "00:00.0"); @@ -251,8 +251,8 @@ void CHud::RenderScoreHud() if(GameFlags&GAMEFLAG_FLAGS) { int BlinkTimer = (m_pClient->m_FlagDropTick[t] != 0 && - (Client()->GameTick()-m_pClient->m_FlagDropTick[t])/Client()->GameTickSpeed() >= 25) ? 10 : 20; - if(FlagCarrier[t] == FLAG_ATSTAND || (FlagCarrier[t] == FLAG_TAKEN && ((Client()->GameTick()/BlinkTimer)&1))) + (Client()->GameTick(g_Config.m_ClDummy)-m_pClient->m_FlagDropTick[t])/Client()->GameTickSpeed() >= 25) ? 10 : 20; + if(FlagCarrier[t] == FLAG_ATSTAND || (FlagCarrier[t] == FLAG_TAKEN && ((Client()->GameTick(g_Config.m_ClDummy)/BlinkTimer)&1))) { // draw flag Graphics()->TextureSet(g_pData->m_aImages[IMAGE_GAME].m_Id); @@ -809,10 +809,10 @@ void CHud::OnRender() static int LastChangeTick = 0; - if (LastChangeTick != Client()->PredGameTick()) + if (LastChangeTick != Client()->PredGameTick(g_Config.m_ClDummy)) { m_DDRaceTick += 100 / Client()->GameTickSpeed(); - LastChangeTick = Client()->PredGameTick(); + LastChangeTick = Client()->PredGameTick(g_Config.m_ClDummy); } if (m_DDRaceTick >= 100) @@ -830,14 +830,14 @@ void CHud::OnMessage(int MsgType, void *pRawMsg) m_DDRaceTime = pMsg->m_Time; m_DDRaceTick = 0; - m_LastReceivedTimeTick = Client()->GameTick(); + m_LastReceivedTimeTick = Client()->GameTick(g_Config.m_ClDummy); m_FinishTime = pMsg->m_Finish ? true : false; if(pMsg->m_Check) { m_CheckpointDiff = (float)pMsg->m_Check/100; - m_CheckpointTick = Client()->GameTick(); + m_CheckpointTick = Client()->GameTick(g_Config.m_ClDummy); } } else if(MsgType == NETMSGTYPE_SV_KILLMSG) @@ -861,12 +861,12 @@ void CHud::OnMessage(int MsgType, void *pRawMsg) m_DDRaceTime = pMsg->m_ServerTimeBest; // First value: m_Time m_DDRaceTick = 0; - m_LastReceivedTimeTick = Client()->GameTick(); + m_LastReceivedTimeTick = Client()->GameTick(g_Config.m_ClDummy); if(pMsg->m_PlayerTimeBest) // Second value: m_Check { m_CheckpointDiff = (float)pMsg->m_PlayerTimeBest/100; - m_CheckpointTick = Client()->GameTick(); + m_CheckpointTick = Client()->GameTick(g_Config.m_ClDummy); } } else if(GameClient()->m_GameInfo.m_RaceRecordMessage) @@ -880,7 +880,7 @@ void CHud::OnMessage(int MsgType, void *pRawMsg) void CHud::RenderDDRaceEffects() { // check racestate - if(m_FinishTime && m_LastReceivedTimeTick + Client()->GameTickSpeed()*2 < Client()->GameTick()) + if(m_FinishTime && m_LastReceivedTimeTick + Client()->GameTickSpeed()*2 < Client()->GameTick(g_Config.m_ClDummy)) { m_FinishTime = false; m_DDRaceTimeReceived = false; @@ -895,16 +895,16 @@ void CHud::RenderDDRaceEffects() str_format(aBuf, sizeof(aBuf), "Finish time: %02d:%02d.%02d", m_DDRaceTime/6000, m_DDRaceTime/100-m_DDRaceTime/6000 * 60, m_DDRaceTime % 100); TextRender()->Text(0, 150*Graphics()->ScreenAspect()-TextRender()->TextWidth(0,12,aBuf,-1)/2, 20, 12, aBuf, -1); } - else if(m_CheckpointTick + Client()->GameTickSpeed()*6 > Client()->GameTick()) + else if(m_CheckpointTick + Client()->GameTickSpeed()*6 > Client()->GameTick(g_Config.m_ClDummy)) { str_format(aBuf, sizeof(aBuf), "%+5.2f", m_CheckpointDiff); // calculate alpha (4 sec 1 than get lower the next 2 sec) float a = 1.0f; - if(m_CheckpointTick+Client()->GameTickSpeed()*4 < Client()->GameTick() && m_CheckpointTick+Client()->GameTickSpeed()*6 > Client()->GameTick()) + if(m_CheckpointTick+Client()->GameTickSpeed()*4 < Client()->GameTick(g_Config.m_ClDummy) && m_CheckpointTick+Client()->GameTickSpeed()*6 > Client()->GameTick(g_Config.m_ClDummy)) { // lower the alpha slowly to blend text out - a = ((float)(m_CheckpointTick+Client()->GameTickSpeed()*6) - (float)Client()->GameTick()) / (float)(Client()->GameTickSpeed()*2); + a = ((float)(m_CheckpointTick+Client()->GameTickSpeed()*6) - (float)Client()->GameTick(g_Config.m_ClDummy)) / (float)(Client()->GameTickSpeed()*2); } if(m_CheckpointDiff > 0) diff --git a/src/game/client/components/items.cpp b/src/game/client/components/items.cpp index 4cfd435b3..7a5a448da 100644 --- a/src/game/client/components/items.cpp +++ b/src/game/client/components/items.cpp @@ -47,15 +47,15 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) if(m_pClient->m_Snap.m_pLocalInfo) LocalPlayerInGame = m_pClient->m_aClients[m_pClient->m_Snap.m_pLocalInfo->m_ClientID].m_Team != -1; - static float s_LastGameTickTime = Client()->GameTickTime(); + static float s_LastGameTickTime = Client()->GameTickTime(g_Config.m_ClDummy); if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) - s_LastGameTickTime = Client()->GameTickTime(); + s_LastGameTickTime = Client()->GameTickTime(g_Config.m_ClDummy); float Ct; if(m_pClient->Predict() && m_pClient->AntiPingGrenade() && LocalPlayerInGame && !(Client()->State() == IClient::STATE_DEMOPLAYBACK)) - Ct = ((float)(Client()->PredGameTick() - 1 - pCurrent->m_StartTick) + Client()->PredIntraGameTick())/(float)SERVER_TICK_SPEED; + Ct = ((float)(Client()->PredGameTick(g_Config.m_ClDummy) - 1 - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy))/(float)SERVER_TICK_SPEED; else - Ct = (Client()->PrevGameTick() - pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime; + Ct = (Client()->PrevGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + s_LastGameTickTime; if(Ct < 0) return; // projectile haven't been shot yet @@ -82,7 +82,7 @@ void CItems::RenderProjectile(const CNetObj_Projectile *pCurrent, int ItemID) int QuadOffset = 2 + 4 + NUM_WEAPONS + clamp(pCurrent->m_Type, 0, NUM_WEAPONS - 1); vec2 Vel = Pos-PrevPos; - //vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), Client()->IntraGameTick()); + //vec2 pos = mix(vec2(prev->x, prev->y), vec2(current->x, current->y), Client()->IntraGameTick(g_Config.m_ClDummy)); // add particle for this projectile if(pCurrent->m_Type == WEAPON_GRENADE) @@ -128,7 +128,7 @@ void CItems::RenderPickup(const CNetObj_Pickup *pPrev, const CNetObj_Pickup *pCu int QuadOffset = 2; - float IntraTick = IsPredicted ? Client()->PredIntraGameTick() : Client()->IntraGameTick(); + float IntraTick = IsPredicted ? Client()->PredIntraGameTick(g_Config.m_ClDummy) : Client()->IntraGameTick(g_Config.m_ClDummy); vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCurrent->m_X, pCurrent->m_Y), IntraTick); float Angle = 0.0f; if(pCurrent->m_Type == POWERUP_WEAPON) @@ -191,7 +191,7 @@ void CItems::RenderFlag(const CNetObj_Flag *pPrev, const CNetObj_Flag *pCurrent, Graphics()->QuadsSetRotation(Angle); - vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCurrent->m_X, pCurrent->m_Y), Client()->IntraGameTick()); + vec2 Pos = mix(vec2(pPrev->m_X, pPrev->m_Y), vec2(pCurrent->m_X, pCurrent->m_Y), Client()->IntraGameTick(g_Config.m_ClDummy)); if(pCurGameData) { @@ -220,9 +220,9 @@ void CItems::RenderLaser(const struct CNetObj_Laser *pCurrent, bool IsPredicted) float Ticks; if(IsPredicted) - Ticks = (float)(Client()->PredGameTick() - pCurrent->m_StartTick) + Client()->PredIntraGameTick(); + Ticks = (float)(Client()->PredGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy); else - Ticks = (float)(Client()->GameTick() - pCurrent->m_StartTick) + Client()->IntraGameTick(); + Ticks = (float)(Client()->GameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->IntraGameTick(g_Config.m_ClDummy); float Ms = (Ticks/50.0f) * 1000.0f; float a = Ms / m_pClient->m_Tuning[g_Config.m_ClDummy].m_LaserBounceDelay; a = clamp(a, 0.0f, 1.0f); @@ -263,10 +263,10 @@ void CItems::RenderLaser(const struct CNetObj_Laser *pCurrent, bool IsPredicted) // render head { - int QuadOffset = 2 + 4 + NUM_WEAPONS * 2 + (Client()->GameTick() % 3); + int QuadOffset = 2 + 4 + NUM_WEAPONS * 2 + (Client()->GameTick(g_Config.m_ClDummy) % 3); Graphics()->TextureSet(g_pData->m_aImages[IMAGE_PARTICLES].m_Id); - Graphics()->QuadsSetRotation(Client()->GameTick()); + Graphics()->QuadsSetRotation(Client()->GameTick(g_Config.m_ClDummy)); Graphics()->SetColor(OuterColor.r, OuterColor.g, OuterColor.b, 1.0f); Graphics()->RenderQuadContainerAsSprite(m_ItemsQuadContainerIndex, QuadOffset, Pos.x, Pos.y); Graphics()->SetColor(InnerColor.r, InnerColor.g, InnerColor.b, 1.0f); @@ -331,7 +331,7 @@ void CItems::OnRender() { ReconstructSmokeTrail((const CNetObj_Projectile *)pData, Item.m_ID, pProj->m_DestroyTick, pProj->m_LifeSpan); } - pProj->m_LastRenderTick = Client()->GameTick(); + pProj->m_LastRenderTick = Client()->GameTick(g_Config.m_ClDummy); continue; } } @@ -378,7 +378,7 @@ void CItems::OnRender() // render extra projectiles for(int i = 0; i < m_NumExtraProjectiles; i++) { - if(m_aExtraProjectiles[i].m_StartTick < Client()->GameTick()) + if(m_aExtraProjectiles[i].m_StartTick < Client()->GameTick(g_Config.m_ClDummy)) { m_aExtraProjectiles[i] = m_aExtraProjectiles[m_NumExtraProjectiles-1]; m_NumExtraProjectiles--; @@ -450,7 +450,7 @@ void CItems::ReconstructSmokeTrail(const CNetObj_Projectile *pCurrent, int ItemI LocalPlayerInGame = m_pClient->m_aClients[m_pClient->m_Snap.m_pLocalInfo->m_ClientID].m_Team != -1; if(!m_pClient->AntiPingGunfire() || !LocalPlayerInGame) return; - if(Client()->PredGameTick() == pCurrent->m_StartTick) + if(Client()->PredGameTick(g_Config.m_ClDummy) == pCurrent->m_StartTick) return; // get positions @@ -472,11 +472,11 @@ void CItems::ReconstructSmokeTrail(const CNetObj_Projectile *pCurrent, int ItemI Speed = m_pClient->m_Tuning[g_Config.m_ClDummy].m_GunSpeed; } - float Pt = ((float)(Client()->PredGameTick() - pCurrent->m_StartTick) + Client()->PredIntraGameTick())/(float)SERVER_TICK_SPEED; + float Pt = ((float)(Client()->PredGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy))/(float)SERVER_TICK_SPEED; if(Pt < 0) return; // projectile haven't been shot yet - float Gt = (Client()->PrevGameTick() - pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(); + float Gt = (Client()->PrevGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick)/(float)SERVER_TICK_SPEED + Client()->GameTickTime(g_Config.m_ClDummy); vec2 StartPos; vec2 StartVel; @@ -494,7 +494,7 @@ void CItems::ReconstructSmokeTrail(const CNetObj_Projectile *pCurrent, int ItemI float T = Pt; if(DestroyTick >= 0) - T = minimum(Pt, ((float)(DestroyTick - 1 - pCurrent->m_StartTick) + Client()->PredIntraGameTick())/(float)SERVER_TICK_SPEED); + T = minimum(Pt, ((float)(DestroyTick - 1 - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy))/(float)SERVER_TICK_SPEED); T = minimum(T, LifeSpan/(float)SERVER_TICK_SPEED); float MinTrailSpan = 0.4f * ((pCurrent->m_Type == WEAPON_GRENADE) ? 0.5f : 0.25f); diff --git a/src/game/client/components/killmessages.cpp b/src/game/client/components/killmessages.cpp index 9f4459276..b4ceaec57 100644 --- a/src/game/client/components/killmessages.cpp +++ b/src/game/client/components/killmessages.cpp @@ -83,7 +83,7 @@ void CKillMessages::OnMessage(int MsgType, void *pRawMsg) Kill.m_Weapon = pMsg->m_Weapon; Kill.m_ModeSpecial = pMsg->m_ModeSpecial; - Kill.m_Tick = Client()->GameTick(); + Kill.m_Tick = Client()->GameTick(g_Config.m_ClDummy); Kill.m_FlagCarrierBlue = m_pClient->m_Snap.m_pGameDataObj ? m_pClient->m_Snap.m_pGameDataObj->m_FlagCarrierBlue : -1; @@ -153,7 +153,7 @@ void CKillMessages::OnRender() for(int i = 1; i <= MAX_KILLMSGS; i++) { int r = (m_KillmsgCurrent+i)%MAX_KILLMSGS; - if(Client()->GameTick() > m_aKillmsgs[r].m_Tick+50*10) + if(Client()->GameTick(g_Config.m_ClDummy) > m_aKillmsgs[r].m_Tick+50*10) continue; float x = StartX; diff --git a/src/game/client/components/maplayers.cpp b/src/game/client/components/maplayers.cpp index 4d9a8c411..89d8f611f 100644 --- a/src/game/client/components/maplayers.cpp +++ b/src/game/client/components/maplayers.cpp @@ -94,15 +94,15 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void } if(pItem->m_Version < 2 || pItem->m_Synchronized) { - s_Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), - (pThis->Client()->GameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), - pThis->Client()->IntraGameTick()); + s_Time = mix((pThis->Client()->PrevGameTick(g_Config.m_ClDummy)-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), + (pThis->Client()->GameTick(g_Config.m_ClDummy)-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), + pThis->Client()->IntraGameTick(g_Config.m_ClDummy)); } else { s_Time = mix(pThis->m_LastLocalTick / (float)pThis->Client()->GameTickSpeed(), pThis->m_CurrentLocalTick / (float)pThis->Client()->GameTickSpeed(), - pThis->Client()->IntraGameTick()); + pThis->Client()->IntraGameTick(g_Config.m_ClDummy)); } } pThis->RenderTools()->RenderEvalEnvelope(pPoints+pItem->m_StartPoint, pItem->m_NumPoints, 4, s_Time+TimeOffset, pChannels); @@ -113,9 +113,9 @@ void CMapLayers::EnvelopeEval(float TimeOffset, int Env, float *pChannels, void { if(pItem->m_Version < 2 || pItem->m_Synchronized) { - s_Time = mix((pThis->Client()->PrevGameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), - (pThis->Client()->GameTick()-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), - pThis->Client()->IntraGameTick()); + s_Time = mix((pThis->Client()->PrevGameTick(g_Config.m_ClDummy)-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), + (pThis->Client()->GameTick(g_Config.m_ClDummy)-pThis->m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)pThis->Client()->GameTickSpeed(), + pThis->Client()->IntraGameTick(g_Config.m_ClDummy)); } else s_Time += pThis->LocalTime()-s_LastLocalTime; diff --git a/src/game/client/components/mapsounds.cpp b/src/game/client/components/mapsounds.cpp index ad6a3997e..e684f684a 100644 --- a/src/game/client/components/mapsounds.cpp +++ b/src/game/client/components/mapsounds.cpp @@ -103,9 +103,9 @@ void CMapSounds::OnRender() static float s_Time = 0.0f; if(m_pClient->m_Snap.m_pGameInfoObj) // && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) { - s_Time = mix((Client()->PrevGameTick()-m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)Client()->GameTickSpeed(), - (Client()->GameTick()-m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)Client()->GameTickSpeed(), - Client()->IntraGameTick()); + s_Time = mix((Client()->PrevGameTick(g_Config.m_ClDummy)-m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)Client()->GameTickSpeed(), + (Client()->GameTick(g_Config.m_ClDummy)-m_pClient->m_Snap.m_pGameInfoObj->m_RoundStartTick) / (float)Client()->GameTickSpeed(), + Client()->IntraGameTick(g_Config.m_ClDummy)); } float Offset = s_Time-pSource->m_pSource->m_TimeDelay; if(Offset >= 0.0f && g_Config.m_SndEnable && (g_Config.m_GfxHighDetail || !pSource->m_HighDetail)) diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 4de14c38f..3540227aa 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -8,6 +8,7 @@ #include #include +#include #include #include diff --git a/src/game/client/components/nameplates.cpp b/src/game/client/components/nameplates.cpp index 0908671ed..b6e0d990d 100644 --- a/src/game/client/components/nameplates.cpp +++ b/src/game/client/components/nameplates.cpp @@ -33,7 +33,7 @@ void CNamePlates::RenderNameplate( if(ClientID >= 0 && ClientID < MAX_CLIENTS) Position = m_pClient->m_aClients[ClientID].m_RenderPos; else - Position = mix(vec2(pPrevChar->m_X, pPrevChar->m_Y), vec2(pPlayerChar->m_X, pPlayerChar->m_Y), Client()->IntraGameTick()); + Position = mix(vec2(pPrevChar->m_X, pPrevChar->m_Y), vec2(pPlayerChar->m_X, pPlayerChar->m_Y), Client()->IntraGameTick(g_Config.m_ClDummy)); bool OtherTeam = m_pClient->IsOtherTeam(ClientID); diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index 3807004a3..7f35502f9 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -97,7 +97,7 @@ void CPlayers::RenderHook( float IntraTick = Intra; if(ClientID >= 0) - IntraTick = (m_pClient->m_aClients[ClientID].m_IsPredicted) ? Client()->PredIntraGameTick() : Client()->IntraGameTick(); + IntraTick = (m_pClient->m_aClients[ClientID].m_IsPredicted) ? Client()->PredIntraGameTick(g_Config.m_ClDummy) : Client()->IntraGameTick(g_Config.m_ClDummy); bool OtherTeam = m_pClient->IsOtherTeam(ClientID); @@ -183,24 +183,24 @@ void CPlayers::RenderPlayer( float IntraTick = Intra; if(ClientID >= 0) - IntraTick = m_pClient->m_aClients[ClientID].m_IsPredicted ? Client()->PredIntraGameTick() : Client()->IntraGameTick(); + IntraTick = m_pClient->m_aClients[ClientID].m_IsPredicted ? Client()->PredIntraGameTick(g_Config.m_ClDummy) : Client()->IntraGameTick(g_Config.m_ClDummy); - static float s_LastGameTickTime = Client()->GameTickTime(); - static float s_LastPredIntraTick = Client()->PredIntraGameTick(); + static float s_LastGameTickTime = Client()->GameTickTime(g_Config.m_ClDummy); + static float s_LastPredIntraTick = Client()->PredIntraGameTick(g_Config.m_ClDummy); if(m_pClient->m_Snap.m_pGameInfoObj && !(m_pClient->m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_PAUSED)) { - s_LastGameTickTime = Client()->GameTickTime(); - s_LastPredIntraTick = Client()->PredIntraGameTick(); + s_LastGameTickTime = Client()->GameTickTime(g_Config.m_ClDummy); + s_LastPredIntraTick = Client()->PredIntraGameTick(g_Config.m_ClDummy); } bool PredictLocalWeapons = false; - float AttackTime = (Client()->PrevGameTick() - Player.m_AttackTick) / (float)SERVER_TICK_SPEED + Client()->GameTickTime(); - float LastAttackTime = (Client()->PrevGameTick() - Player.m_AttackTick) / (float)SERVER_TICK_SPEED + s_LastGameTickTime; + float AttackTime = (Client()->PrevGameTick(g_Config.m_ClDummy) - Player.m_AttackTick) / (float)SERVER_TICK_SPEED + Client()->GameTickTime(g_Config.m_ClDummy); + float LastAttackTime = (Client()->PrevGameTick(g_Config.m_ClDummy) - Player.m_AttackTick) / (float)SERVER_TICK_SPEED + s_LastGameTickTime; if(m_pClient->m_aClients[ClientID].m_IsPredictedLocal && m_pClient->AntiPingGunfire()) { PredictLocalWeapons = true; - AttackTime = (Client()->PredIntraGameTick() + (Client()->PredGameTick() - 1 - Player.m_AttackTick)) / (float)SERVER_TICK_SPEED; - LastAttackTime = (s_LastPredIntraTick + (Client()->PredGameTick() - 1 - Player.m_AttackTick)) / (float)SERVER_TICK_SPEED; + AttackTime = (Client()->PredIntraGameTick(g_Config.m_ClDummy) + (Client()->PredGameTick(g_Config.m_ClDummy) - 1 - Player.m_AttackTick)) / (float)SERVER_TICK_SPEED; + LastAttackTime = (s_LastPredIntraTick + (Client()->PredGameTick(g_Config.m_ClDummy) - 1 - Player.m_AttackTick)) / (float)SERVER_TICK_SPEED; } float AttackTicksPassed = AttackTime*SERVER_TICK_SPEED; @@ -215,7 +215,7 @@ void CPlayers::RenderPlayer( float AngleIntraTick = IntraTick; // using unpredicted angle when rendering other players in-game if(ClientID >= 0) - AngleIntraTick = Client()->IntraGameTick(); + AngleIntraTick = Client()->IntraGameTick(g_Config.m_ClDummy); // If the player moves their weapon through top, then change // the end angle by 2*Pi, so that the mix function will use the // short path and not the long one. @@ -522,7 +522,7 @@ void CPlayers::RenderPlayer( GhostPosition = mix( vec2(m_pClient->m_Snap.m_aCharacters[ClientID].m_Prev.m_X, m_pClient->m_Snap.m_aCharacters[ClientID].m_Prev.m_Y), vec2(m_pClient->m_Snap.m_aCharacters[ClientID].m_Cur.m_X, m_pClient->m_Snap.m_aCharacters[ClientID].m_Cur.m_Y), - Client()->IntraGameTick()); + Client()->IntraGameTick(g_Config.m_ClDummy)); CTeeRenderInfo Ghost = RenderInfo; RenderTools()->RenderTee(&State, &Ghost, Player.m_Emote, Direction, GhostPosition, 0.5f); // render ghost @@ -590,12 +590,12 @@ void CPlayers::RenderPlayer( Graphics()->QuadsSetRotation(0); } - if(g_Config.m_ClShowEmotes && m_pClient->m_aClients[ClientID].m_EmoticonStart != -1 && m_pClient->m_aClients[ClientID].m_EmoticonStart <= Client()->GameTick() && m_pClient->m_aClients[ClientID].m_EmoticonStart + 2 * Client()->GameTickSpeed() > Client()->GameTick()) + if(g_Config.m_ClShowEmotes && m_pClient->m_aClients[ClientID].m_EmoticonStart != -1 && m_pClient->m_aClients[ClientID].m_EmoticonStart <= Client()->GameTick(g_Config.m_ClDummy) && m_pClient->m_aClients[ClientID].m_EmoticonStart + 2 * Client()->GameTickSpeed() > Client()->GameTick(g_Config.m_ClDummy)) { Graphics()->TextureSet(g_pData->m_aImages[IMAGE_EMOTICONS].m_Id); - int SinceStart = Client()->GameTick() - m_pClient->m_aClients[ClientID].m_EmoticonStart; - int FromEnd = m_pClient->m_aClients[ClientID].m_EmoticonStart + 2 * Client()->GameTickSpeed() - Client()->GameTick(); + int SinceStart = Client()->GameTick(g_Config.m_ClDummy) - m_pClient->m_aClients[ClientID].m_EmoticonStart; + int FromEnd = m_pClient->m_aClients[ClientID].m_EmoticonStart + 2 * Client()->GameTickSpeed() - Client()->GameTick(g_Config.m_ClDummy); float a = 1; diff --git a/src/game/client/components/race_demo.cpp b/src/game/client/components/race_demo.cpp index 7df0ab8eb..0ee68107a 100644 --- a/src/game/client/components/race_demo.cpp +++ b/src/game/client/components/race_demo.cpp @@ -64,8 +64,8 @@ void CRaceDemo::OnNewSnapshot() int RaceTick = -m_pClient->m_Snap.m_pGameInfoObj->m_WarmupTimer; // start the demo - bool ForceStart = ServerControl && s_LastRaceTick != RaceTick && Client()->GameTick() - RaceTick < Client()->GameTickSpeed(); - bool AllowRestart = (m_AllowRestart || ForceStart) && m_RaceStartTick + 10 * Client()->GameTickSpeed() < Client()->GameTick(); + bool ForceStart = ServerControl && s_LastRaceTick != RaceTick && Client()->GameTick(g_Config.m_ClDummy) - RaceTick < Client()->GameTickSpeed(); + bool AllowRestart = (m_AllowRestart || ForceStart) && m_RaceStartTick + 10 * Client()->GameTickSpeed() < Client()->GameTick(g_Config.m_ClDummy); if(m_RaceState == RACE_IDLE || m_RaceState == RACE_PREPARE || (m_RaceState == RACE_STARTED && AllowRestart)) { vec2 PrevPos = vec2(m_pClient->m_Snap.m_pLocalPrevCharacter->m_X, m_pClient->m_Snap.m_pLocalPrevCharacter->m_Y); @@ -80,7 +80,7 @@ void CRaceDemo::OnNewSnapshot() GetPath(m_aTmpFilename, sizeof(m_aTmpFilename)); Client()->RaceRecord_Start(m_aTmpFilename); } - m_RaceStartTick = Client()->GameTick(); + m_RaceStartTick = Client()->GameTick(g_Config.m_ClDummy); m_RaceState = RACE_STARTED; } } @@ -90,19 +90,19 @@ void CRaceDemo::OnNewSnapshot() { GetPath(m_aTmpFilename, sizeof(m_aTmpFilename)); Client()->RaceRecord_Start(m_aTmpFilename); - m_RaceStartTick = Client()->GameTick(); + m_RaceStartTick = Client()->GameTick(g_Config.m_ClDummy); m_RaceState = RACE_PREPARE; } // stop recording if the player did not pass the start line after 20 seconds - if(m_RaceState == RACE_PREPARE && Client()->GameTick() - m_RaceStartTick >= Client()->GameTickSpeed() * 20) + if(m_RaceState == RACE_PREPARE && Client()->GameTick(g_Config.m_ClDummy) - m_RaceStartTick >= Client()->GameTickSpeed() * 20) { StopRecord(); m_RaceState = RACE_IDLE; } // stop the demo - if(m_RaceState == RACE_FINISHED && m_RecordStopTick <= Client()->GameTick()) + if(m_RaceState == RACE_FINISHED && m_RecordStopTick <= Client()->GameTick(g_Config.m_ClDummy)) StopRecord(m_Time); s_LastRaceTick = RaceFlag ? RaceTick : -1; @@ -132,7 +132,7 @@ void CRaceDemo::OnMessage(int MsgType, void *pRawMsg) if(Time > 0 && str_comp(aName, m_pClient->m_aClients[m_pClient->m_Snap.m_LocalClientID].m_aName) == 0) { m_RaceState = RACE_FINISHED; - m_RecordStopTick = Client()->GameTick() + Client()->GameTickSpeed(); + m_RecordStopTick = Client()->GameTick(g_Config.m_ClDummy) + Client()->GameTickSpeed(); m_Time = Time; } } diff --git a/src/game/client/components/statboard.cpp b/src/game/client/components/statboard.cpp index 4a98e281d..fad7473cd 100644 --- a/src/game/client/components/statboard.cpp +++ b/src/game/client/components/statboard.cpp @@ -333,7 +333,7 @@ void CStatboard::RenderGlobalStats() } // FPM { - float Fpm = pStats->GetFPM(Client()->GameTick(), Client()->GameTickSpeed()); + float Fpm = pStats->GetFPM(Client()->GameTick(g_Config.m_ClDummy), Client()->GameTickSpeed()); str_format(aBuf, sizeof(aBuf), "%.1f", Fpm); tw = TextRender()->TextWidth(0, FontSize, aBuf, -1); TextRender()->Text(0, x-tw+px, y + (LineHeight*0.95f - FontSize) / 2.f, FontSize, aBuf, -1); @@ -521,7 +521,7 @@ void CStatboard::FormatStats() pStats->m_Suicides, // Suicides fdratio, // fdratio pStats->m_Frags - pStats->m_Deaths, // Net - pStats->GetFPM(Client()->GameTick(), Client()->GameTickSpeed()), // FPM + pStats->GetFPM(Client()->GameTick(g_Config.m_ClDummy), Client()->GameTickSpeed()), // FPM pStats->m_CurrentSpree, // CurSpree pStats->m_BestSpree, // BestSpree aWeaponFD, // WeaponFD diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 1909eafdf..60f4675f8 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -539,24 +539,24 @@ void CGameClient::UpdatePositions() // don't use predicted } else - m_LocalCharacterPos = mix(m_PredictedPrevChar.m_Pos, m_PredictedChar.m_Pos, Client()->PredIntraGameTick()); + m_LocalCharacterPos = mix(m_PredictedPrevChar.m_Pos, m_PredictedChar.m_Pos, Client()->PredIntraGameTick(g_Config.m_ClDummy)); } else { if(!(m_Snap.m_pGameInfoObj && m_Snap.m_pGameInfoObj->m_GameStateFlags&GAMESTATEFLAG_GAMEOVER)) { if(m_Snap.m_pLocalCharacter) - m_LocalCharacterPos = mix(m_PredictedPrevChar.m_Pos, m_PredictedChar.m_Pos, Client()->PredIntraGameTick()); + m_LocalCharacterPos = mix(m_PredictedPrevChar.m_Pos, m_PredictedChar.m_Pos, Client()->PredIntraGameTick(g_Config.m_ClDummy)); } // else - // m_LocalCharacterPos = mix(m_PredictedPrevChar.m_Pos, m_PredictedChar.m_Pos, Client()->PredIntraGameTick()); + // m_LocalCharacterPos = mix(m_PredictedPrevChar.m_Pos, m_PredictedChar.m_Pos, Client()->PredIntraGameTick(g_Config.m_ClDummy)); } } else if(m_Snap.m_pLocalCharacter && m_Snap.m_pLocalPrevCharacter) { m_LocalCharacterPos = mix( vec2(m_Snap.m_pLocalPrevCharacter->m_X, m_Snap.m_pLocalPrevCharacter->m_Y), - vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y), Client()->IntraGameTick()); + vec2(m_Snap.m_pLocalCharacter->m_X, m_Snap.m_pLocalCharacter->m_Y), Client()->IntraGameTick(g_Config.m_ClDummy)); } // spectator position @@ -567,14 +567,14 @@ void CGameClient::UpdatePositions() m_Snap.m_SpecInfo.m_Position = mix( vec2(m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Prev.m_X, m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Prev.m_Y), vec2(m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Cur.m_X, m_Snap.m_aCharacters[m_Snap.m_SpecInfo.m_SpectatorID].m_Cur.m_Y), - Client()->IntraGameTick()); + Client()->IntraGameTick(g_Config.m_ClDummy)); m_Snap.m_SpecInfo.m_UsePosition = true; } else if(m_Snap.m_pSpectatorInfo && ((Client()->State() == IClient::STATE_DEMOPLAYBACK && m_DemoSpecID == SPEC_FOLLOW) || (Client()->State() != IClient::STATE_DEMOPLAYBACK && m_Snap.m_SpecInfo.m_SpectatorID != SPEC_FREEVIEW))) { if(m_Snap.m_pPrevSpectatorInfo) m_Snap.m_SpecInfo.m_Position = mix(vec2(m_Snap.m_pPrevSpectatorInfo->m_X, m_Snap.m_pPrevSpectatorInfo->m_Y), - vec2(m_Snap.m_pSpectatorInfo->m_X, m_Snap.m_pSpectatorInfo->m_Y), Client()->IntraGameTick()); + vec2(m_Snap.m_pSpectatorInfo->m_X, m_Snap.m_pSpectatorInfo->m_Y), Client()->IntraGameTick(g_Config.m_ClDummy)); else m_Snap.m_SpecInfo.m_Position = vec2(m_Snap.m_pSpectatorInfo->m_X, m_Snap.m_pSpectatorInfo->m_Y); m_Snap.m_SpecInfo.m_UsePosition = true; @@ -775,7 +775,7 @@ void CGameClient::OnMessage(int MsgId, CUnpacker *pUnpacker, bool IsDummy) // apply m_aClients[pMsg->m_ClientID].m_Emoticon = pMsg->m_Emoticon; - m_aClients[pMsg->m_ClientID].m_EmoticonStart = Client()->GameTick(); + m_aClients[pMsg->m_ClientID].m_EmoticonStart = Client()->GameTick(g_Config.m_ClDummy); } else if(MsgId == NETMSGTYPE_SV_SOUNDGLOBAL) { @@ -1104,7 +1104,7 @@ void CGameClient::OnNewSnapshot() #ifdef CONF_DEBUG if(g_Config.m_DbgStress) { - if((Client()->GameTick()%100) == 0) + if((Client()->GameTick(g_Config.m_ClDummy)%100) == 0) { char aMessage[64]; int MsgLen = rand()%(sizeof(aMessage)-1); @@ -1194,10 +1194,10 @@ void CGameClient::OnNewSnapshot() { m_Snap.m_aTeamSize[pInfo->m_Team]++; if(!m_aStats[pInfo->m_ClientID].IsActive()) - m_aStats[pInfo->m_ClientID].JoinGame(Client()->GameTick()); + m_aStats[pInfo->m_ClientID].JoinGame(Client()->GameTick(g_Config.m_ClDummy)); } else if(m_aStats[pInfo->m_ClientID].IsActive()) - m_aStats[pInfo->m_ClientID].JoinSpec(Client()->GameTick()); + m_aStats[pInfo->m_ClientID].JoinSpec(Client()->GameTick(g_Config.m_ClDummy)); } else if(Item.m_Type == NETOBJTYPE_DDNETPLAYER) @@ -1218,7 +1218,7 @@ void CGameClient::OnNewSnapshot() m_Snap.m_aCharacters[Item.m_ID].m_Prev = *((const CNetObj_Character *)pOld); // reuse the result from the previous evolve if the snapped character didn't change since the previous snapshot - if(m_aClients[Item.m_ID].m_Evolved.m_Tick == Client()->PrevGameTick()) + if(m_aClients[Item.m_ID].m_Evolved.m_Tick == Client()->PrevGameTick(g_Config.m_ClDummy)) { if(mem_comp(&m_Snap.m_aCharacters[Item.m_ID].m_Prev, &m_aClients[Item.m_ID].m_Snapped, sizeof(CNetObj_Character)) == 0) m_Snap.m_aCharacters[Item.m_ID].m_Prev = m_aClients[Item.m_ID].m_Evolved; @@ -1227,9 +1227,9 @@ void CGameClient::OnNewSnapshot() } if(m_Snap.m_aCharacters[Item.m_ID].m_Prev.m_Tick) - Evolve(&m_Snap.m_aCharacters[Item.m_ID].m_Prev, Client()->PrevGameTick()); + Evolve(&m_Snap.m_aCharacters[Item.m_ID].m_Prev, Client()->PrevGameTick(g_Config.m_ClDummy)); if(m_Snap.m_aCharacters[Item.m_ID].m_Cur.m_Tick) - Evolve(&m_Snap.m_aCharacters[Item.m_ID].m_Cur, Client()->GameTick()); + Evolve(&m_Snap.m_aCharacters[Item.m_ID].m_Cur, Client()->GameTick(g_Config.m_ClDummy)); m_aClients[Item.m_ID].m_Snapped = *((const CNetObj_Character *)pData); m_aClients[Item.m_ID].m_Evolved = m_Snap.m_aCharacters[Item.m_ID].m_Cur; @@ -1318,14 +1318,14 @@ void CGameClient::OnNewSnapshot() if(m_Snap.m_pGameDataObj->m_FlagCarrierRed == FLAG_TAKEN) { if(m_FlagDropTick[TEAM_RED] == 0) - m_FlagDropTick[TEAM_RED] = Client()->GameTick(); + m_FlagDropTick[TEAM_RED] = Client()->GameTick(g_Config.m_ClDummy); } else if(m_FlagDropTick[TEAM_RED] != 0) m_FlagDropTick[TEAM_RED] = 0; if(m_Snap.m_pGameDataObj->m_FlagCarrierBlue == FLAG_TAKEN) { if(m_FlagDropTick[TEAM_BLUE] == 0) - m_FlagDropTick[TEAM_BLUE] = Client()->GameTick(); + m_FlagDropTick[TEAM_BLUE] = Client()->GameTick(g_Config.m_ClDummy); } else if(m_FlagDropTick[TEAM_BLUE] != 0) m_FlagDropTick[TEAM_BLUE] = 0; @@ -1512,7 +1512,7 @@ void CGameClient::OnNewSnapshot() { vec2 Pos = mix(vec2(m_Snap.m_aCharacters[i].m_Prev.m_X, m_Snap.m_aCharacters[i].m_Prev.m_Y), vec2(m_Snap.m_aCharacters[i].m_Cur.m_X, m_Snap.m_aCharacters[i].m_Cur.m_Y), - Client()->IntraGameTick()); + Client()->IntraGameTick(g_Config.m_ClDummy)); m_pEffects->AirJump(Pos); } @@ -1565,10 +1565,10 @@ void CGameClient::OnPredict() return; // predict - for(int Tick = Client()->GameTick() + 1; Tick <= Client()->PredGameTick(); Tick++) + for(int Tick = Client()->GameTick(g_Config.m_ClDummy) + 1; Tick <= Client()->PredGameTick(g_Config.m_ClDummy); Tick++) { // fetch the previous characters - if(Tick == Client()->PredGameTick()) + if(Tick == Client()->PredGameTick(g_Config.m_ClDummy)) { m_PrevPredictedWorld.CopyWorld(&m_PredictedWorld); m_PredictedPrevChar = pLocalChar->GetCore(); @@ -1578,7 +1578,7 @@ void CGameClient::OnPredict() } // optionally allow some movement in freeze by not predicting freeze the last one to two ticks - if(g_Config.m_ClPredictFreeze == 2 && Client()->PredGameTick() - 1 - Client()->PredGameTick()%2 <= Tick) + if(g_Config.m_ClPredictFreeze == 2 && Client()->PredGameTick(g_Config.m_ClDummy) - 1 - Client()->PredGameTick(g_Config.m_ClDummy)%2 <= Tick) pLocalChar->m_CanMoveInFreeze = true; // apply inputs and tick @@ -1591,7 +1591,7 @@ void CGameClient::OnPredict() m_PredictedWorld.Tick(); // fetch the current characters - if(Tick == Client()->PredGameTick()) + if(Tick == Client()->PredGameTick(g_Config.m_ClDummy)) { m_PredictedChar = pLocalChar->GetCore(); for(int i = 0; i < MAX_CLIENTS; i++) @@ -1632,7 +1632,7 @@ void CGameClient::OnPredict() static vec2 s_aLastPos[MAX_CLIENTS] = {{0,0}}; static bool s_aLastActive[MAX_CLIENTS] = {0}; - if(g_Config.m_ClAntiPingSmooth && Predict() && AntiPingPlayers() && m_NewTick && abs(m_PredictedTick - Client()->PredGameTick()) <= 1 && abs(Client()->GameTick() - Client()->PrevGameTick()) <= 2) + if(g_Config.m_ClAntiPingSmooth && Predict() && AntiPingPlayers() && m_NewTick && abs(m_PredictedTick - Client()->PredGameTick(g_Config.m_ClDummy)) <= 1 && abs(Client()->GameTick(g_Config.m_ClDummy) - Client()->PrevGameTick(g_Config.m_ClDummy)) <= 2) { int PredTime = clamp(Client()->GetPredictionTime(), 0, 800); float SmoothPace = 4 - 1.5f * PredTime/800.f; // smoothing pace (a lower value will make the smoothing quicker) @@ -1642,15 +1642,15 @@ void CGameClient::OnPredict() { if(!m_Snap.m_aCharacters[i].m_Active || i == m_Snap.m_LocalClientID || !s_aLastActive[i]) continue; - vec2 NewPos = (m_PredictedTick == Client()->PredGameTick()) ? m_aClients[i].m_Predicted.m_Pos : m_aClients[i].m_PrevPredicted.m_Pos; + vec2 NewPos = (m_PredictedTick == Client()->PredGameTick(g_Config.m_ClDummy)) ? m_aClients[i].m_Predicted.m_Pos : m_aClients[i].m_PrevPredicted.m_Pos; vec2 PredErr = (s_aLastPos[i] - NewPos)/(float)minimum(Client()->GetPredictionTime(), 200); if(in_range(length(PredErr), 0.05f, 5.f)) { - vec2 PredPos = mix(m_aClients[i].m_PrevPredicted.m_Pos, m_aClients[i].m_Predicted.m_Pos, Client()->PredIntraGameTick()); + vec2 PredPos = mix(m_aClients[i].m_PrevPredicted.m_Pos, m_aClients[i].m_Predicted.m_Pos, Client()->PredIntraGameTick(g_Config.m_ClDummy)); vec2 CurPos = mix( vec2(m_Snap.m_aCharacters[i].m_Prev.m_X, m_Snap.m_aCharacters[i].m_Prev.m_Y), vec2(m_Snap.m_aCharacters[i].m_Cur.m_X, m_Snap.m_aCharacters[i].m_Cur.m_Y), - Client()->IntraGameTick()); + Client()->IntraGameTick(g_Config.m_ClDummy)); vec2 RenderDiff = PredPos - aBeforeRender[i]; vec2 PredDiff = PredPos - CurPos; @@ -1700,7 +1700,7 @@ void CGameClient::OnPredict() s_aLastActive[i] = false; } - if(g_Config.m_Debug && g_Config.m_ClPredict && m_PredictedTick == Client()->PredGameTick()) + if(g_Config.m_Debug && g_Config.m_ClPredict && m_PredictedTick == Client()->PredGameTick(g_Config.m_ClDummy)) { CNetObj_CharacterCore Before = {0}, Now = {0}, BeforePrev = {0}, NowPrev = {0}; BeforeChar.Write(&Before); @@ -1721,7 +1721,7 @@ void CGameClient::OnPredict() } } - m_PredictedTick = Client()->PredGameTick(); + m_PredictedTick = Client()->PredGameTick(g_Config.m_ClDummy); if(m_NewPredictedTick) m_pGhost->OnNewPredictedSnapshot(); @@ -1981,7 +1981,7 @@ int CGameClient::IntersectCharacter(vec2 HookPos, vec2 NewPos, vec2& NewPos2, in CNetObj_Character Prev = m_Snap.m_aCharacters[i].m_Prev; CNetObj_Character Player = m_Snap.m_aCharacters[i].m_Cur; - vec2 Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), Client()->IntraGameTick()); + vec2 Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), Client()->IntraGameTick(g_Config.m_ClDummy)); bool IsOneSuper = cData.m_Super || OwnClientData.m_Super; bool IsOneSolo = cData.m_Solo || OwnClientData.m_Solo; @@ -2084,9 +2084,9 @@ void CGameClient::UpdatePrediction() } // advance the gameworld to the current gametick - if(pLocalChar && abs(m_GameWorld.GameTick() - Client()->GameTick()) < SERVER_TICK_SPEED) + if(pLocalChar && abs(m_GameWorld.GameTick() - Client()->GameTick(g_Config.m_ClDummy)) < SERVER_TICK_SPEED) { - for(int Tick = m_GameWorld.GameTick() + 1; Tick <= Client()->GameTick(); Tick++) + for(int Tick = m_GameWorld.GameTick() + 1; Tick <= Client()->GameTick(g_Config.m_ClDummy); Tick++) { CNetObj_PlayerInput *pInput = (CNetObj_PlayerInput*) Client()->GetDirectInput(Tick); if(pInput) @@ -2107,17 +2107,17 @@ void CGameClient::UpdatePrediction() else { // skip to current gametick - m_GameWorld.m_GameTick = Client()->GameTick(); + m_GameWorld.m_GameTick = Client()->GameTick(g_Config.m_ClDummy); if(pLocalChar) - if(CNetObj_PlayerInput *pInput = (CNetObj_PlayerInput*) Client()->GetInput(Client()->GameTick())) + if(CNetObj_PlayerInput *pInput = (CNetObj_PlayerInput*) Client()->GetInput(Client()->GameTick(g_Config.m_ClDummy))) pLocalChar->SetInput(pInput); } for(int i = 0; i < MAX_CLIENTS; i++) if(CCharacter *pChar = m_GameWorld.GetCharacterByID(i)) { - m_aClients[i].m_PredPos[Client()->GameTick() % 200] = pChar->Core()->m_Pos; - m_aClients[i].m_PredTick[Client()->GameTick() % 200] = Client()->GameTick(); + m_aClients[i].m_PredPos[Client()->GameTick(g_Config.m_ClDummy) % 200] = pChar->Core()->m_Pos; + m_aClients[i].m_PredTick[Client()->GameTick(g_Config.m_ClDummy) % 200] = Client()->GameTick(g_Config.m_ClDummy); } // update the local gameworld with the new snapshot @@ -2164,7 +2164,7 @@ void CGameClient::UpdateRenderedCharacters() vec2 UnpredPos = mix( vec2(m_Snap.m_aCharacters[i].m_Prev.m_X, m_Snap.m_aCharacters[i].m_Prev.m_Y), vec2(m_Snap.m_aCharacters[i].m_Cur.m_X, m_Snap.m_aCharacters[i].m_Cur.m_Y), - Client()->IntraGameTick()); + Client()->IntraGameTick(g_Config.m_ClDummy)); vec2 Pos = UnpredPos; if(Predict() && (i == m_Snap.m_LocalClientID || AntiPingPlayers())) @@ -2177,7 +2177,7 @@ void CGameClient::UpdateRenderedCharacters() Pos = mix( vec2(m_aClients[i].m_RenderPrev.m_X, m_aClients[i].m_RenderPrev.m_Y), vec2(m_aClients[i].m_RenderCur.m_X, m_aClients[i].m_RenderCur.m_Y), - m_aClients[i].m_IsPredicted ? Client()->PredIntraGameTick() : Client()->IntraGameTick()); + m_aClients[i].m_IsPredicted ? Client()->PredIntraGameTick(g_Config.m_ClDummy) : Client()->IntraGameTick(g_Config.m_ClDummy)); if(i == m_Snap.m_LocalClientID) { @@ -2219,7 +2219,7 @@ void CGameClient::DetectStrongHook() int ToPlayer = m_Snap.m_aCharacters[FromPlayer].m_Prev.m_HookedPlayer; if(ToPlayer < 0 || ToPlayer >= MAX_CLIENTS || !m_Snap.m_aCharacters[ToPlayer].m_Active || ToPlayer != m_Snap.m_aCharacters[FromPlayer].m_Cur.m_HookedPlayer) continue; - if(abs(minimum(s_LastUpdateTick[ToPlayer], s_LastUpdateTick[FromPlayer]) - Client()->GameTick()) < SERVER_TICK_SPEED/4) + if(abs(minimum(s_LastUpdateTick[ToPlayer], s_LastUpdateTick[FromPlayer]) - Client()->GameTick(g_Config.m_ClDummy)) < SERVER_TICK_SPEED/4) continue; if(m_Snap.m_aCharacters[FromPlayer].m_Prev.m_Direction != m_Snap.m_aCharacters[FromPlayer].m_Cur.m_Direction || m_Snap.m_aCharacters[ToPlayer].m_Prev.m_Direction != m_Snap.m_aCharacters[ToPlayer].m_Cur.m_Direction) @@ -2230,7 +2230,7 @@ void CGameClient::DetectStrongHook() if(!pFromCharWorld || !pToCharWorld) continue; - s_LastUpdateTick[ToPlayer] = s_LastUpdateTick[FromPlayer] = Client()->GameTick(); + s_LastUpdateTick[ToPlayer] = s_LastUpdateTick[FromPlayer] = Client()->GameTick(g_Config.m_ClDummy); float PredictErr[2]; CCharacterCore ToCharCur; @@ -2251,7 +2251,7 @@ void CGameClient::DetectStrongHook() World.m_apCharacters[FromPlayer] = &FromChar; FromChar.Read(&m_Snap.m_aCharacters[FromPlayer].m_Prev); - for(int Tick = Client()->PrevGameTick(); Tick < Client()->GameTick(); Tick++) + for(int Tick = Client()->PrevGameTick(g_Config.m_ClDummy); Tick < Client()->GameTick(g_Config.m_ClDummy); Tick++) { if(dir == 0) { @@ -2297,7 +2297,7 @@ void CGameClient::DetectStrongHook() vec2 CGameClient::GetSmoothPos(int ClientID) { - vec2 Pos = mix(m_aClients[ClientID].m_PrevPredicted.m_Pos, m_aClients[ClientID].m_Predicted.m_Pos, Client()->PredIntraGameTick()); + vec2 Pos = mix(m_aClients[ClientID].m_PrevPredicted.m_Pos, m_aClients[ClientID].m_Predicted.m_Pos, Client()->PredIntraGameTick(g_Config.m_ClDummy)); int64 Now = time_get(); for(int i = 0; i < 2; i++) { @@ -2309,7 +2309,7 @@ vec2 CGameClient::GetSmoothPos(int ClientID) int SmoothTick; float SmoothIntra; Client()->GetSmoothTick(&SmoothTick, &SmoothIntra, MixAmount); - if(SmoothTick > 0 && m_aClients[ClientID].m_PredTick[(SmoothTick-1) % 200] >= Client()->PrevGameTick() && m_aClients[ClientID].m_PredTick[SmoothTick % 200] <= Client()->PredGameTick()) + if(SmoothTick > 0 && m_aClients[ClientID].m_PredTick[(SmoothTick-1) % 200] >= Client()->PrevGameTick(g_Config.m_ClDummy) && m_aClients[ClientID].m_PredTick[SmoothTick % 200] <= Client()->PredGameTick(g_Config.m_ClDummy)) Pos[i] = mix(m_aClients[ClientID].m_PredPos[(SmoothTick-1) % 200][i], m_aClients[ClientID].m_PredPos[SmoothTick % 200][i], SmoothIntra); } } diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 3cfd4e8d2..b581d8187 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 9c9df8e58..20f265e11 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -1309,7 +1309,7 @@ void CEditor::DoToolbar(CUIRect ToolBar) { TB_Bottom.VSplitLeft(60.0f, &Button, &TB_Bottom); { - int (*pPopupFunc)(CEditor *peditor, CUIRect View) = NULL; + int (*pPopupFunc)(CEditor *peditor, CUIRect View, void *pContext) = NULL; const char *aButtonName = "Modifier"; float Height = 0.0f; int Checked = -1; @@ -3472,19 +3472,39 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect View) if(int Result = DoButton_Ex(m_Map.m_lGroups[g]->m_lLayers[i], aBuf, Checked, &Button, BUTTON_CONTEXT, "Select layer. Shift click to select multiple.", CUI::CORNER_R, FontSize)) { - if ((Input()->KeyIsPressed(KEY_LSHIFT) || Input()->KeyIsPressed(KEY_RSHIFT)) && m_SelectedGroup == g) + if(Result == 1 && (Input()->KeyIsPressed(KEY_LSHIFT) || Input()->KeyIsPressed(KEY_RSHIFT)) && m_SelectedGroup == g) { if(!m_lSelectedLayers.remove(i)) m_lSelectedLayers.add(i); } - else + else if(!(Input()->KeyIsPressed(KEY_LSHIFT) || Input()->KeyIsPressed(KEY_RSHIFT))) { m_SelectedGroup = g; SelectLayer(i); } - static int s_LayerPopupID = 0; + static CLayerPopupContext s_LayerPopupContext = {}; if(Result == 2) - UiInvokePopupMenu(&s_LayerPopupID, 0, UI()->MouseX(), UI()->MouseY(), 120, 300, PopupLayer); + { + if(m_lSelectedLayers.size() > 1) + { + bool AllTile = true; + for(int i = 0; AllTile && i < m_lSelectedLayers.size(); i++) + { + if(m_Map.m_lGroups[m_SelectedGroup]->m_lLayers[i]->m_Type == LAYERTYPE_TILES) + s_LayerPopupContext.m_aLayers.add((CLayerTiles *)m_Map.m_lGroups[m_SelectedGroup]->m_lLayers[i]); + else + AllTile = false; + } + + // Don't allow editing if all selected layers are tile layers + if(!AllTile) + s_LayerPopupContext.m_aLayers.clear(); + } + else + s_LayerPopupContext.m_aLayers.clear(); + + UiInvokePopupMenu(&s_LayerPopupContext, 0, UI()->MouseX(), UI()->MouseY(), 120, 300, PopupLayer, &s_LayerPopupContext); + } } LayerCur += 14.0f; @@ -3694,7 +3714,7 @@ static void ModifyIndexDeleted(int *pIndex) *pIndex = *pIndex - 1; } -int CEditor::PopupImage(CEditor *pEditor, CUIRect View) +int CEditor::PopupImage(CEditor *pEditor, CUIRect View, void *pContext) { static int s_ReplaceButton = 0; static int s_RemoveButton = 0; @@ -3744,7 +3764,7 @@ int CEditor::PopupImage(CEditor *pEditor, CUIRect View) return 0; } -int CEditor::PopupSound(CEditor *pEditor, CUIRect View) +int CEditor::PopupSound(CEditor *pEditor, CUIRect View, void *pContext) { static int s_ReplaceButton = 0; static int s_RemoveButton = 0; @@ -5440,7 +5460,7 @@ void CEditor::RenderServerSettingsEditor(CUIRect View) UI()->ClipDisable(); } -int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View) +int CEditor::PopupMenuFile(CEditor *pEditor, CUIRect View, void *pContext) { static int s_NewMapButton = 0; static int s_SaveButton = 0; diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index 915e5dcda..ca43ff742 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -537,6 +537,14 @@ public: virtual void ShowInfo(); virtual int RenderProperties(CUIRect *pToolbox); + struct SCommonPropState { + bool Modified = false; + int Width = -1; + int Height = -1; + int Color = 0; + }; + static int RenderCommonProperties(SCommonPropState &State, CEditor *pEditor, CUIRect *pToolbox, array &pLayers); + virtual void ModifyImageIndex(INDEX_MODIFY_FUNC pfnFunc); virtual void ModifyEnvelopeIndex(INDEX_MODIFY_FUNC pfnFunc); @@ -946,28 +954,34 @@ public: void RenderGrid(CLayerGroup *pGroup); - void UiInvokePopupMenu(void *pID, int Flags, float X, float Y, float W, float H, int (*pfnFunc)(CEditor *pEditor, CUIRect Rect), void *pExtra=0); + void UiInvokePopupMenu(void *pID, int Flags, float X, float Y, float W, float H, int (*pfnFunc)(CEditor *pEditor, CUIRect Rect, void *pContext), void *pExtra=0); void UiDoPopupMenu(); int UiDoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, int Current, int Min, int Max, int Step, float Scale, const char *pToolTip, bool IsDegree=false, bool IsHex=false, int corners=CUI::CORNER_ALL, ColorRGBA* Color=0); - static int PopupGroup(CEditor *pEditor, CUIRect View); - static int PopupLayer(CEditor *pEditor, CUIRect View); - static int PopupQuad(CEditor *pEditor, CUIRect View); - static int PopupPoint(CEditor *pEditor, CUIRect View); - static int PopupNewFolder(CEditor *pEditor, CUIRect View); - static int PopupMapInfo(CEditor *pEditor, CUIRect View); - static int PopupEvent(CEditor *pEditor, CUIRect View); - static int PopupSelectImage(CEditor *pEditor, CUIRect View); - static int PopupSelectSound(CEditor *pEditor, CUIRect View); - static int PopupSelectGametileOp(CEditor *pEditor, CUIRect View); - static int PopupImage(CEditor *pEditor, CUIRect View); - static int PopupMenuFile(CEditor *pEditor, CUIRect View); - static int PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View); - static int PopupSound(CEditor *pEditor, CUIRect View); - static int PopupSource(CEditor *pEditor, CUIRect View); - static int PopupColorPicker(CEditor *pEditor, CUIRect View); - static int PopupEntities(CEditor *pEditor, CUIRect View); + static int PopupGroup(CEditor *pEditor, CUIRect View, void *pContext); + + struct CLayerPopupContext + { + array m_aLayers; + CLayerTiles::SCommonPropState m_CommonPropState; + }; + static int PopupLayer(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupQuad(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupPoint(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupNewFolder(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupMapInfo(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupEvent(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupSelectImage(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupSelectSound(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupSelectGametileOp(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupImage(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupMenuFile(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupSound(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupSource(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupColorPicker(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupEntities(CEditor *pEditor, CUIRect View, void *pContext); static void CallbackOpenMap(const char *pFileName, int StorageType, void *pUser); static void CallbackAppendMap(const char *pFileName, int StorageType, void *pUser); @@ -1037,10 +1051,10 @@ public: IGraphics::CTextureHandle m_SpeedupTexture; IGraphics::CTextureHandle m_SwitchTexture; IGraphics::CTextureHandle m_TuneTexture; - static int PopupTele(CEditor *pEditor, CUIRect View); - static int PopupSpeedup(CEditor *pEditor, CUIRect View); - static int PopupSwitch(CEditor *pEditor, CUIRect View); - static int PopupTune(CEditor *pEditor, CUIRect View); + static int PopupTele(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupSpeedup(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupSwitch(CEditor *pEditor, CUIRect View, void *pContext); + static int PopupTune(CEditor *pEditor, CUIRect View, void *pContext); unsigned char m_TeleNumber; unsigned char m_TuningNum; diff --git a/src/game/editor/layer_tiles.cpp b/src/game/editor/layer_tiles.cpp index 3bff55e55..d6e439fda 100644 --- a/src/game/editor/layer_tiles.cpp +++ b/src/game/editor/layer_tiles.cpp @@ -1,6 +1,7 @@ /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include +#include #include #include @@ -960,6 +961,115 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox) return 0; } +int CLayerTiles::RenderCommonProperties(SCommonPropState &State, CEditor *pEditor, CUIRect *pToolbox, array &pLayers) +{ + if(State.Modified) + { + CUIRect Commit; + pToolbox->HSplitBottom(20.0f, pToolbox, &Commit); + static int s_CommitButton = 0; + if(pEditor->DoButton_Editor(&s_CommitButton, "Commit", 0, &Commit, 0, "Applies the changes")) + { + dbg_msg("editor", "applying changes"); + for_each(pLayers.all(), [&State](CLayerTiles *pLayer){ + pLayer->Resize(State.Width, State.Height); + + pLayer->m_Color.r = (State.Color>>24)&0xff; + pLayer->m_Color.g = (State.Color>>16)&0xff; + pLayer->m_Color.b = (State.Color>>8)&0xff; + pLayer->m_Color.a = State.Color&0xff; + + pLayer->FlagModified(0, 0, pLayer->m_Width, pLayer->m_Height); + }); + State.Modified = false; + } + + } + else + { + for_each(pLayers.all(), [&State](CLayerTiles *pLayer){ + if(pLayer->m_Width > State.Width) + State.Width = pLayer->m_Width; + if(pLayer->m_Height > State.Height) + State.Height = pLayer->m_Height; + }); + } + + { + CUIRect Warning; + pToolbox->HSplitTop(13.0f, &Warning, pToolbox); + Warning.HMargin(0.5f, &Warning); + + pEditor->TextRender()->TextColor(ColorRGBA(1.0f, 0.0f, 0.0f, 1.0f)); + pEditor->UI()->DoLabel(&Warning, "Editing multiple layers", 9.0f, -1, Warning.w); + pEditor->TextRender()->TextColor(ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f)); + pToolbox->HSplitTop(2.0f, 0, pToolbox); + } + + enum + { + PROP_WIDTH=0, + PROP_HEIGHT, + PROP_SHIFT, + PROP_SHIFT_BY, + PROP_COLOR, + NUM_PROPS, + }; + + CProperty aProps[] = { + {"Width", State.Width, PROPTYPE_INT_SCROLL, 1, 100000}, + {"Height", State.Height, PROPTYPE_INT_SCROLL, 1, 100000}, + {"Shift", 0, PROPTYPE_SHIFT, 0, 0}, + {"Shift by", pEditor->m_ShiftBy, PROPTYPE_INT_SCROLL, 1, 100000}, + {"Color", State.Color, PROPTYPE_COLOR, 0, 0}, + {0}, + }; + + static int s_aIds[NUM_PROPS] = {0}; + int NewVal = 0; + int Prop = pEditor->DoProperties(pToolbox, aProps, s_aIds, &NewVal); + + if(Prop == PROP_WIDTH && NewVal > 1) + { + if(NewVal > 1000 && !pEditor->m_LargeLayerWasWarned) + { + pEditor->m_PopupEventType = pEditor->POPEVENT_LARGELAYER; + pEditor->m_PopupEventActivated = true; + pEditor->m_LargeLayerWasWarned = true; + } + State.Width = NewVal; + } + else if(Prop == PROP_HEIGHT && NewVal > 1) + { + if(NewVal > 1000 && !pEditor->m_LargeLayerWasWarned) + { + pEditor->m_PopupEventType = pEditor->POPEVENT_LARGELAYER; + pEditor->m_PopupEventActivated = true; + pEditor->m_LargeLayerWasWarned = true; + } + State.Height = NewVal; + } + else if(Prop == PROP_SHIFT) + { + for_each(pLayers.all(), [NewVal](CLayerTiles *pLayer){ + pLayer->Shift(NewVal); + }); + } + else if(Prop == PROP_SHIFT_BY) + pEditor->m_ShiftBy = NewVal; + else if(Prop == PROP_COLOR) + { + State.Color = NewVal; + } + + if(Prop != -1 && Prop != PROP_SHIFT) + { + State.Modified = true; + } + + return 0; +} + void CLayerTiles::FlagModified(int x, int y, int w, int h) { m_pEditor->m_Map.m_Modified = true; diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp index 2f15f6add..9b443a0b6 100644 --- a/src/game/editor/popups.cpp +++ b/src/game/editor/popups.cpp @@ -18,14 +18,14 @@ static struct { CUIRect m_Rect; void *m_pId; - int (*m_pfnFunc)(CEditor *pEditor, CUIRect Rect); + int (*m_pfnFunc)(CEditor *pEditor, CUIRect Rect, void *pContext); int m_IsMenu; - void *m_pExtra; + void *m_pContext; } s_UiPopups[8]; static int g_UiNumPopups = 0; -void CEditor::UiInvokePopupMenu(void *pID, int Flags, float x, float y, float Width, float Height, int (*pfnFunc)(CEditor *pEditor, CUIRect Rect), void *pExtra) +void CEditor::UiInvokePopupMenu(void *pID, int Flags, float x, float y, float Width, float Height, int (*pfnFunc)(CEditor *pEditor, CUIRect Rect, void *pContext), void *pContext) { if(g_UiNumPopups > 7) return; @@ -41,7 +41,7 @@ void CEditor::UiInvokePopupMenu(void *pID, int Flags, float x, float y, float Wi s_UiPopups[g_UiNumPopups].m_Rect.w = Width; s_UiPopups[g_UiNumPopups].m_Rect.h = Height; s_UiPopups[g_UiNumPopups].m_pfnFunc = pfnFunc; - s_UiPopups[g_UiNumPopups].m_pExtra = pExtra; + s_UiPopups[g_UiNumPopups].m_pContext = pContext; g_UiNumPopups++; } @@ -80,7 +80,7 @@ void CEditor::UiDoPopupMenu() RenderTools()->DrawUIRect(&r, ColorRGBA(0,0,0,0.75f), Corners, 3.0f); r.Margin(4.0f, &r); - if(s_UiPopups[i].m_pfnFunc(this, r)) + if(s_UiPopups[i].m_pfnFunc(this, r, s_UiPopups[i].m_pContext)) { m_LockMouse = false; UI()->SetActiveItem(0); @@ -99,7 +99,7 @@ void CEditor::UiDoPopupMenu() } -int CEditor::PopupGroup(CEditor *pEditor, CUIRect View) +int CEditor::PopupGroup(CEditor *pEditor, CUIRect View, void *pContext) { // remove group button CUIRect Button; @@ -357,13 +357,20 @@ int CEditor::PopupGroup(CEditor *pEditor, CUIRect View) return 0; } -int CEditor::PopupLayer(CEditor *pEditor, CUIRect View) +int CEditor::PopupLayer(CEditor *pEditor, CUIRect View, void *pContext) { + CLayerPopupContext *pPopup = (CLayerPopupContext *)pContext; + // remove layer button CUIRect Button; View.HSplitBottom(12.0f, &View, &Button); static int s_DeleteButton = 0; + if(pPopup->m_aLayers.size() > 1) + { + return CLayerTiles::RenderCommonProperties(pPopup->m_CommonPropState, pEditor, &View, pPopup->m_aLayers); + } + // don't allow deletion of game layer if(pEditor->m_Map.m_pGameLayer != pEditor->GetSelectedLayer(0) && pEditor->DoButton_Editor(&s_DeleteButton, "Delete layer", 0, &Button, 0, "Deletes the layer")) @@ -452,7 +459,7 @@ int CEditor::PopupLayer(CEditor *pEditor, CUIRect View) return pCurrentLayer->RenderProperties(&View); } -int CEditor::PopupQuad(CEditor *pEditor, CUIRect View) +int CEditor::PopupQuad(CEditor *pEditor, CUIRect View, void *pContext) { array lQuads = pEditor->GetSelectedQuads(); CQuad *pCurrentQuad = lQuads[pEditor->m_SelectedQuadIndex]; @@ -634,7 +641,7 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View) return 0; } -int CEditor::PopupSource(CEditor *pEditor, CUIRect View) +int CEditor::PopupSource(CEditor *pEditor, CUIRect View, void *pContext) { CSoundSource *pSource = pEditor->GetSelectedSource(); @@ -828,7 +835,7 @@ int CEditor::PopupSource(CEditor *pEditor, CUIRect View) return 0; } -int CEditor::PopupPoint(CEditor *pEditor, CUIRect View) +int CEditor::PopupPoint(CEditor *pEditor, CUIRect View, void *pContext) { array lQuads = pEditor->GetSelectedQuads(); CQuad *pCurrentQuad = lQuads[pEditor->m_SelectedQuadIndex]; @@ -918,7 +925,7 @@ int CEditor::PopupPoint(CEditor *pEditor, CUIRect View) return 0; } -int CEditor::PopupNewFolder(CEditor *pEditor, CUIRect View) +int CEditor::PopupNewFolder(CEditor *pEditor, CUIRect View, void *pContext) { CUIRect Label, ButtonBar; @@ -987,7 +994,7 @@ int CEditor::PopupNewFolder(CEditor *pEditor, CUIRect View) return 0; } -int CEditor::PopupMapInfo(CEditor *pEditor, CUIRect View) +int CEditor::PopupMapInfo(CEditor *pEditor, CUIRect View, void *pContext) { CUIRect Label, ButtonBar, Button; @@ -1055,7 +1062,7 @@ int CEditor::PopupMapInfo(CEditor *pEditor, CUIRect View) return 0; } -int CEditor::PopupEvent(CEditor *pEditor, CUIRect View) +int CEditor::PopupEvent(CEditor *pEditor, CUIRect View, void *pContext) { CUIRect Label, ButtonBar; @@ -1137,7 +1144,7 @@ int CEditor::PopupEvent(CEditor *pEditor, CUIRect View) static int g_SelectImageSelected = -100; static int g_SelectImageCurrent = -100; -int CEditor::PopupSelectImage(CEditor *pEditor, CUIRect View) +int CEditor::PopupSelectImage(CEditor *pEditor, CUIRect View, void *pContext) { CUIRect ButtonBar, ImageView; View.VSplitLeft(80.0f, &ButtonBar, &View); @@ -1249,7 +1256,7 @@ int CEditor::PopupSelectImageResult() static int g_SelectSoundSelected = -100; static int g_SelectSoundCurrent = -100; -int CEditor::PopupSelectSound(CEditor *pEditor, CUIRect View) +int CEditor::PopupSelectSound(CEditor *pEditor, CUIRect View, void *pContext) { CUIRect ButtonBar, SoundView; View.VSplitLeft(80.0f, &ButtonBar, &View); @@ -1340,7 +1347,7 @@ int CEditor::PopupSelectSoundResult() static int s_GametileOpSelected = -1; -int CEditor::PopupSelectGametileOp(CEditor *pEditor, CUIRect View) +int CEditor::PopupSelectGametileOp(CEditor *pEditor, CUIRect View, void *pContext) { static const char *s_pButtonNames[] = { "Air", "Hookable", "Death", "Unhookable", "Hookthrough", "Freeze", "Unfreeze", "Deep Freeze", "Deep Unfreeze", "Blue Check-Tele", "Red Check-Tele" }; static unsigned s_NumButtons = sizeof(s_pButtonNames) / sizeof(char*); @@ -1377,7 +1384,7 @@ int CEditor::PopupSelectGameTileOpResult() static int s_AutoMapConfigSelected = -100; static int s_AutoMapConfigCurrent = -100; -int CEditor::PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View) +int CEditor::PopupSelectConfigAutoMap(CEditor *pEditor, CUIRect View, void *pContext) { CLayerTiles *pLayer = static_cast(pEditor->GetSelectedLayer(0)); CUIRect Button; @@ -1416,7 +1423,7 @@ int CEditor::PopupSelectConfigAutoMapResult() // DDRace -int CEditor::PopupTele(CEditor *pEditor, CUIRect View) +int CEditor::PopupTele(CEditor *pEditor, CUIRect View, void *pContext) { CUIRect Button; View.HSplitBottom(12.0f, &View, &Button); @@ -1464,7 +1471,7 @@ int CEditor::PopupTele(CEditor *pEditor, CUIRect View) return 0; } -int CEditor::PopupSpeedup(CEditor *pEditor, CUIRect View) +int CEditor::PopupSpeedup(CEditor *pEditor, CUIRect View, void *pContext) { CUIRect Button; View.HSplitBottom(12.0f, &View, &Button); @@ -1498,7 +1505,7 @@ int CEditor::PopupSpeedup(CEditor *pEditor, CUIRect View) return 0; } -int CEditor::PopupSwitch(CEditor *pEditor, CUIRect View) +int CEditor::PopupSwitch(CEditor *pEditor, CUIRect View, void *pContext) { CUIRect Button; View.HSplitBottom(12.0f, &View, &Button); @@ -1549,7 +1556,7 @@ int CEditor::PopupSwitch(CEditor *pEditor, CUIRect View) return 0; } -int CEditor::PopupTune(CEditor *pEditor, CUIRect View) +int CEditor::PopupTune(CEditor *pEditor, CUIRect View, void *pContext) { CUIRect Button; View.HSplitBottom(12.0f, &View, &Button); @@ -1575,7 +1582,7 @@ int CEditor::PopupTune(CEditor *pEditor, CUIRect View) return 0; } -int CEditor::PopupColorPicker(CEditor *pEditor, CUIRect View) +int CEditor::PopupColorPicker(CEditor *pEditor, CUIRect View, void *pContext) { CUIRect SVPicker, HuePicker; View.VSplitRight(20.0f, &SVPicker, &HuePicker); @@ -1677,7 +1684,7 @@ int CEditor::PopupColorPicker(CEditor *pEditor, CUIRect View) return 0; } -int CEditor::PopupEntities(CEditor *pEditor, CUIRect View) +int CEditor::PopupEntities(CEditor *pEditor, CUIRect View, void *pContext) { for(int i = 0; i < (int)pEditor->m_SelectEntitiesFiles.size(); i++) { diff --git a/src/game/server/antibot.cpp b/src/game/server/antibot.cpp index 80409b9f0..bc1da467c 100644 --- a/src/game/server/antibot.cpp +++ b/src/game/server/antibot.cpp @@ -25,9 +25,6 @@ CAntibot::CAntibot() } CAntibot::~CAntibot() { - AntibotDestroy(); - free(g_Data.m_Map.m_pTiles); - g_Data.m_Map.m_pTiles = 0; } void CAntibot::Init(CGameContext *pGameContext) { @@ -40,6 +37,12 @@ void CAntibot::Init(CGameContext *pGameContext) AntibotInit(&g_Data); Update(); } +void CAntibot::Shutdown() +{ + AntibotDestroy(); + free(g_Data.m_Map.m_pTiles); + g_Data.m_Map.m_pTiles = 0; +} void CAntibot::Dump() { AntibotDump(); } void CAntibot::Update() { @@ -72,6 +75,9 @@ void CAntibot::Dump() { m_pGameContext->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "antibot", "antibot support not compiled in"); } +void CAntibot::Shutdown() +{ +} void CAntibot::Update() { } diff --git a/src/game/server/antibot.h b/src/game/server/antibot.h index 4dca085ee..8515247a6 100644 --- a/src/game/server/antibot.h +++ b/src/game/server/antibot.h @@ -11,6 +11,7 @@ public: CAntibot(); ~CAntibot(); void Init(CGameContext *pGameContext); + void Shutdown(); void Dump(); void OnPlayerInit(int ClientID); diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 45f44e806..2d001a481 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -3044,6 +3044,8 @@ void CGameContext::OnShutdown(bool FullShutdown) if (FullShutdown) Score()->OnShutdown(); + m_Antibot.Shutdown(); + if(m_TeeHistorianActive) { m_TeeHistorian.Finish();