1 | /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */ |
2 | /* If you are missing that file, acquire a complete release at teeworlds.com. */ |
3 | #include <engine/graphics.h> |
4 | #include <engine/shared/config.h> |
5 | #include <engine/textrender.h> |
6 | |
7 | #include <game/generated/protocol.h> |
8 | |
9 | #include <game/client/gameclient.h> |
10 | |
11 | #include <game/client/components/motd.h> |
12 | #include <game/client/components/scoreboard.h> |
13 | |
14 | #include "broadcast.h" |
15 | |
16 | void CBroadcast::OnReset() |
17 | { |
18 | m_BroadcastTick = 0; |
19 | m_BroadcastRenderOffset = -1.0f; |
20 | TextRender()->DeleteTextContainer(TextContainerIndex&: m_TextContainerIndex); |
21 | } |
22 | |
23 | void CBroadcast::OnWindowResize() |
24 | { |
25 | m_BroadcastRenderOffset = -1.0f; |
26 | TextRender()->DeleteTextContainer(TextContainerIndex&: m_TextContainerIndex); |
27 | } |
28 | |
29 | void CBroadcast::OnRender() |
30 | { |
31 | if(Client()->State() != IClient::STATE_ONLINE && Client()->State() != IClient::STATE_DEMOPLAYBACK) |
32 | return; |
33 | |
34 | RenderServerBroadcast(); |
35 | } |
36 | |
37 | void CBroadcast::RenderServerBroadcast() |
38 | { |
39 | if(m_pClient->m_Scoreboard.Active() || m_pClient->m_Motd.IsActive() || !g_Config.m_ClShowBroadcasts) |
40 | return; |
41 | const float SecondsRemaining = (m_BroadcastTick - Client()->GameTick(Conn: g_Config.m_ClDummy)) / (float)Client()->GameTickSpeed(); |
42 | if(SecondsRemaining <= 0.0f) |
43 | { |
44 | TextRender()->DeleteTextContainer(TextContainerIndex&: m_TextContainerIndex); |
45 | return; |
46 | } |
47 | |
48 | const float Height = 300.0f; |
49 | const float Width = Height * Graphics()->ScreenAspect(); |
50 | Graphics()->MapScreen(TopLeftX: 0.0f, TopLeftY: 0.0f, BottomRightX: Width, BottomRightY: Height); |
51 | |
52 | if(m_BroadcastRenderOffset < 0.0f) |
53 | m_BroadcastRenderOffset = Width / 2.0f - TextRender()->TextWidth(Size: 12.0f, pText: m_aBroadcastText, StrLength: -1, LineWidth: Width) / 2.0f; |
54 | |
55 | if(!m_TextContainerIndex.Valid()) |
56 | { |
57 | CTextCursor Cursor; |
58 | TextRender()->SetCursor(pCursor: &Cursor, x: m_BroadcastRenderOffset, y: 40.0f, FontSize: 12.0f, Flags: TEXTFLAG_RENDER); |
59 | Cursor.m_LineWidth = Width; |
60 | TextRender()->CreateTextContainer(TextContainerIndex&: m_TextContainerIndex, pCursor: &Cursor, pText: m_aBroadcastText); |
61 | } |
62 | if(m_TextContainerIndex.Valid()) |
63 | { |
64 | const float Alpha = SecondsRemaining >= 1.0f ? 1.0f : SecondsRemaining; |
65 | ColorRGBA TextColor = TextRender()->DefaultTextColor(); |
66 | TextColor.a *= Alpha; |
67 | ColorRGBA OutlineColor = TextRender()->DefaultTextOutlineColor(); |
68 | OutlineColor.a *= Alpha; |
69 | TextRender()->RenderTextContainer(TextContainerIndex: m_TextContainerIndex, TextColor, TextOutlineColor: OutlineColor); |
70 | } |
71 | } |
72 | |
73 | void CBroadcast::OnMessage(int MsgType, void *pRawMsg) |
74 | { |
75 | if(MsgType == NETMSGTYPE_SV_BROADCAST) |
76 | { |
77 | OnBroadcastMessage(pMsg: (CNetMsg_Sv_Broadcast *)pRawMsg); |
78 | } |
79 | } |
80 | |
81 | void CBroadcast::OnBroadcastMessage(const CNetMsg_Sv_Broadcast *pMsg) |
82 | { |
83 | str_copy(dst&: m_aBroadcastText, src: pMsg->m_pMessage); |
84 | m_BroadcastTick = Client()->GameTick(Conn: g_Config.m_ClDummy) + Client()->GameTickSpeed() * 10; |
85 | m_BroadcastRenderOffset = -1.0f; |
86 | TextRender()->DeleteTextContainer(TextContainerIndex&: m_TextContainerIndex); |
87 | |
88 | if(g_Config.m_ClPrintBroadcasts) |
89 | { |
90 | const char *pText = m_aBroadcastText; |
91 | char aLine[sizeof(m_aBroadcastText)]; |
92 | while((pText = str_next_token(str: pText, delim: "\n" , buffer: aLine, buffer_size: sizeof(aLine)))) |
93 | { |
94 | if(aLine[0] != '\0') |
95 | { |
96 | m_pClient->Console()->Print(Level: IConsole::OUTPUT_LEVEL_STANDARD, pFrom: "broadcast" , pStr: aLine, PrintColor: color_cast<ColorRGBA>(hsl: ColorHSLA(g_Config.m_ClMessageHighlightColor))); |
97 | } |
98 | } |
99 | } |
100 | } |
101 | |