diff --git a/CMakeLists.txt b/CMakeLists.txt index fbd9982cb..8b8ae1711 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1543,6 +1543,7 @@ set(EXPECTED_DATA menuimages/play_game.png menuimages/settings.png particles.png + race_flag.png shader/pipeline.frag shader/pipeline.vert shader/prim.frag @@ -2194,10 +2195,10 @@ if(CLIENT) components/ghost.h components/hud.cpp components/hud.h + components/infomessages.cpp + components/infomessages.h components/items.cpp components/items.h - components/killmessages.cpp - components/killmessages.h components/mapimages.cpp components/mapimages.h components/maplayers.cpp diff --git a/data/race_flag.png b/data/race_flag.png new file mode 100644 index 000000000..c9ceba5b8 Binary files /dev/null and b/data/race_flag.png differ diff --git a/datasrc/content.py b/datasrc/content.py index 73bc6bcaa..a9403f2bf 100644 --- a/datasrc/content.py +++ b/datasrc/content.py @@ -255,6 +255,7 @@ container.images.Add(image_audio_source) container.images.Add(image_strongweak) container.images.Add(image_hud) container.images.Add(image_extras) +container.images.Add(Image("raceflag", "race_flag.png")) container.pickups.Add(Pickup("health")) container.pickups.Add(Pickup("armor")) diff --git a/datasrc/network.py b/datasrc/network.py index cc092b55f..898556651 100644 --- a/datasrc/network.py +++ b/datasrc/network.py @@ -558,4 +558,12 @@ Messages = [ NetMessageEx("Sv_YourVote", "yourvote@netmsg.ddnet.org", [ NetIntRange("m_Voted", -1, 1), ]), + + NetMessageEx("Sv_RaceFinish", "racefinish@netmsg.ddnet.org", [ + NetIntRange("m_ClientID", 0, 'MAX_CLIENTS-1'), + NetIntAny("m_Time"), + NetIntAny("m_Diff"), + NetBool("m_RecordPersonal"), + NetBool("m_RecordServer", default=False), + ]), ] diff --git a/src/base/system.cpp b/src/base/system.cpp index 877daebc0..9402051c8 100644 --- a/src/base/system.cpp +++ b/src/base/system.cpp @@ -3453,8 +3453,12 @@ int str_time(int64_t centisecs, int format, char *buffer, int buffer_size) (centisecs % hour) / min, (centisecs % min) / sec, centisecs % sec); [[fallthrough]]; case TIME_MINS_CENTISECS: - return str_format(buffer, buffer_size, "%02" PRId64 ":%02" PRId64 ".%02" PRId64, centisecs / min, - (centisecs % min) / sec, centisecs % sec); + if(centisecs >= min) + return str_format(buffer, buffer_size, "%02" PRId64 ":%02" PRId64 ".%02" PRId64, centisecs / min, + (centisecs % min) / sec, centisecs % sec); + [[fallthrough]]; + case TIME_SECS_CENTISECS: + return str_format(buffer, buffer_size, "%02" PRId64 ".%02" PRId64, (centisecs % min) / sec, centisecs % sec); } return -1; diff --git a/src/base/system.h b/src/base/system.h index b27d853fb..b10cf5660 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -1754,6 +1754,7 @@ enum TIME_MINS, TIME_HOURS_CENTISECS, TIME_MINS_CENTISECS, + TIME_SECS_CENTISECS, }; /* diff --git a/src/game/client/components/infomessages.cpp b/src/game/client/components/infomessages.cpp index fbf87b837..1b1b6025a 100644 --- a/src/game/client/components/infomessages.cpp +++ b/src/game/client/components/infomessages.cpp @@ -18,24 +18,28 @@ void CInfoMessages::OnWindowResize() { for(auto &InfoMsg : m_aInfoMsgs) { - TextRender()->DeleteTextContainer(InfoMsg.m_VictimTextContainerIndex); - TextRender()->DeleteTextContainer(InfoMsg.m_KillerTextContainerIndex); + DeleteTextContainers(&InfoMsg); } } void CInfoMessages::OnReset() { m_InfoMsgCurrent = 0; - for(auto &InfoMsg : m_aInfoMsgs) { InfoMsg.m_Tick = -100000; - - TextRender()->DeleteTextContainer(InfoMsg.m_VictimTextContainerIndex); - TextRender()->DeleteTextContainer(InfoMsg.m_KillerTextContainerIndex); + DeleteTextContainers(&InfoMsg); } } +void CInfoMessages::DeleteTextContainers(CInfoMsg *pInfoMsg) +{ + TextRender()->DeleteTextContainer(pInfoMsg->m_VictimTextContainerIndex); + TextRender()->DeleteTextContainer(pInfoMsg->m_KillerTextContainerIndex); + TextRender()->DeleteTextContainer(pInfoMsg->m_DiffTextContainerIndex); + TextRender()->DeleteTextContainer(pInfoMsg->m_TimeTextContainerIndex); +} + void CInfoMessages::OnInit() { Graphics()->SetColor(1.f, 1.f, 1.f, 1.f); @@ -61,21 +65,22 @@ void CInfoMessages::OnInit() Graphics()->QuadContainerUpload(m_SpriteQuadContainerIndex); } -void CInfoMessages::AddInfoMsg(int Type, CInfoMsg NewMsg) +void CInfoMessages::AddInfoMsg(EType Type, CInfoMsg NewMsg) { NewMsg.m_Type = Type; NewMsg.m_Tick = Client()->GameTick(g_Config.m_ClDummy); - m_InfoMsgCurrent = (m_InfoMsgCurrent+1)%MAX_INFOMSGS; + m_InfoMsgCurrent = (m_InfoMsgCurrent + 1) % MAX_INFOMSGS; + DeleteTextContainers(&m_aInfoMsgs[m_InfoMsgCurrent]); m_aInfoMsgs[m_InfoMsgCurrent] = NewMsg; } -void CInfoMessages::CreateKillmessageNamesIfNotCreated(CInfoMsg *pInfoMsg) +void CInfoMessages::CreateNamesIfNotCreated(CInfoMsg *pInfoMsg) { const float FontSize = 36.0f; if(!pInfoMsg->m_VictimTextContainerIndex.Valid() && pInfoMsg->m_aVictimName[0] != 0) { - pInfoMsg->m_VictimTextWidth = TextRender()->TextWidth(FontSize, pInfoMsg->m_aVictimName, -1, -1.0f); + pInfoMsg->m_VictimTextWidth = TextRender()->TextWidth(FontSize, pInfoMsg->m_aVictimName); CTextCursor Cursor; TextRender()->SetCursor(&Cursor, 0, 0, FontSize, TEXTFLAG_RENDER); @@ -93,7 +98,7 @@ void CInfoMessages::CreateKillmessageNamesIfNotCreated(CInfoMsg *pInfoMsg) if(!pInfoMsg->m_KillerTextContainerIndex.Valid() && pInfoMsg->m_aKillerName[0] != 0) { - pInfoMsg->m_KillerTextWidth = TextRender()->TextWidth(FontSize, pInfoMsg->m_aKillerName, -1, -1.0f); + pInfoMsg->m_KillerTextWidth = TextRender()->TextWidth(FontSize, pInfoMsg->m_aKillerName); CTextCursor Cursor; TextRender()->SetCursor(&Cursor, 0, 0, FontSize, TEXTFLAG_RENDER); @@ -111,6 +116,39 @@ void CInfoMessages::CreateKillmessageNamesIfNotCreated(CInfoMsg *pInfoMsg) TextRender()->TextColor(TextRender()->DefaultTextColor()); } +void CInfoMessages::CreateFinishTextContainersIfNotCreated(CInfoMsg *pInfoMsg) +{ + const float FontSize = 36.0f; + if(!pInfoMsg->m_DiffTextContainerIndex.Valid() && pInfoMsg->m_aDiffText[0] != 0) + { + pInfoMsg->m_DiffTextWidth = TextRender()->TextWidth(FontSize, pInfoMsg->m_aDiffText); + CTextCursor Cursor; + TextRender()->SetCursor(&Cursor, 0, 0, FontSize, TEXTFLAG_RENDER); + Cursor.m_LineWidth = -1; + + if(pInfoMsg->m_Diff > 0) + TextRender()->TextColor(1.0f, 0.5f, 0.5f, 1); // red + else if(pInfoMsg->m_Diff < 0) + TextRender()->TextColor(0.5f, 1.0f, 0.5f, 1); // green + else + TextRender()->TextColor(TextRender()->DefaultTextColor()); + + TextRender()->CreateTextContainer(pInfoMsg->m_DiffTextContainerIndex, &Cursor, pInfoMsg->m_aDiffText); + } + if(!pInfoMsg->m_TimeTextContainerIndex.Valid() && pInfoMsg->m_aTimeText[0] != 0) + { + pInfoMsg->m_TimeTextWidth = TextRender()->TextWidth(FontSize, pInfoMsg->m_aTimeText); + CTextCursor Cursor; + TextRender()->SetCursor(&Cursor, 0, 0, FontSize, TEXTFLAG_RENDER); + Cursor.m_LineWidth = -1; + + TextRender()->TextColor(TextRender()->DefaultTextColor()); + + TextRender()->CreateTextContainer(pInfoMsg->m_TimeTextContainerIndex, &Cursor, pInfoMsg->m_aTimeText); + } + TextRender()->TextColor(TextRender()->DefaultTextColor()); +} + void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) { if(m_pClient->m_SuppressEvents) @@ -121,7 +159,6 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) CNetMsg_Sv_KillMsgTeam *pMsg = (CNetMsg_Sv_KillMsgTeam *)pRawMsg; CInfoMsg Kill{}; - Kill.m_Type = INFOMSG_KILL; std::vector> vStrongWeakSorted; for(int i = 0; i < MAX_CLIENTS; i++) @@ -166,7 +203,6 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) Kill.m_Weapon = -1; Kill.m_ModeSpecial = 0; - Kill.m_Tick = Client()->GameTick(g_Config.m_ClDummy); Kill.m_VictimTextWidth = Kill.m_KillerTextWidth = 0.f; @@ -177,7 +213,7 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1); Graphics()->MapScreen(0, 0, Width * 1.5f, Height * 1.5f); - CreateKillmessageNamesIfNotCreated(&Kill); + CreateNamesIfNotCreated(&Kill); bool KillMsgValid = true; for(int i = 0; i < Kill.m_TeamSize; i++) @@ -187,18 +223,11 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) if(KillMsgValid) { - // add the message - m_InfoMsgCurrent = (m_InfoMsgCurrent + 1) % MAX_INFOMSGS; - - TextRender()->DeleteTextContainer(m_aInfoMsgs[m_InfoMsgCurrent].m_VictimTextContainerIndex); - TextRender()->DeleteTextContainer(m_aInfoMsgs[m_InfoMsgCurrent].m_KillerTextContainerIndex); - - m_aInfoMsgs[m_InfoMsgCurrent] = Kill; + AddInfoMsg(EType::TYPE_KILL, Kill); } else { - TextRender()->DeleteTextContainer(Kill.m_VictimTextContainerIndex); - TextRender()->DeleteTextContainer(Kill.m_KillerTextContainerIndex); + DeleteTextContainers(&Kill); } Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); @@ -209,7 +238,6 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) CNetMsg_Sv_KillMsg *pMsg = (CNetMsg_Sv_KillMsg *)pRawMsg; CInfoMsg Kill{}; - Kill.m_Type = INFOMSG_KILL; Kill.m_TeamSize = 1; Kill.m_aVictimIds[0] = pMsg->m_Victim; @@ -244,7 +272,6 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) Kill.m_Weapon = pMsg->m_Weapon; Kill.m_ModeSpecial = pMsg->m_ModeSpecial; - 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; @@ -257,28 +284,75 @@ void CInfoMessages::OnMessage(int MsgType, void *pRawMsg) Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1); Graphics()->MapScreen(0, 0, Width * 1.5f, Height * 1.5f); - CreateKillmessageNamesIfNotCreated(&Kill); + CreateNamesIfNotCreated(&Kill); bool KillMsgValid = (Kill.m_aVictimRenderInfo[0].m_CustomColoredSkin && Kill.m_aVictimRenderInfo[0].m_ColorableRenderSkin.m_Body.IsValid()) || (!Kill.m_aVictimRenderInfo[0].m_CustomColoredSkin && Kill.m_aVictimRenderInfo[0].m_OriginalRenderSkin.m_Body.IsValid()); KillMsgValid &= Kill.m_KillerID == -1 || ((Kill.m_KillerRenderInfo.m_CustomColoredSkin && Kill.m_KillerRenderInfo.m_ColorableRenderSkin.m_Body.IsValid()) || (!Kill.m_KillerRenderInfo.m_CustomColoredSkin && Kill.m_KillerRenderInfo.m_OriginalRenderSkin.m_Body.IsValid())); if(KillMsgValid) { - // add the message - m_InfoMsgCurrent = (m_InfoMsgCurrent + 1) % MAX_INFOMSGS; - - TextRender()->DeleteTextContainer(m_aInfoMsgs[m_InfoMsgCurrent].m_VictimTextContainerIndex); - TextRender()->DeleteTextContainer(m_aInfoMsgs[m_InfoMsgCurrent].m_KillerTextContainerIndex); - - m_aInfoMsgs[m_InfoMsgCurrent] = Kill; + AddInfoMsg(EType::TYPE_KILL, Kill); } else { - TextRender()->DeleteTextContainer(Kill.m_VictimTextContainerIndex); - TextRender()->DeleteTextContainer(Kill.m_KillerTextContainerIndex); + DeleteTextContainers(&Kill); } Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); } + + if(MsgType == NETMSGTYPE_SV_RACEFINISH) + { + CNetMsg_Sv_RaceFinish *pMsg = (CNetMsg_Sv_RaceFinish *)pRawMsg; + + char aBuf[256]; + + CInfoMsg Finish; + Finish.m_TeamSize = 1; + Finish.m_aVictimIds[0] = pMsg->m_ClientID; + Finish.m_VictimDDTeam = m_pClient->m_Teams.Team(Finish.m_aVictimIds[0]); + str_copy(Finish.m_aVictimName, m_pClient->m_aClients[Finish.m_aVictimIds[0]].m_aName); + Finish.m_aVictimRenderInfo[0] = m_pClient->m_aClients[pMsg->m_ClientID].m_RenderInfo; + + Finish.m_aKillerName[0] = '\0'; + + Finish.m_Diff = pMsg->m_Diff; + Finish.m_RecordPersonal = (pMsg->m_RecordPersonal || pMsg->m_RecordServer); + + // diff time text + if(Finish.m_Diff) + { + if(Finish.m_Diff < 0) + { + str_time_float(-Finish.m_Diff / 1000.0f, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)); + str_format(Finish.m_aDiffText, sizeof(Finish.m_aDiffText), "(-%s)", aBuf); + } + else + { + str_time_float(Finish.m_Diff / 1000.0f, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)); + str_format(Finish.m_aDiffText, sizeof(Finish.m_aDiffText), "(+%s)", aBuf); + } + } + else + { + Finish.m_aDiffText[0] = '\0'; + } + + // finish time text + str_time_float(pMsg->m_Time / 1000.0f, TIME_HOURS_CENTISECS, Finish.m_aTimeText, sizeof(Finish.m_aTimeText)); + + float ScreenX0, ScreenY0, ScreenX1, ScreenY1; + float Height = 400 * 3.0f; + float Width = Height * Graphics()->ScreenAspect(); + Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1); + Graphics()->MapScreen(0, 0, Width * 1.5f, Height * 1.5f); + + CreateNamesIfNotCreated(&Finish); + CreateFinishTextContainersIfNotCreated(&Finish); + + AddInfoMsg(EType::TYPE_FINISH, Finish); + + Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); + } } void CInfoMessages::RenderKillMsg(CInfoMsg *pInfoMsg, float x, float y) @@ -291,7 +365,7 @@ void CInfoMessages::RenderKillMsg(CInfoMsg *pInfoMsg, float x, float y) else TextColor = TextRender()->DefaultTextColor(); - CreateKillmessageNamesIfNotCreated(pInfoMsg); + CreateNamesIfNotCreated(pInfoMsg); if(pInfoMsg->m_VictimTextContainerIndex.Valid()) TextRender()->RenderTextContainer(pInfoMsg->m_VictimTextContainerIndex, TextColor, TextRender()->DefaultTextOutlineColor(), x, y + (46.f - 36.f) / 2.f); @@ -380,12 +454,60 @@ void CInfoMessages::RenderKillMsg(CInfoMsg *pInfoMsg, float x, float y) } } +void CInfoMessages::RenderFinishMsg(CInfoMsg *pInfoMsg, float x, float y) +{ + // render time diff + CreateFinishTextContainersIfNotCreated(pInfoMsg); + + if(pInfoMsg->m_Diff) + { + x -= pInfoMsg->m_DiffTextWidth; + + if(pInfoMsg->m_DiffTextContainerIndex.Valid()) + TextRender()->RenderTextContainer(pInfoMsg->m_DiffTextContainerIndex, TextRender()->DefaultTextColor(), TextRender()->DefaultTextOutlineColor(), x, y + (46.f - 36.f) / 2.f); + } + + // render time + x -= pInfoMsg->m_TimeTextWidth; + + if(pInfoMsg->m_TimeTextContainerIndex.Valid()) + TextRender()->RenderTextContainer(pInfoMsg->m_TimeTextContainerIndex, TextRender()->DefaultTextColor(), TextRender()->DefaultTextOutlineColor(), x, y + (46.f - 36.f) / 2.f); + + // render flag + x -= 52.0f; + + Graphics()->TextureSet(g_pData->m_aImages[IMAGE_RACEFLAG].m_Id); + Graphics()->QuadsBegin(); + IGraphics::CQuadItem QuadItem(x, y, 52, 52); + Graphics()->QuadsDrawTL(&QuadItem, 1); + Graphics()->QuadsEnd(); + + // render victim name + ColorRGBA TextColor; + x -= pInfoMsg->m_VictimTextWidth; + if(g_Config.m_ClChatTeamColors && pInfoMsg->m_VictimDDTeam) + TextColor = m_pClient->GetDDTeamColor(pInfoMsg->m_VictimDDTeam, 0.75f); + else + TextColor = TextRender()->DefaultTextColor(); + + CreateNamesIfNotCreated(pInfoMsg); + + if(pInfoMsg->m_VictimTextContainerIndex.Valid()) + TextRender()->RenderTextContainer(pInfoMsg->m_VictimTextContainerIndex, TextColor, TextRender()->DefaultTextOutlineColor(), x, y + (46.f - 36.f) / 2.f); + + // render victim tee + x -= 24.0f; + + const CAnimState *pIdleState = CAnimState::GetIdle(); + vec2 OffsetToMid; + RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &pInfoMsg->m_aVictimRenderInfo[0], OffsetToMid); + const vec2 TeeRenderPos = vec2(x, y + 46.0f / 2.0f + OffsetToMid.y); + const int Emote = pInfoMsg->m_RecordPersonal ? EMOTE_HAPPY : EMOTE_NORMAL; + RenderTools()->RenderTee(pIdleState, &pInfoMsg->m_aVictimRenderInfo[0], Emote, vec2(-1, 0), TeeRenderPos); +} void CInfoMessages::OnRender() { - if(!g_Config.m_ClShowKillMessages) - return; - float Height = 400 * 3.0f; float Width = Height * Graphics()->ScreenAspect(); @@ -397,12 +519,14 @@ void CInfoMessages::OnRender() for(int i = 1; i <= MAX_INFOMSGS; i++) { - int r = (m_KillmsgCurrent + i) % MAX_KILLMSGS; - if(Client()->GameTick(g_Config.m_ClDummy) > m_aKillmsgs[r].m_Tick + Client()->GameTickSpeed() * 10) + CInfoMsg *pInfoMsg = &m_aInfoMsgs[(m_InfoMsgCurrent + i) % MAX_INFOMSGS]; + if(Client()->GameTick(g_Config.m_ClDummy) > pInfoMsg->m_Tick + Client()->GameTickSpeed() * 10) continue; - if(pInfoMsg->m_Type == INFOMSG_KILL) + if(pInfoMsg->m_Type == EType::TYPE_KILL && g_Config.m_ClShowKillMessages) RenderKillMsg(pInfoMsg, StartX, y); + else if(pInfoMsg->m_Type == EType::TYPE_FINISH) + RenderFinishMsg(pInfoMsg, StartX, y); y += 46.0f; } diff --git a/src/game/client/components/infomessages.h b/src/game/client/components/infomessages.h index 02a8ae11d..680c46c65 100644 --- a/src/game/client/components/infomessages.h +++ b/src/game/client/components/infomessages.h @@ -12,15 +12,19 @@ class CInfoMessages : public CComponent { MAX_INFOMSGS = 5, MAX_KILLMSG_TEAM_MEMBERS = 4, + }; - INFOMSG_KILL = 0, + enum EType + { + TYPE_KILL, + TYPE_FINISH, }; public: // info messages struct CInfoMsg { - int m_Type; + EType m_Type; int m_Tick; int m_aVictimIds[MAX_KILLMSG_TEAM_MEMBERS]; @@ -40,13 +44,27 @@ public: int m_ModeSpecial; // for CTF, if the guy is carrying a flag for example int m_FlagCarrierBlue; int m_TeamSize; + + // finish msg + int m_Diff; + char m_aTimeText[32]; + char m_aDiffText[32]; + STextContainerIndex m_TimeTextContainerIndex; + STextContainerIndex m_DiffTextContainerIndex; + float m_TimeTextWidth; + float m_DiffTextWidth; + bool m_RecordPersonal; }; private: - void AddInfoMsg(int Type, CInfoMsg NewMsg); + void AddInfoMsg(EType Type, CInfoMsg NewMsg); void RenderKillMsg(CInfoMsg *pInfoMsg, float x, float y); + void RenderFinishMsg(CInfoMsg *pInfoMsg, float x, float y); - void CreateKillmessageNamesIfNotCreated(CInfoMsg *pInfoMsg); + void CreateNamesIfNotCreated(CInfoMsg *pInfoMsg); + void CreateFinishTextContainersIfNotCreated(CInfoMsg *pInfoMsg); + + void DeleteTextContainers(CInfoMsg *pInfoMsg); public: CInfoMsg m_aInfoMsgs[MAX_INFOMSGS]; diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp index 26104ace0..19c929677 100644 --- a/src/game/client/gameclient.cpp +++ b/src/game/client/gameclient.cpp @@ -51,8 +51,8 @@ #include "components/freezebars.h" #include "components/ghost.h" #include "components/hud.h" -#include "components/items.h" #include "components/infomessages.h" +#include "components/items.h" #include "components/mapimages.h" #include "components/maplayers.h" #include "components/mapsounds.h" diff --git a/src/game/client/gameclient.h b/src/game/client/gameclient.h index 5787db748..30856f74d 100644 --- a/src/game/client/gameclient.h +++ b/src/game/client/gameclient.h @@ -34,8 +34,8 @@ #include "components/freezebars.h" #include "components/ghost.h" #include "components/hud.h" -#include "components/items.h" #include "components/infomessages.h" +#include "components/items.h" #include "components/mapimages.h" #include "components/maplayers.h" #include "components/mapsounds.h" diff --git a/src/game/server/teams.cpp b/src/game/server/teams.cpp index 1cff6a384..aa0cd418a 100644 --- a/src/game/server/teams.cpp +++ b/src/game/server/teams.cpp @@ -770,6 +770,18 @@ void CGameTeams::OnFinish(CPlayer *Player, float Time, const char *pTimestamp) Server()->SendPackMsg(&MsgLegacy, MSGFLAG_VITAL, ClientID); } } + + CNetMsg_Sv_RaceFinish RaceFinishMsg; + RaceFinishMsg.m_ClientID = ClientID; + RaceFinishMsg.m_Time = Time * 1000; + RaceFinishMsg.m_Diff = 0; + if(pData->m_BestTime) + { + RaceFinishMsg.m_Diff = Diff * 1000 * (Time < pData->m_BestTime ? -1 : 1); + } + RaceFinishMsg.m_RecordPersonal = (Time < pData->m_BestTime || !pData->m_BestTime); + RaceFinishMsg.m_RecordServer = Time < GameServer()->m_pController->m_CurrentRecord; + Server()->SendPackMsg(&RaceFinishMsg, MSGFLAG_VITAL | MSGFLAG_NORECORD, -1); } else { @@ -781,7 +793,7 @@ void CGameTeams::OnFinish(CPlayer *Player, float Time, const char *pTimestamp) { Msg.m_Diff = Diff * 1000 * (Time < pData->m_BestTime ? -1 : 1); } - Msg.m_RecordPersonal = Time < pData->m_BestTime; + Msg.m_RecordPersonal = (Time < pData->m_BestTime || !pData->m_BestTime); Msg.m_RecordServer = Time < GameServer()->m_pController->m_CurrentRecord; Server()->SendPackMsg(&Msg, MSGFLAG_VITAL | MSGFLAG_NORECORD, -1); } diff --git a/src/test/str.cpp b/src/test/str.cpp index fcd75b705..bb4502149 100644 --- a/src/test/str.cpp +++ b/src/test/str.cpp @@ -757,11 +757,11 @@ TEST(Str, Time) EXPECT_EQ(str_time(123456, TIME_DAYS, aBuf, 0), -1); EXPECT_STREQ(aBuf, "foobar"); - EXPECT_EQ(str_time(123456, TIME_MINS_CENTISECS + 1, aBuf, sizeof(aBuf)), -1); + EXPECT_EQ(str_time(123456, TIME_SECS_CENTISECS + 1, aBuf, sizeof(aBuf)), -1); EXPECT_STREQ(aBuf, ""); - EXPECT_EQ(str_time(-123456, TIME_MINS_CENTISECS, aBuf, sizeof(aBuf)), 8); - EXPECT_STREQ(aBuf, "00:00.00"); + EXPECT_EQ(str_time(-123456, TIME_MINS_CENTISECS, aBuf, sizeof(aBuf)), 5); + EXPECT_STREQ(aBuf, "00.00"); EXPECT_EQ(str_time(INT64_MAX, TIME_DAYS, aBuf, sizeof(aBuf)), 23); EXPECT_STREQ(aBuf, "1067519911673d 00:09:18"); @@ -800,6 +800,13 @@ TEST(Str, Time) EXPECT_STREQ(aBuf, "205:45.67"); EXPECT_EQ(str_time(12345678, TIME_MINS_CENTISECS, aBuf, sizeof(aBuf)), 10); EXPECT_STREQ(aBuf, "2057:36.78"); + + EXPECT_EQ(str_time(123456, TIME_SECS_CENTISECS, aBuf, sizeof(aBuf)), 5); + EXPECT_STREQ(aBuf, "34.56"); + EXPECT_EQ(str_time(1234567, TIME_SECS_CENTISECS, aBuf, sizeof(aBuf)), 5); + EXPECT_STREQ(aBuf, "45.67"); + EXPECT_EQ(str_time(12345678, TIME_SECS_CENTISECS, aBuf, sizeof(aBuf)), 5); + EXPECT_STREQ(aBuf, "36.78"); } TEST(Str, TimeFloat) @@ -808,8 +815,8 @@ TEST(Str, TimeFloat) EXPECT_EQ(str_time_float(123456.78, TIME_DAYS, aBuf, sizeof(aBuf)), 11); EXPECT_STREQ(aBuf, "1d 10:17:36"); - EXPECT_EQ(str_time_float(12.16, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)), 8); - EXPECT_STREQ(aBuf, "00:12.16"); + EXPECT_EQ(str_time_float(12.16, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)), 5); + EXPECT_STREQ(aBuf, "12.16"); EXPECT_EQ(str_time_float(22.995, TIME_MINS, aBuf, sizeof(aBuf)), 5); EXPECT_STREQ(aBuf, "00:22");