diff --git a/data/languages/bosnian.txt b/data/languages/bosnian.txt index 7ecf0afd0..dbf3b7c65 100644 --- a/data/languages/bosnian.txt +++ b/data/languages/bosnian.txt @@ -867,6 +867,9 @@ Select layer. Right click for properties. Shift == +Sound error +== + Square == @@ -882,6 +885,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == diff --git a/data/languages/czech.txt b/data/languages/czech.txt index 3b03b0b48..ce243990f 100644 --- a/data/languages/czech.txt +++ b/data/languages/czech.txt @@ -858,6 +858,9 @@ Shift Show chat == +Sound error +== + Square == @@ -876,6 +879,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == diff --git a/data/languages/dutch.txt b/data/languages/dutch.txt index 32fcc6c7a..d03a15869 100644 --- a/data/languages/dutch.txt +++ b/data/languages/dutch.txt @@ -963,6 +963,12 @@ no limit Name plates size == +Sound error +== + +The audio device couldn't be initialised. +== + Unable to delete the demo == diff --git a/data/languages/finnish.txt b/data/languages/finnish.txt index c11d1f1cf..70783d71b 100644 --- a/data/languages/finnish.txt +++ b/data/languages/finnish.txt @@ -864,6 +864,9 @@ Select layer. Right click for properties. Shift == +Sound error +== + Square == @@ -879,6 +882,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == diff --git a/data/languages/french.txt b/data/languages/french.txt index 804a57e82..a76ea7a42 100644 --- a/data/languages/french.txt +++ b/data/languages/french.txt @@ -897,6 +897,9 @@ Rotation of the envelope Shift == +Sound error +== + Squares the current quad == @@ -909,6 +912,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == diff --git a/data/languages/german.txt b/data/languages/german.txt index f8deb9411..329a5ace9 100644 --- a/data/languages/german.txt +++ b/data/languages/german.txt @@ -963,6 +963,12 @@ no limit Name plates size == +Sound error +== + +The audio device couldn't be initialised. +== + Unable to delete the demo == diff --git a/data/languages/italian.txt b/data/languages/italian.txt index 0e75f2d3a..4f2f77008 100644 --- a/data/languages/italian.txt +++ b/data/languages/italian.txt @@ -855,6 +855,9 @@ Shift Show chat == +Sound error +== + Square == @@ -873,6 +876,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == diff --git a/data/languages/polish.txt b/data/languages/polish.txt index 5a08fbee7..2d9c61ee5 100644 --- a/data/languages/polish.txt +++ b/data/languages/polish.txt @@ -930,9 +930,15 @@ Rotation of the envelope Shift == +Sound error +== + Stop record == +The audio device couldn't be initialised. +== + Tiles == diff --git a/data/languages/portuguese.txt b/data/languages/portuguese.txt index 028c29f51..47d1b3a73 100644 --- a/data/languages/portuguese.txt +++ b/data/languages/portuguese.txt @@ -864,6 +864,9 @@ Select layer. Right click for properties. Shift == +Sound error +== + Square == @@ -879,6 +882,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == diff --git a/data/languages/romanian.txt b/data/languages/romanian.txt index 9e33ca351..32e1011b9 100644 --- a/data/languages/romanian.txt +++ b/data/languages/romanian.txt @@ -856,6 +856,9 @@ Type UI Color == Culoare meniu +Unable to delete the demo +== Nu pot șterge demo-ul + Up == Sus @@ -963,7 +966,10 @@ no limit ##### needs translation ##### -Unable to delete the demo +Sound error +== + +The audio device couldn't be initialised. == ##### old translations ##### diff --git a/data/languages/russian.txt b/data/languages/russian.txt index 2facf9d11..11e1f79a9 100644 --- a/data/languages/russian.txt +++ b/data/languages/russian.txt @@ -930,9 +930,15 @@ Rotation of the envelope Shift == +Sound error +== + Stop record == +The audio device couldn't be initialised. +== + Tiles == diff --git a/data/languages/serbian.txt b/data/languages/serbian.txt index ad1c0346a..33ca37625 100644 --- a/data/languages/serbian.txt +++ b/data/languages/serbian.txt @@ -864,6 +864,9 @@ Select layer. Right click for properties. Shift == +Sound error +== + Square == @@ -879,6 +882,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == diff --git a/data/languages/swedish.txt b/data/languages/swedish.txt index 1a3112945..c73e9b789 100644 --- a/data/languages/swedish.txt +++ b/data/languages/swedish.txt @@ -855,6 +855,9 @@ Shift Show chat == +Sound error +== + Square == @@ -873,6 +876,9 @@ Switch between images and layers managment. Switch curve type == +The audio device couldn't be initialised. +== + Tiles == diff --git a/data/languages/ukrainian.txt b/data/languages/ukrainian.txt index dbaffce0e..518e76397 100644 --- a/data/languages/ukrainian.txt +++ b/data/languages/ukrainian.txt @@ -945,6 +945,12 @@ Rotation of the envelope Shift == +Sound error +== + +The audio device couldn't be initialised. +== + Unable to delete the demo == diff --git a/scripts/cmd5.py b/scripts/cmd5.py index dbdfae824..11a18137d 100644 --- a/scripts/cmd5.py +++ b/scripts/cmd5.py @@ -31,6 +31,6 @@ for filename in sys.argv[1:]: hash = hashlib.md5(f.encode()).hexdigest().lower()[16:] # TODO: refactor hash that is equal to the 0.5 hash, remove when we # TODO: remove when we don't need it any more -if hash == "026b8eceb4cdd369": +if hash == "f16c2456fc487748": hash = "b67d1f1a1eea234e" print('#define GAME_NETVERSION_HASH "%s"' % hash) diff --git a/src/engine/client.h b/src/engine/client.h index 80a0241d8..2da2bd8b7 100644 --- a/src/engine/client.h +++ b/src/engine/client.h @@ -130,6 +130,8 @@ public: virtual const char *ErrorString() = 0; virtual const char *LatestVersion() = 0; virtual bool ConnectionProblems() = 0; + + virtual bool SoundInitFailed() = 0; }; class IGameClient : public IInterface @@ -149,6 +151,7 @@ public: virtual void OnConnected() = 0; virtual void OnMessage(int MsgId, CUnpacker *pUnpacker) = 0; virtual void OnPredict() = 0; + virtual void OnActivateEditor() = 0; virtual int OnSnapInput(int *pData) = 0; diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp index 6cfc77be9..c356c9238 100644 --- a/src/engine/client/client.cpp +++ b/src/engine/client/client.cpp @@ -414,6 +414,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta), m_DemoRecorder(&m_SnapshotD m_WindowMustRefocus = 0; m_SnapCrcErrors = 0; m_AutoScreenshotRecycle = false; + m_EditorActive = false; m_AckGameTick = -1; m_CurrentRecvTick = 0; @@ -1466,11 +1467,11 @@ void CClient::ProcessPacket(CNetChunk *pPacket) } // adjust game time + if(m_RecivedSnapshots > 2) { int64 Now = m_GameTime.Get(time_get()); int64 TickStart = GameTick*time_freq()/50; int64 TimeLeft = (TickStart-Now)*1000 / time_freq(); - //st_update(&game_time, (game_tick-1)*time_freq()/50); m_GameTime.Update(&m_GametimeMarginGraph, (GameTick-1)*time_freq()/50, TimeLeft, 0); } @@ -1807,7 +1808,7 @@ void CClient::Run() m_pEditor->Init(); // init sound, allowed to fail - Sound()->Init(); + m_SoundInitFailed = Sound()->Init() != 0; // load data if(!LoadData()) @@ -1919,12 +1920,21 @@ void CClient::Run() // render if(g_Config.m_ClEditor) { + if(!m_EditorActive) + { + GameClient()->OnActivateEditor(); + m_EditorActive = true; + } + Update(); m_pEditor->UpdateAndRender(); m_pGraphics->Swap(); } else { + if(m_EditorActive) + m_EditorActive = false; + Update(); if(g_Config.m_DbgStress) diff --git a/src/engine/client/client.h b/src/engine/client/client.h index 12a2e9ae4..9d3687706 100644 --- a/src/engine/client/client.h +++ b/src/engine/client/client.h @@ -141,6 +141,8 @@ class CClient : public IClient, public CDemoPlayer::IListner int m_WindowMustRefocus; int m_SnapCrcErrors; bool m_AutoScreenshotRecycle; + bool m_EditorActive; + bool m_SoundInitFailed; int m_AckGameTick; int m_CurrentRecvTick; @@ -234,6 +236,8 @@ public: virtual bool ConnectionProblems(); + virtual bool SoundInitFailed() { return m_SoundInitFailed; } + void DirectInput(int *pInput, int Size); void SendInput(); diff --git a/src/engine/client/srvbrowse.cpp b/src/engine/client/srvbrowse.cpp index 0041bcd03..7196edee7 100644 --- a/src/engine/client/srvbrowse.cpp +++ b/src/engine/client/srvbrowse.cpp @@ -2,6 +2,7 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include // sort +#include #include #include #include @@ -449,9 +450,9 @@ void CServerBrowser::Set(const NETADDR &Addr, int Type, int Token, const CServer { SetInfo(pEntry, *pInfo); if(m_ServerlistType == IServerBrowser::TYPE_LAN) - pEntry->m_Info.m_Latency = (time_get()-m_BroadcastTime)*1000/time_freq(); + pEntry->m_Info.m_Latency = min(static_cast((time_get()-m_BroadcastTime)*1000/time_freq()), 999); else - pEntry->m_Info.m_Latency = (time_get()-pEntry->m_RequestTime)*1000/time_freq(); + pEntry->m_Info.m_Latency = min(static_cast((time_get()-pEntry->m_RequestTime)*1000/time_freq()), 999); RemoveRequest(pEntry); } } @@ -463,9 +464,9 @@ void CServerBrowser::Set(const NETADDR &Addr, int Type, int Token, const CServer SetInfo(pEntry, *pInfo); if(m_ServerlistType == IServerBrowser::TYPE_LAN) - pEntry->m_Info.m_Latency = (time_get()-m_BroadcastTime)*1000/time_freq(); + pEntry->m_Info.m_Latency = min(static_cast((time_get()-m_BroadcastTime)*1000/time_freq()), 999); else - pEntry->m_Info.m_Latency = (time_get()-pEntry->m_RequestTime)*1000/time_freq(); + pEntry->m_Info.m_Latency = min(static_cast((time_get()-pEntry->m_RequestTime)*1000/time_freq()), 999); RemoveRequest(pEntry); } } @@ -748,4 +749,4 @@ void CServerBrowser::ConfigSaveCallback(IConfig *pConfig, void *pUserData) str_format(aBuffer, sizeof(aBuffer), "add_favorite %s", aAddrStr); pConfig->WriteLine(aBuffer); } -} \ No newline at end of file +} diff --git a/src/engine/server/register.cpp b/src/engine/server/register.cpp index dfa3060f3..36b26f1e1 100644 --- a/src/engine/server/register.cpp +++ b/src/engine/server/register.cpp @@ -187,7 +187,7 @@ void CRegister::RegisterUpdate() else { char aBuf[256]; - str_format(aBuf, sizeof(aBuf), "choosen '%s' as master, sending heartbeats", m_pMasterServer->GetName(m_RegisterRegisteredServer)); + str_format(aBuf, sizeof(aBuf), "chose '%s' as master, sending heartbeats", m_pMasterServer->GetName(m_RegisterRegisteredServer)); m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "register", aBuf); m_aMasterserverInfo[m_RegisterRegisteredServer].m_LastSend = 0; RegisterNewState(REGISTERSTATE_HEARTBEAT); diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp index c87c4efc6..649c399bb 100644 --- a/src/engine/server/server.cpp +++ b/src/engine/server/server.cpp @@ -903,22 +903,24 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket) } else { - char aHex[] = "0123456789ABCDEF"; - char aBuf[512]; - - for(int b = 0; b < pPacket->m_DataSize && b < 32; b++) + if(g_Config.m_Debug) { - aBuf[b*3] = aHex[((const unsigned char *)pPacket->m_pData)[b]>>4]; - aBuf[b*3+1] = aHex[((const unsigned char *)pPacket->m_pData)[b]&0xf]; - aBuf[b*3+2] = ' '; - aBuf[b*3+3] = 0; - } + char aHex[] = "0123456789ABCDEF"; + char aBuf[512]; - char aBufMsg[256]; - str_format(aBufMsg, sizeof(aBufMsg), "strange message ClientId=%d msg=%d data_size=%d", ClientId, Msg, pPacket->m_DataSize); - Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBufMsg); - Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf); - + for(int b = 0; b < pPacket->m_DataSize && b < 32; b++) + { + aBuf[b*3] = aHex[((const unsigned char *)pPacket->m_pData)[b]>>4]; + aBuf[b*3+1] = aHex[((const unsigned char *)pPacket->m_pData)[b]&0xf]; + aBuf[b*3+2] = ' '; + aBuf[b*3+3] = 0; + } + + char aBufMsg[256]; + str_format(aBufMsg, sizeof(aBufMsg), "strange message ClientId=%d msg=%d data_size=%d", ClientId, Msg, pPacket->m_DataSize); + Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBufMsg); + Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf); + } } } else diff --git a/src/engine/shared/snapshot.cpp b/src/engine/shared/snapshot.cpp index ac16a6f8e..7ead43201 100644 --- a/src/engine/shared/snapshot.cpp +++ b/src/engine/shared/snapshot.cpp @@ -80,7 +80,7 @@ static void GenerateHash(CItemList *pHashlist, CSnapshot *pSnapshot) for(int i = 0; i < pSnapshot->NumItems(); i++) { int Key = pSnapshot->GetItem(i)->Key(); - int HashID = ((Key>>8)&0xf0) | (Key&0xf); + int HashID = ((Key>>12)&0xf0) | (Key&0xf); if(pHashlist[HashID].m_Num != 64) { pHashlist[HashID].m_aIndex[pHashlist[HashID].m_Num] = i; @@ -92,7 +92,7 @@ static void GenerateHash(CItemList *pHashlist, CSnapshot *pSnapshot) static int GetItemIndexHashed(int Key, const CItemList *pHashlist) { - int HashID = ((Key>>8)&0xf0) | (Key&0xf); + int HashID = ((Key>>12)&0xf0) | (Key&0xf); for(int i = 0; i < pHashlist[HashID].m_Num; i++) { if(pHashlist[HashID].m_aKeys[i] == Key) @@ -523,6 +523,14 @@ int CSnapshotBuilder::Finish(void *SpnapData) void *CSnapshotBuilder::NewItem(int Type, int ID, int Size) { + if(m_DataSize + sizeof(CSnapshotItem) + Size >= CSnapshot::MAX_SIZE || + m_NumItems+1 >= MAX_ITEMS) + { + dbg_assert(m_DataSize < CSnapshot::MAX_SIZE, "too much data"); + dbg_assert(m_NumItems < MAX_ITEMS, "too many items"); + return 0; + } + CSnapshotItem *pObj = (CSnapshotItem *)(m_aData + m_DataSize); mem_zero(pObj, sizeof(CSnapshotItem) + Size); @@ -530,9 +538,6 @@ void *CSnapshotBuilder::NewItem(int Type, int ID, int Size) m_aOffsets[m_NumItems] = m_DataSize; m_DataSize += sizeof(CSnapshotItem) + Size; m_NumItems++; - - dbg_assert(m_DataSize < CSnapshot::MAX_SIZE, "too much data"); - dbg_assert(m_NumItems < MAX_ITEMS, "too many items"); return pObj->Data(); } diff --git a/src/engine/shared/snapshot.h b/src/engine/shared/snapshot.h index abd25a72f..34c3a5487 100644 --- a/src/engine/shared/snapshot.h +++ b/src/engine/shared/snapshot.h @@ -114,7 +114,7 @@ class CSnapshotBuilder { enum { - MAX_ITEMS = 1024*2 + MAX_ITEMS = 1024 }; char m_aData[CSnapshot::MAX_SIZE]; diff --git a/src/game/client/components/broadcast.cpp b/src/game/client/components/broadcast.cpp index 37876562c..17b2d66b6 100644 --- a/src/game/client/components/broadcast.cpp +++ b/src/game/client/components/broadcast.cpp @@ -8,6 +8,7 @@ #include +#include #include #include "broadcast.h" @@ -19,7 +20,7 @@ void CBroadcast::OnReset() void CBroadcast::OnRender() { - if(m_pClient->m_pScoreboard->Active()) + if(m_pClient->m_pScoreboard->Active() || m_pClient->m_pMotd->IsActive()) return; Graphics()->MapScreen(0, 0, 300*Graphics()->ScreenAspect(), 300); diff --git a/src/game/client/components/controls.cpp b/src/game/client/components/controls.cpp index 96c8c52a1..2fcfedf81 100644 --- a/src/game/client/components/controls.cpp +++ b/src/game/client/components/controls.cpp @@ -32,6 +32,11 @@ void CControls::OnReset() m_InputDirectionRight = 0; } +void CControls::OnRelease() +{ + OnReset(); +} + void CControls::OnPlayerDeath() { m_LastData.m_WantedWeapon = m_InputData.m_WantedWeapon = 0; diff --git a/src/game/client/components/controls.h b/src/game/client/components/controls.h index 38b3c8ba0..a50318f5a 100644 --- a/src/game/client/components/controls.h +++ b/src/game/client/components/controls.h @@ -19,6 +19,7 @@ public: CControls(); virtual void OnReset(); + virtual void OnRelease(); virtual void OnRender(); virtual void OnMessage(int MsgType, void *pRawMsg); virtual bool OnMouseMove(float x, float y); diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp index f54a45d70..388ce47b1 100644 --- a/src/game/client/components/hud.cpp +++ b/src/game/client/components/hud.cpp @@ -151,24 +151,34 @@ void CHud::RenderScoreHud() } else { - int Local = 1; + int Local = -1; int aPos[2] = { 1, 2 }; - const CNetObj_PlayerInfo *apPlayerInfo[2] = { m_pClient->m_Snap.m_paInfoByScore[0], 0 }; - if(m_pClient->m_Snap.m_paInfoByScore[0]) + const CNetObj_PlayerInfo *apPlayerInfo[2] = { 0, 0 }; + int i = 0; + for(int t = 0; t < 2 && i < MAX_CLIENTS && m_pClient->m_Snap.m_paInfoByScore[i]; ++i) { - if(m_pClient->m_Snap.m_paInfoByScore[0]->m_ClientId == m_pClient->m_Snap.m_LocalCid) + if(m_pClient->m_Snap.m_paInfoByScore[i]->m_Team != TEAM_SPECTATORS) { - apPlayerInfo[1] = m_pClient->m_Snap.m_paInfoByScore[1]; - Local = 0; + apPlayerInfo[t] = m_pClient->m_Snap.m_paInfoByScore[i]; + if(apPlayerInfo[t]->m_ClientId == m_pClient->m_Snap.m_LocalCid) + Local = t; + ++t; + } + } + // search local player info if not a spectator, nor within top2 scores + if(Local == -1 && m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS) + { + for(; i < MAX_CLIENTS && m_pClient->m_Snap.m_paInfoByScore[i]; ++i) + { + if(m_pClient->m_Snap.m_paInfoByScore[i]->m_Team != TEAM_SPECTATORS) + ++aPos[1]; + if(m_pClient->m_Snap.m_paInfoByScore[i]->m_ClientId == m_pClient->m_Snap.m_LocalCid) + { + apPlayerInfo[1] = m_pClient->m_Snap.m_paInfoByScore[i]; + Local = 1; + break; + } } - else - for(int i = 1; i < MAX_CLIENTS; ++i) - if(m_pClient->m_Snap.m_paInfoByScore[i]->m_ClientId == m_pClient->m_Snap.m_LocalCid) - { - apPlayerInfo[1] = m_pClient->m_Snap.m_paInfoByScore[i]; - aPos[1] = i+1; - break; - } } char aScore[2][32]; for(int t = 0; t < 2; ++t) diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp index af42dae6c..0ba74b681 100644 --- a/src/game/client/components/menus.cpp +++ b/src/game/client/components/menus.cpp @@ -759,6 +759,14 @@ int CMenus::Render() // some margin around the screen Screen.Margin(10.0f, &Screen); + static bool s_SoundCheck = false; + if(!s_SoundCheck && m_Popup == POPUP_NONE) + { + if(Client()->SoundInitFailed()) + m_Popup = POPUP_SOUNDERROR; + s_SoundCheck = true; + } + if(m_Popup == POPUP_NONE) { // do tab bar @@ -848,6 +856,13 @@ int CMenus::Render() pExtraText = Localize("Are you sure that you want to delete the demo?"); ExtraAlign = -1; } + else if(m_Popup == POPUP_SOUNDERROR) + { + pTitle = Localize("Sound error"); + pExtraText = Localize("The audio device couldn't be initialised."); + pButtonText = Localize("Ok"); + ExtraAlign = -1; + } else if(m_Popup == POPUP_PASSWORD) { pTitle = Localize("Password incorrect"); diff --git a/src/game/client/components/menus.h b/src/game/client/components/menus.h index 9c1bfc453..8da539f46 100644 --- a/src/game/client/components/menus.h +++ b/src/game/client/components/menus.h @@ -97,6 +97,7 @@ class CMenus : public CComponent POPUP_PURE, POPUP_LANGUAGE, POPUP_DELETE_DEMO, + POPUP_SOUNDERROR, POPUP_PASSWORD, POPUP_QUIT, }; diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp index d1fe2aed0..0544010a4 100644 --- a/src/game/client/components/players.cpp +++ b/src/game/client/components/players.cpp @@ -121,9 +121,6 @@ void CPlayers::RenderHook( float IntraTick = Client()->IntraGameTick(); - if(Player.m_Health < 0) // dont render dead players - return; - // set size RenderInfo.m_Size = 64.0f; @@ -131,7 +128,7 @@ void CPlayers::RenderHook( // use preditect players if needed if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { - if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pLocalCharacter->m_Health < 0) || (m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver)) + if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver)) { } else @@ -145,9 +142,6 @@ void CPlayers::RenderHook( vec2 Position = mix(vec2(Prev.m_X, Prev.m_Y), vec2(Player.m_X, Player.m_Y), IntraTick); - if(Prev.m_Health < 0) // Don't flicker from previous position - Position = vec2(Player.m_X, Player.m_Y); - // draw hook if (Prev.m_HookState>0 && Player.m_HookState>0) { @@ -254,9 +248,6 @@ void CPlayers::RenderPlayer( float IntraTick = Client()->IntraGameTick(); - if(Player.m_Health < 0) // dont render dead players - return; - float Angle = mix((float)Prev.m_Angle, (float)Player.m_Angle, IntraTick)/256.0f; //float angle = 0; @@ -292,7 +283,7 @@ void CPlayers::RenderPlayer( // use preditect players if needed if(pInfo.m_Local && g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { - if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pLocalCharacter->m_Health < 0) || (m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver)) + if(!m_pClient->m_Snap.m_pLocalCharacter || (m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver)) { } else @@ -322,9 +313,6 @@ void CPlayers::RenderPlayer( m_pClient->m_pEffects->AirJump(Position); } - if(Prev.m_Health < 0) // Don't flicker from previous position - Position = vec2(Player.m_X, Player.m_Y); - bool Stationary = Player.m_VelX <= 1 && Player.m_VelX >= -1; bool InAir = !Collision()->CheckPoint(Player.m_X, Player.m_Y+16); bool WantOtherDir = (Player.m_Direction == -1 && Vel.x > 0) || (Player.m_Direction == 1 && Vel.x < 0); diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp index 6c8eb2184..0432b256f 100644 --- a/src/game/client/components/scoreboard.cpp +++ b/src/game/client/components/scoreboard.cpp @@ -53,32 +53,26 @@ void CScoreboard::RenderGoals(float x, float y, float w) Graphics()->QuadsEnd(); // render goals - //y = ystart+h-54; - float tw = 0.0f; if(m_pClient->m_Snap.m_pGameobj) { if(m_pClient->m_Snap.m_pGameobj->m_ScoreLimit) { char aBuf[64]; str_format(aBuf, sizeof(aBuf), "%s: %d", Localize("Score limit"), m_pClient->m_Snap.m_pGameobj->m_ScoreLimit); - TextRender()->Text(0, x+20.0f, y, 22.0f, aBuf, -1); - tw += TextRender()->TextWidth(0, 22.0f, aBuf, -1); + TextRender()->Text(0, x, y, 20.0f, aBuf, -1); } if(m_pClient->m_Snap.m_pGameobj->m_TimeLimit) { char aBuf[64]; str_format(aBuf, sizeof(aBuf), Localize("Time limit: %d min"), m_pClient->m_Snap.m_pGameobj->m_TimeLimit); - TextRender()->Text(0, x+220.0f, y, 22.0f, aBuf, -1); - tw += TextRender()->TextWidth(0, 22.0f, aBuf, -1); + TextRender()->Text(0, x+220.0f, y, 20.0f, aBuf, -1); } if(m_pClient->m_Snap.m_pGameobj->m_RoundNum && m_pClient->m_Snap.m_pGameobj->m_RoundCurrent) { char aBuf[64]; str_format(aBuf, sizeof(aBuf), "%s %d/%d", Localize("Round"), m_pClient->m_Snap.m_pGameobj->m_RoundCurrent, m_pClient->m_Snap.m_pGameobj->m_RoundNum); - TextRender()->Text(0, x+450.0f, y, 22.0f, aBuf, -1); - - /*[48c3fd4c][game/scoreboard]: timelimit x:219.428558 - [48c3fd4c][game/scoreboard]: round x:453.142822*/ + float tw = TextRender()->TextWidth(0, 20.0f, aBuf, -1); + TextRender()->Text(0, x+w-tw-20.0f, y, 20.0f, aBuf, -1); } } } @@ -132,13 +126,13 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch return; //float ystart = y; - float h = 750.0f; + float h = 740.0f; Graphics()->BlendNormal(); Graphics()->TextureSet(-1); Graphics()->QuadsBegin(); Graphics()->SetColor(0,0,0,0.5f); - RenderTools()->DrawRoundRect(x-10.f, y-10.f, w, h, 17.0f); + RenderTools()->DrawRoundRect(x-10.f, y, w, h, 17.0f); Graphics()->QuadsEnd(); // render title @@ -334,24 +328,7 @@ void CScoreboard::RenderRecordingNotification(float x) void CScoreboard::OnRender() { - bool DoScoreBoard = false; - - // if we activly wanna look on the scoreboard - if(m_Active) - DoScoreBoard = true; - - if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS) - { - // we are not a spectator, check if we are ead - if(!m_pClient->m_Snap.m_pLocalCharacter || m_pClient->m_Snap.m_pLocalCharacter->m_Health < 0) - DoScoreBoard = true; - } - - // if we the game is over - if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver) - DoScoreBoard = true; - - if(!DoScoreBoard) + if(!Active()) return; // if the score board is active, then we should clear the motd message aswell @@ -371,10 +348,7 @@ void CScoreboard::OnRender() w = 650.0f; if(m_pClient->m_Snap.m_pGameobj && !(m_pClient->m_Snap.m_pGameobj->m_Flags&GAMEFLAG_TEAMS)) - { RenderScoreboard(Width/2-w/2, 150.0f, w, 0, 0); - //render_scoreboard(gameobj, 0, 0, -1, 0); - } else { @@ -401,5 +375,20 @@ void CScoreboard::OnRender() bool CScoreboard::Active() { - return m_Active | (m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver); + // if we activly wanna look on the scoreboard + if(m_Active) + return true; + + if(m_pClient->m_Snap.m_pLocalInfo && m_pClient->m_Snap.m_pLocalInfo->m_Team != TEAM_SPECTATORS) + { + // we are not a spectator, check if we are dead + if(!m_pClient->m_Snap.m_pLocalCharacter) + return true; + } + + // if the game is over + if(m_pClient->m_Snap.m_pGameobj && m_pClient->m_Snap.m_pGameobj->m_GameOver) + return true; + + return false; } diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 3dcaaad4b..9c60782f9 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -404,7 +404,7 @@ void CGameClient::UpdateLocalCharacterPos() { if(g_Config.m_ClPredict && Client()->State() != IClient::STATE_DEMOPLAYBACK) { - if(!m_Snap.m_pLocalCharacter || (m_Snap.m_pLocalCharacter->m_Health < 0) || (m_Snap.m_pGameobj && m_Snap.m_pGameobj->m_GameOver)) + if(!m_Snap.m_pLocalCharacter || (m_Snap.m_pGameobj && m_Snap.m_pGameobj->m_GameOver)) { // don't use predicted } @@ -1019,6 +1019,11 @@ void CGameClient::OnPredict() m_PredictedTick = Client()->PredGameTick(); } +void CGameClient::OnActivateEditor() +{ + OnRelease(); +} + void CGameClient::CClientData::UpdateRenderInfo() { m_RenderInfo = m_SkinInfo; diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 8cda6a7ca..2baf936b2 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -182,6 +182,7 @@ public: virtual void OnMessage(int MsgId, CUnpacker *pUnpacker); virtual void OnNewSnapshot(); virtual void OnPredict(); + virtual void OnActivateEditor(); virtual int OnSnapInput(int *pData); virtual void OnShutdown(); virtual void OnEnterGame(); diff --git a/src/game/gamecore.cpp b/src/game/gamecore.cpp index 5a23f3bae..0f5c0307b 100644 --- a/src/game/gamecore.cpp +++ b/src/game/gamecore.cpp @@ -362,18 +362,19 @@ void CCharacterCore::Tick(bool UseInput) // handle player <-> player collision float d = distance(m_Pos, p->m_Pos); vec2 Dir = normalize(m_Pos - p->m_Pos); - if (m_pWorld->m_Tuning.m_PlayerCollision) { - + if (m_pWorld->m_Tuning.m_PlayerCollision) + { if(d < PhysSize*1.25f && d > 1.0f) { float a = (PhysSize*1.45f - d); - + float v = 0.5f; // make sure that we don't add excess force by checking the - // direction against the current velocity - vec2 VelDir = normalize(m_Vel); - float v = 1-(dot(VelDir, Dir)+1)/2; - m_Vel = m_Vel + Dir*a*(v*0.75f); - m_Vel = m_Vel * 0.85f; + // direction against the current velocity. if not zero. + if (length(m_Vel) > 0.0001) + v = 1-(dot(normalize(m_Vel), Dir)+1)/2; + + m_Vel += Dir*a*(v*0.75f); + m_Vel *= 0.85f; } } // handle hook influence diff --git a/src/game/localization.cpp b/src/game/localization.cpp index 47b9fddbe..ad025100a 100644 --- a/src/game/localization.cpp +++ b/src/game/localization.cpp @@ -91,6 +91,7 @@ bool CLocalizationDatabase::Load(const char *pFilename, IStorage *pStorage, ICon pReplacement += 3; AddString(pLine, pReplacement); } + io_close(IoHandle); m_CurrentVersion = ++m_VersionCounter; return true; diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp index 1491b89ef..aa5cd959f 100644 --- a/src/game/server/entities/character.cpp +++ b/src/game/server/entities/character.cpp @@ -47,7 +47,7 @@ MACRO_ALLOC_POOL_ID_IMPL(CCharacter, MAX_CLIENTS) // Character, "physical" m_pPlayer's part CCharacter::CCharacter(CGameWorld *pWorld) -: CEntity(pWorld, NETOBJTYPE_CHARACTER) +: CEntity(pWorld, CGameWorld::ENTTYPE_CHARACTER) { m_ProximityRadius = ms_PhysSize; m_Health = 0; @@ -186,38 +186,38 @@ void CCharacter::HandleNinja() // check if we Hit anything along the way { - CCharacter *apEnts[64]; + CCharacter *aEnts[MAX_CLIENTS]; vec2 Dir = m_Pos - OldPos; float Radius = m_ProximityRadius * 2.0f; vec2 Center = OldPos + Dir * 0.5f; - int Num = GameServer()->m_World.FindEntities(Center, Radius, (CEntity**)apEnts, 64, NETOBJTYPE_CHARACTER); + int Num = GameServer()->m_World.FindEntities(Center, Radius, (CEntity**)aEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); for (int i = 0; i < Num; ++i) { - if (apEnts[i] == this) + if (aEnts[i] == this) continue; // make sure we haven't Hit this object before bool bAlreadyHit = false; for (int j = 0; j < m_NumObjectsHit; j++) { - if (m_apHitObjects[j] == apEnts[i]) + if (m_apHitObjects[j] == aEnts[i]) bAlreadyHit = true; } if (bAlreadyHit) continue; // check so we are sufficiently close - if (distance(apEnts[i]->m_Pos, m_Pos) > (m_ProximityRadius * 2.0f)) + if (distance(aEnts[i]->m_Pos, m_Pos) > (m_ProximityRadius * 2.0f)) continue; // Hit a m_pPlayer, give him damage and stuffs... - GameServer()->CreateSound(apEnts[i]->m_Pos, SOUND_NINJA_HIT); + GameServer()->CreateSound(aEnts[i]->m_Pos, SOUND_NINJA_HIT); // set his velocity to fast upward (for now) if(m_NumObjectsHit < 10) - m_apHitObjects[m_NumObjectsHit++] = apEnts[i]; + m_apHitObjects[m_NumObjectsHit++] = aEnts[i]; - apEnts[i]->TakeDamage(vec2(0, 10.0f), g_pData->m_Weapons.m_Ninja.m_pBase->m_Damage, m_pPlayer->GetCID(), WEAPON_NINJA); + aEnts[i]->TakeDamage(vec2(0, 10.0f), g_pData->m_Weapons.m_Ninja.m_pBase->m_Damage, m_pPlayer->GetCID(), WEAPON_NINJA); } } @@ -329,28 +329,26 @@ void CCharacter::FireWeapon() if (!g_Config.m_SvHit) break; - CCharacter *apEnts[64]; + CCharacter *apEnts[MAX_CLIENTS]; int Hits = 0; int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)apEnts, - 64, NETOBJTYPE_CHARACTER); + MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); for (int i = 0; i < Num; ++i) { CCharacter *pTarget = apEnts[i]; - //for DDRace mod or any other mod, which needs hammer hits through the wall remove second condition if ((pTarget == this || !CanCollide(pTarget->GetPlayer()->GetCID())) /*|| GameServer()->Collision()->IntersectLine(ProjStartPos, pTarget->m_Pos, NULL, NULL)*/) continue; // set his velocity to fast upward (for now) GameServer()->CreateHammerHit(m_Pos, Teams()->TeamMask(Team())); - apEnts[i]->TakeDamage(vec2(0.f, -1.f), g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage, m_pPlayer->GetCID(), m_ActiveWeapon); - vec2 Dir; if (length(pTarget->m_Pos - m_Pos) > 0.0f) Dir = normalize(pTarget->m_Pos - m_Pos); else Dir = vec2(0.f, -1.f); + vec2 Temp = pTarget->m_Core.m_Vel + normalize(Dir + vec2(0.f, -1.1f)) * 10.0f * (m_HammerType + 1); if(Temp.x > 0 && ((pTarget->m_TileIndex == TILE_STOP && pTarget->m_TileFlags == ROTATION_270) || (pTarget->m_TileIndexL == TILE_STOP && pTarget->m_TileFlagsL == ROTATION_270) || (pTarget->m_TileIndexL == TILE_STOPS && (pTarget->m_TileFlagsL == ROTATION_90 || pTarget->m_TileFlagsL ==ROTATION_270)) || (pTarget->m_TileIndexL == TILE_STOPA) || (pTarget->m_TileFIndex == TILE_STOP && pTarget->m_TileFFlags == ROTATION_270) || (pTarget->m_TileFIndexL == TILE_STOP && pTarget->m_TileFFlagsL == ROTATION_270) || (pTarget->m_TileFIndexL == TILE_STOPS && (pTarget->m_TileFFlagsL == ROTATION_90 || pTarget->m_TileFFlagsL == ROTATION_270)) || (pTarget->m_TileFIndexL == TILE_STOPA) || (pTarget->m_TileSIndex == TILE_STOP && pTarget->m_TileSFlags == ROTATION_270) || (pTarget->m_TileSIndexL == TILE_STOP && pTarget->m_TileSFlagsL == ROTATION_270) || (pTarget->m_TileSIndexL == TILE_STOPS && (pTarget->m_TileSFlagsL == ROTATION_90 || pTarget->m_TileSFlagsL == ROTATION_270)) || (pTarget->m_TileSIndexL == TILE_STOPA))) Temp.x = 0; @@ -360,7 +358,9 @@ void CCharacter::FireWeapon() Temp.y = 0; if(Temp.y > 0 && ((pTarget->m_TileIndex == TILE_STOP && pTarget->m_TileFlags == ROTATION_0) || (pTarget->m_TileIndexT == TILE_STOP && pTarget->m_TileFlagsT == ROTATION_0) || (pTarget->m_TileIndexT == TILE_STOPS && (pTarget->m_TileFlagsT == ROTATION_0 || pTarget->m_TileFlagsT == ROTATION_180)) || (pTarget->m_TileIndexT == TILE_STOPA) || (pTarget->m_TileFIndex == TILE_STOP && pTarget->m_TileFFlags == ROTATION_0) || (pTarget->m_TileFIndexT == TILE_STOP && pTarget->m_TileFFlagsT == ROTATION_0) || (pTarget->m_TileFIndexT == TILE_STOPS && (pTarget->m_TileFFlagsT == ROTATION_0 || pTarget->m_TileFFlagsT == ROTATION_180)) || (pTarget->m_TileFIndexT == TILE_STOPA) || (pTarget->m_TileSIndex == TILE_STOP && pTarget->m_TileSFlags == ROTATION_0) || (pTarget->m_TileSIndexT == TILE_STOP && pTarget->m_TileSFlagsT == ROTATION_0) || (pTarget->m_TileSIndexT == TILE_STOPS && (pTarget->m_TileSFlagsT == ROTATION_0 || pTarget->m_TileSFlagsT == ROTATION_180)) || (pTarget->m_TileSIndexT == TILE_STOPA))) Temp.y = 0; - pTarget->m_Core.m_Vel = Temp; + Temp -= pTarget->m_Core.m_Vel; + pTarget->TakeDamage(vec2(0.f, -1.f) + Temp, g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage, + m_pPlayer->GetCID(), m_ActiveWeapon); pTarget->UnFreeze(); Hits++; } diff --git a/src/game/server/entities/flag.cpp b/src/game/server/entities/flag.cpp index 139bc7446..cff6f10cc 100644 --- a/src/game/server/entities/flag.cpp +++ b/src/game/server/entities/flag.cpp @@ -5,7 +5,7 @@ #include "flag.h" CFlag::CFlag(CGameWorld *pGameWorld, int Team) -: CEntity(pGameWorld, NETOBJTYPE_FLAG) +: CEntity(pGameWorld, CGameWorld::ENTTYPE_FLAG) { m_Team = Team; m_ProximityRadius = ms_PhysSize; diff --git a/src/game/server/entities/laser.cpp b/src/game/server/entities/laser.cpp index 47301660f..f5fc11736 100644 --- a/src/game/server/entities/laser.cpp +++ b/src/game/server/entities/laser.cpp @@ -6,7 +6,7 @@ #include "laser.h" CLaser::CLaser(CGameWorld *pGameWorld, vec2 Pos, vec2 Direction, float StartEnergy, int Owner, int Type) -: CEntity(pGameWorld, NETOBJTYPE_LASER) +: CEntity(pGameWorld, CGameWorld::ENTTYPE_LASER) { m_Pos = Pos; m_Owner = Owner; diff --git a/src/game/server/entities/pickup.cpp b/src/game/server/entities/pickup.cpp index a0b7222a7..09f965a26 100644 --- a/src/game/server/entities/pickup.cpp +++ b/src/game/server/entities/pickup.cpp @@ -5,7 +5,7 @@ #include "pickup.h" CPickup::CPickup(CGameWorld *pGameWorld, int Type, int SubType, int Layer, int Number) -: CEntity(pGameWorld, NETOBJTYPE_PICKUP) +: CEntity(pGameWorld, CGameWorld::ENTTYPE_PICKUP) { m_Layer = Layer; m_Number = Number; @@ -121,16 +121,21 @@ void CPickup::Tick() } break; - case POWERUP_NINJA: + case POWERUP_NINJA: + { + // activate ninja on target player + pChr->GiveNinja(); + //RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; + + /*// loop through all players, setting their emotes + CCharacter *pC = static_cast(GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER)); + for(; pC; pC = (CCharacter *)pC->TypeNext()) { - // activate ninja on target player - //if(!pChr->m_FreezeTime) pChr->GiveNinja(); - pChr->GiveNinja(); - //RespawnTime = g_pData->m_aPickups[m_Type].m_Respawntime; - - break; - } - + if (pC != pChr) + pC->SetEmote(EMOTE_SURPRISE, Server()->Tick() + Server()->TickSpeed()); + }*/ + break; + } default: break; }; diff --git a/src/game/server/entities/projectile.cpp b/src/game/server/entities/projectile.cpp index 80fc0d407..5df88bad3 100644 --- a/src/game/server/entities/projectile.cpp +++ b/src/game/server/entities/projectile.cpp @@ -22,7 +22,7 @@ CProjectile::CProjectile int Layer, int Number ) -: CEntity(pGameWorld, NETOBJTYPE_PROJECTILE) +: CEntity(pGameWorld, CGameWorld::ENTTYPE_PROJECTILE) { m_Layer = Layer; m_Number = Number; diff --git a/src/game/server/entity.cpp b/src/game/server/entity.cpp index 5241c06b1..aff36943c 100644 --- a/src/game/server/entity.cpp +++ b/src/game/server/entity.cpp @@ -11,15 +11,13 @@ CEntity::CEntity(CGameWorld *pGameWorld, int ObjType) { m_pGameWorld = pGameWorld; - m_Objtype = ObjType; + m_ObjType = ObjType; m_Pos = vec2(0,0); m_ProximityRadius = 0; m_MarkedForDestroy = false; m_Id = Server()->SnapNewID(); - m_pNextEntity = 0; - m_pPrevEntity = 0; m_pPrevTypeEntity = 0; m_pNextTypeEntity = 0; } diff --git a/src/game/server/entity.h b/src/game/server/entity.h index 237822c73..ebdd0bf1f 100644 --- a/src/game/server/entity.h +++ b/src/game/server/entity.h @@ -57,11 +57,8 @@ class CEntity { MACRO_ALLOC_HEAP() -private: - friend class CGameWorld; // thy these? - CEntity *m_pPrevEntity; - CEntity *m_pNextEntity; + friend class CGameWorld; // entity list handling CEntity *m_pPrevTypeEntity; CEntity *m_pNextTypeEntity; @@ -69,7 +66,7 @@ private: protected: bool m_MarkedForDestroy; int m_Id; - int m_Objtype; + int m_ObjType; int m_Number; int m_Layer; public: diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp index 6deaf8838..9144462cd 100644 --- a/src/game/server/gamecontext.cpp +++ b/src/game/server/gamecontext.cpp @@ -138,10 +138,10 @@ void CGameContext::CreateExplosion(vec2 P, int Owner, int Weapon, bool NoDamage, /*if(!NoDamage) {*/ // deal damage - CCharacter *apEnts[64]; + CCharacter *apEnts[MAX_CLIENTS]; float Radius = 135.0f; float InnerRadius = 48.0f; - int Num = m_World.FindEntities(P, Radius, (CEntity**)apEnts, 64, NETOBJTYPE_CHARACTER); + int Num = m_World.FindEntities(P, Radius, (CEntity**)apEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); for(int i = 0; i < Num; i++) { vec2 Diff = apEnts[i]->m_Pos - P; diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp index b427c4b54..3ed5fdd59 100644 --- a/src/game/server/gamecontroller.cpp +++ b/src/game/server/gamecontroller.cpp @@ -57,7 +57,7 @@ IGameController::~IGameController() float IGameController::EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos) { float Score = 0.0f; - CCharacter *pC = static_cast(GameServer()->m_World.FindFirst(NETOBJTYPE_CHARACTER)); + CCharacter *pC = static_cast(GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_CHARACTER)); for(; pC; pC = (CCharacter *)pC->TypeNext()) { // team mates are not as dangerous as enemies @@ -66,10 +66,7 @@ float IGameController::EvaluateSpawnPos(CSpawnEval *pEval, vec2 Pos) Scoremod = 0.5f; float d = distance(Pos, pC->m_Pos); - if(d == 0) - Score += 1000000000.0f; - else - Score += 1.0f/d; + Score += Scoremod * (d == 0 ? 1000000000.0f : 1.0f/d); } return Score; @@ -840,7 +837,7 @@ bool IGameController::CheckTeamBalance() char aBuf[256]; if(absolute(aT[0]-aT[1]) >= 2) { - str_format(aBuf, sizeof(aBuf), "Team is NOT balanced (red=%d blue=%d)", aT[0], aT[1]); + str_format(aBuf, sizeof(aBuf), "Teams are NOT balanced (red=%d blue=%d)", aT[0], aT[1]); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); if(GameServer()->m_pController->m_UnbalancedTick == -1) GameServer()->m_pController->m_UnbalancedTick = Server()->Tick(); @@ -848,7 +845,7 @@ bool IGameController::CheckTeamBalance() } else { - str_format(aBuf, sizeof(aBuf), "Team is balanced (red=%d blue=%d)", aT[0], aT[1]); + str_format(aBuf, sizeof(aBuf), "Teams are balanced (red=%d blue=%d)", aT[0], aT[1]); GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf); GameServer()->m_pController->m_UnbalancedTick = -1; return true; diff --git a/src/game/server/gamemodes/ctf.cpp b/src/game/server/gamemodes/ctf.cpp index ed0e111e5..7f2a6a94e 100644 --- a/src/game/server/gamemodes/ctf.cpp +++ b/src/game/server/gamemodes/ctf.cpp @@ -140,7 +140,7 @@ void CGameControllerCTF::Tick() else { CCharacter *apCloseCCharacters[MAX_CLIENTS]; - int Num = GameServer()->m_World.FindEntities(F->m_Pos, CFlag::ms_PhysSize, (CEntity**)apCloseCCharacters, MAX_CLIENTS, NETOBJTYPE_CHARACTER); + int Num = GameServer()->m_World.FindEntities(F->m_Pos, CFlag::ms_PhysSize, (CEntity**)apCloseCCharacters, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); for(int i = 0; i < Num; i++) { if(!apCloseCCharacters[i]->IsAlive() || apCloseCCharacters[i]->GetPlayer()->GetTeam() == TEAM_SPECTATORS || GameServer()->Collision()->IntersectLine(F->m_Pos, apCloseCCharacters[i]->m_Pos, NULL, NULL)) diff --git a/src/game/server/gameworld.cpp b/src/game/server/gameworld.cpp index 5695b030c..e79bfd43a 100644 --- a/src/game/server/gameworld.cpp +++ b/src/game/server/gameworld.cpp @@ -15,16 +15,16 @@ CGameWorld::CGameWorld() m_Paused = false; m_ResetRequested = false; - m_pFirstEntity = 0x0; - for(int i = 0; i < NUM_ENT_TYPES; i++) + for(int i = 0; i < NUM_ENTTYPES; i++) m_apFirstEntityTypes[i] = 0; } CGameWorld::~CGameWorld() { // delete all entities - while(m_pFirstEntity) - delete m_pFirstEntity; + for(int i = 0; i < NUM_ENTTYPES; i++) + while(m_apFirstEntityTypes[i]) + delete m_apFirstEntityTypes[i]; } void CGameWorld::SetGameServer(CGameContext *pGameServer) @@ -35,15 +35,16 @@ void CGameWorld::SetGameServer(CGameContext *pGameServer) CEntity *CGameWorld::FindFirst(int Type) { - return m_apFirstEntityTypes[Type]; + return Type < 0 || Type >= NUM_ENTTYPES ? 0 : m_apFirstEntityTypes[Type]; } - int CGameWorld::FindEntities(vec2 Pos, float Radius, CEntity **ppEnts, int Max, int Type) { + if(Type < 0 || Type >= NUM_ENTTYPES) + return 0; + int Num = 0; - for(CEntity *pEnt = (Type<0) ? m_pFirstEntity : m_apFirstEntityTypes[Type]; - pEnt; pEnt = (Type<0) ? pEnt->m_pNextEntity : pEnt->m_pNextTypeEntity) + for(CEntity *pEnt = m_apFirstEntityTypes[Type]; pEnt; pEnt = pEnt->m_pNextTypeEntity) { if(distance(pEnt->m_Pos, Pos) < Radius+pEnt->m_ProximityRadius) { @@ -59,26 +60,17 @@ int CGameWorld::FindEntities(vec2 Pos, float Radius, CEntity **ppEnts, int Max, void CGameWorld::InsertEntity(CEntity *pEnt) { - CEntity *pCur = m_pFirstEntity; - while(pCur) - { +#ifdef CONF_DEBUG + for(CEntity *pCur = m_apFirstEntityTypes[pEnt->m_ObjType]; pCur; pCur = pCur->m_pNextTypeEntity) dbg_assert(pCur != pEnt, "err"); - pCur = pCur->m_pNextEntity; - } +#endif // insert it - if(m_pFirstEntity) - m_pFirstEntity->m_pPrevEntity = pEnt; - pEnt->m_pNextEntity = m_pFirstEntity; - pEnt->m_pPrevEntity = 0x0; - m_pFirstEntity = pEnt; - - // into typelist aswell - if(m_apFirstEntityTypes[pEnt->m_Objtype]) - m_apFirstEntityTypes[pEnt->m_Objtype]->m_pPrevTypeEntity = pEnt; - pEnt->m_pNextTypeEntity = m_apFirstEntityTypes[pEnt->m_Objtype]; + if(m_apFirstEntityTypes[pEnt->m_ObjType]) + m_apFirstEntityTypes[pEnt->m_ObjType]->m_pPrevTypeEntity = pEnt; + pEnt->m_pNextTypeEntity = m_apFirstEntityTypes[pEnt->m_ObjType]; pEnt->m_pPrevTypeEntity = 0x0; - m_apFirstEntityTypes[pEnt->m_Objtype] = pEnt; + m_apFirstEntityTypes[pEnt->m_ObjType] = pEnt; } void CGameWorld::DestroyEntity(CEntity *pEnt) @@ -89,26 +81,21 @@ void CGameWorld::DestroyEntity(CEntity *pEnt) void CGameWorld::RemoveEntity(CEntity *pEnt) { // not in the list - if(!pEnt->m_pNextEntity && !pEnt->m_pPrevEntity && m_pFirstEntity != pEnt) + if(!pEnt->m_pNextTypeEntity && !pEnt->m_pPrevTypeEntity && m_apFirstEntityTypes[pEnt->m_ObjType] != pEnt) return; // remove - if(pEnt->m_pPrevEntity) - pEnt->m_pPrevEntity->m_pNextEntity = pEnt->m_pNextEntity; - else - m_pFirstEntity = pEnt->m_pNextEntity; - if(pEnt->m_pNextEntity) - pEnt->m_pNextEntity->m_pPrevEntity = pEnt->m_pPrevEntity; - if(pEnt->m_pPrevTypeEntity) pEnt->m_pPrevTypeEntity->m_pNextTypeEntity = pEnt->m_pNextTypeEntity; else - m_apFirstEntityTypes[pEnt->m_Objtype] = pEnt->m_pNextTypeEntity; + m_apFirstEntityTypes[pEnt->m_ObjType] = pEnt->m_pNextTypeEntity; if(pEnt->m_pNextTypeEntity) pEnt->m_pNextTypeEntity->m_pPrevTypeEntity = pEnt->m_pPrevTypeEntity; - pEnt->m_pNextEntity = 0; - pEnt->m_pPrevEntity = 0; + // keep list traversing valid + if(m_pNextTraverseEntity == pEnt) + m_pNextTraverseEntity = pEnt->m_pNextTypeEntity; + pEnt->m_pNextTypeEntity = 0; pEnt->m_pPrevTypeEntity = 0; } @@ -116,15 +103,25 @@ void CGameWorld::RemoveEntity(CEntity *pEnt) // void CGameWorld::Snap(int SnappingClient) { - for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) - pEnt->Snap(SnappingClient); + for(int i = 0; i < NUM_ENTTYPES; i++) + for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; ) + { + m_pNextTraverseEntity = pEnt->m_pNextTypeEntity; + pEnt->Snap(SnappingClient); + pEnt = m_pNextTraverseEntity; + } } void CGameWorld::Reset() { // reset all entities - for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) - pEnt->Reset(); + for(int i = 0; i < NUM_ENTTYPES; i++) + for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; ) + { + m_pNextTraverseEntity = pEnt->m_pNextTypeEntity; + pEnt->Reset(); + pEnt = m_pNextTraverseEntity; + } RemoveEntities(); GameServer()->m_pController->PostReset(); @@ -136,17 +133,17 @@ void CGameWorld::Reset() void CGameWorld::RemoveEntities() { // destroy objects marked for destruction - CEntity *pEnt = m_pFirstEntity; - while(pEnt) - { - CEntity *pNext = pEnt->m_pNextEntity; - if(pEnt->m_MarkedForDestroy) + for(int i = 0; i < NUM_ENTTYPES; i++) + for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; ) { - RemoveEntity(pEnt); - pEnt->Destroy(); + m_pNextTraverseEntity = pEnt->m_pNextTypeEntity; + if(pEnt->m_MarkedForDestroy) + { + RemoveEntity(pEnt); + pEnt->Destroy(); + } + pEnt = m_pNextTraverseEntity; } - pEnt = pNext; - } } void CGameWorld::Tick() @@ -159,11 +156,21 @@ void CGameWorld::Tick() if(GameServer()->m_pController->IsForceBalanced()) GameServer()->SendChat(-1, CGameContext::CHAT_ALL, "Teams have been balanced"); // update all objects - for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) - pEnt->Tick(); + for(int i = 0; i < NUM_ENTTYPES; i++) + for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; ) + { + m_pNextTraverseEntity = pEnt->m_pNextTypeEntity; + pEnt->Tick(); + pEnt = m_pNextTraverseEntity; + } - for(CEntity *pEnt = m_pFirstEntity; pEnt; pEnt = pEnt->m_pNextEntity) - pEnt->TickDefered(); + for(int i = 0; i < NUM_ENTTYPES; i++) + for(CEntity *pEnt = m_apFirstEntityTypes[i]; pEnt; ) + { + m_pNextTraverseEntity = pEnt->m_pNextTypeEntity; + pEnt->TickDefered(); + pEnt = m_pNextTraverseEntity; + } } RemoveEntities(); @@ -178,7 +185,7 @@ CCharacter *CGameWorld::IntersectCharacter(vec2 Pos0, vec2 Pos1, float Radius, v vec2 LineDir = normalize(Pos1-Pos0); CCharacter *pClosest = 0; - CCharacter *p = (CCharacter *)FindFirst(NETOBJTYPE_CHARACTER); + CCharacter *p = (CCharacter *)FindFirst(ENTTYPE_CHARACTER); for(; p; p = (CCharacter *)p->TypeNext()) { if(p == pNotThis) @@ -208,7 +215,7 @@ CCharacter *CGameWorld::ClosestCharacter(vec2 Pos, float Radius, CEntity *pNotTh float ClosestRange = Radius*2; CCharacter *pClosest = 0; - CCharacter *p = (CCharacter *)GameServer()->m_World.FindFirst(NETOBJTYPE_CHARACTER); + CCharacter *p = (CCharacter *)GameServer()->m_World.FindFirst(ENTTYPE_CHARACTER); for(; p; p = (CCharacter *)p->TypeNext()) { if(p == pNotThis) @@ -262,4 +269,4 @@ void CGameWorld::ReleaseHooked(int ClientId) p->m_Core.m_HookState = HOOK_RETRACTED; } -} \ No newline at end of file +} diff --git a/src/game/server/gameworld.h b/src/game/server/gameworld.h index 142ef4b51..d9b1a9d8f 100644 --- a/src/game/server/gameworld.h +++ b/src/game/server/gameworld.h @@ -16,17 +16,23 @@ class CCharacter; */ class CGameWorld { +public: + enum + { + ENTTYPE_PROJECTILE = 0, + ENTTYPE_LASER, + ENTTYPE_PICKUP, + ENTTYPE_FLAG, + ENTTYPE_CHARACTER, + NUM_ENTTYPES + }; + +private: void Reset(); void RemoveEntities(); - enum - { - NUM_ENT_TYPES=10, // TODO: are more exact value perhaps? :) - }; - - // TODO: two lists seams kinda not good, shouldn't be needed - CEntity *m_pFirstEntity; - CEntity *m_apFirstEntityTypes[NUM_ENT_TYPES]; + CEntity *m_pNextTraverseEntity; + CEntity *m_apFirstEntityTypes[NUM_ENTTYPES]; class CGameContext *m_pGameServer; class IServer *m_pServer; @@ -44,7 +50,6 @@ public: void SetGameServer(CGameContext *pGameServer); - CEntity *FindFirst() { return m_pFirstEntity; } CEntity *FindFirst(int Type); /* @@ -57,12 +62,12 @@ public: ents - Pointer to a list that should be filled with the pointers to the entities. max - Number of entities that fits into the ents array. - type - Type of the entities to find. -1 for all types. + type - Type of the entities to find. Returns: Number of entities found and added to the ents array. */ - int FindEntities(vec2 Pos, float Radius, CEntity **ppEnts, int Max, int Type = -1); + int FindEntities(vec2 Pos, float Radius, CEntity **ppEnts, int Max, int Type); /* Function: InterserctCharacters diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp index 1d5dc1500..9b43410ce 100644 --- a/src/game/server/player.cpp +++ b/src/game/server/player.cpp @@ -1,11 +1,9 @@ /* (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 //TODO:GFX check if linux still needs this +#include #include #include -#include - #include "player.h" #include "gamecontext.h" #include @@ -46,6 +44,9 @@ CPlayer::~CPlayer() void CPlayer::Tick() { +#ifdef CONF_DEBUG + if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS-g_Config.m_DbgDummies) +#endif if(!Server()->ClientIngame(m_ClientID)) return; @@ -94,6 +95,9 @@ void CPlayer::Tick() void CPlayer::Snap(int SnappingClient) { +#ifdef CONF_DEBUG + if(!g_Config.m_DbgDummies || m_ClientID < MAX_CLIENTS-g_Config.m_DbgDummies) +#endif if(!Server()->ClientIngame(m_ClientID)) return; @@ -239,7 +243,7 @@ void CPlayer::TryRespawn() // check if the position is occupado CEntity *apEnts[2] = {0}; - int NumEnts = GameServer()->m_World.FindEntities(SpawnPos, 64, apEnts, 2, NETOBJTYPE_CHARACTER); + int NumEnts = GameServer()->m_World.FindEntities(SpawnPos, 64, apEnts, 2, CGameWorld::ENTTYPE_CHARACTER); if(NumEnts < 3) { m_Spawning = false; diff --git a/src/game/variables.h b/src/game/variables.h index 5b8b364c1..fc163e66d 100644 --- a/src/game/variables.h +++ b/src/game/variables.h @@ -25,7 +25,7 @@ MACRO_CONFIG_INT(ClMouseMaxDistance, cl_mouse_max_distance, 800, 0, 0, CFGFLAG_C MACRO_CONFIG_INT(EdShowkeys, ed_showkeys, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "", -1) -MACRO_CONFIG_INT(ClFlow, cl_flow, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "", -1) +//MACRO_CONFIG_INT(ClFlow, cl_flow, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "", -1) MACRO_CONFIG_INT(ClShowWelcome, cl_show_welcome, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "", -1) MACRO_CONFIG_INT(ClMotdTime, cl_motd_time, 10, 0, 100, CFGFLAG_CLIENT|CFGFLAG_SAVE, "How long to show the server message of the day", -1)