1 /**
2 * @file plrmsg.cpp
3 *
4 * Implementation of functionality for printing the ingame chat messages.
5 */
6 #include "all.h"
7
8 DEVILUTION_BEGIN_NAMESPACE
9
10 static BYTE plr_msg_slot;
11 _plrmsg plr_msgs[PMSG_COUNT];
12
13 /** Maps from player_num to text color, as used in chat messages. */
14 const text_color text_color_from_player_num[MAX_PLRS + 1] = { COL_WHITE, COL_WHITE, COL_WHITE, COL_WHITE, COL_GOLD };
15
plrmsg_delay(BOOL delay)16 void plrmsg_delay(BOOL delay)
17 {
18 int i;
19 _plrmsg *pMsg;
20 static DWORD plrmsg_ticks;
21
22 if (delay) {
23 plrmsg_ticks = -SDL_GetTicks();
24 return;
25 }
26
27 plrmsg_ticks += SDL_GetTicks();
28 pMsg = plr_msgs;
29 for (i = 0; i < PMSG_COUNT; i++, pMsg++)
30 pMsg->time += plrmsg_ticks;
31 }
32
ErrorPlrMsg(const char * pszMsg)33 void ErrorPlrMsg(const char *pszMsg)
34 {
35 _plrmsg *pMsg = &plr_msgs[plr_msg_slot];
36 plr_msg_slot = (plr_msg_slot + 1) & (PMSG_COUNT - 1);
37 pMsg->player = MAX_PLRS;
38 pMsg->time = SDL_GetTicks();
39 strncpy(pMsg->str, pszMsg, sizeof(pMsg->str));
40 pMsg->str[sizeof(pMsg->str) - 1] = '\0';
41 }
42
EventPlrMsg(const char * pszFmt,...)43 size_t EventPlrMsg(const char *pszFmt, ...)
44 {
45 _plrmsg *pMsg;
46 va_list va;
47
48 va_start(va, pszFmt);
49 pMsg = &plr_msgs[plr_msg_slot];
50 plr_msg_slot = (plr_msg_slot + 1) & (PMSG_COUNT - 1);
51 pMsg->player = MAX_PLRS;
52 pMsg->time = SDL_GetTicks();
53 vsprintf(pMsg->str, pszFmt, va);
54 va_end(va);
55 return strlen(pMsg->str);
56 }
57
SendPlrMsg(int pnum,const char * pszStr)58 void SendPlrMsg(int pnum, const char *pszStr)
59 {
60 _plrmsg *pMsg = &plr_msgs[plr_msg_slot];
61 plr_msg_slot = (plr_msg_slot + 1) & (PMSG_COUNT - 1);
62 pMsg->player = pnum;
63 pMsg->time = SDL_GetTicks();
64 assert(strlen(plr[pnum]._pName) < PLR_NAME_LEN);
65 assert(strlen(pszStr) < MAX_SEND_STR_LEN);
66 sprintf(pMsg->str, "%s (lvl %d): %s", plr[pnum]._pName, plr[pnum]._pLevel, pszStr);
67 }
68
ClearPlrMsg()69 void ClearPlrMsg()
70 {
71 int i;
72 _plrmsg *pMsg = plr_msgs;
73 DWORD tick = SDL_GetTicks();
74
75 for (i = 0; i < PMSG_COUNT; i++, pMsg++) {
76 if ((int)(tick - pMsg->time) > 10000)
77 pMsg->str[0] = '\0';
78 }
79 }
80
InitPlrMsg()81 void InitPlrMsg()
82 {
83 memset(plr_msgs, 0, sizeof(plr_msgs));
84 plr_msg_slot = 0;
85 }
86
PrintPlrMsg(CelOutputBuffer out,DWORD x,DWORD y,DWORD width,const char * str,text_color col)87 static void PrintPlrMsg(CelOutputBuffer out, DWORD x, DWORD y, DWORD width, const char *str, text_color col)
88 {
89 int line = 0;
90
91 while (*str) {
92 BYTE c;
93 int sx = x;
94 DWORD len = 0;
95 const char *sstr = str;
96 const char *endstr = sstr;
97
98 while (1) {
99 if (*sstr) {
100 c = gbFontTransTbl[(BYTE)*sstr++];
101 c = fontframe[c];
102 len += fontkern[c] + 1;
103 if (!c) // allow wordwrap on blank glyph
104 endstr = sstr;
105 else if (len >= width)
106 break;
107 } else {
108 endstr = sstr;
109 break;
110 }
111 }
112
113 while (str < endstr) {
114 c = gbFontTransTbl[(BYTE)*str++];
115 c = fontframe[c];
116 if (c)
117 PrintChar(out, sx, y, c, col);
118 sx += fontkern[c] + 1;
119 }
120
121 y += 10;
122 line++;
123 if (line == 3)
124 break;
125 }
126 }
127
DrawPlrMsg(CelOutputBuffer out)128 void DrawPlrMsg(CelOutputBuffer out)
129 {
130 int i;
131 DWORD x = 10;
132 DWORD y = 70;
133 DWORD width = gnScreenWidth - 20;
134 _plrmsg *pMsg;
135
136 if (chrflag || questlog) {
137 x += SPANEL_WIDTH;
138 width -= SPANEL_WIDTH;
139 }
140 if (invflag || sbookflag)
141 width -= SPANEL_WIDTH;
142
143 if (width < 300)
144 return;
145
146 pMsg = plr_msgs;
147 for (i = 0; i < PMSG_COUNT; i++) {
148 if (pMsg->str[0])
149 PrintPlrMsg(out, x, y, width, pMsg->str, text_color_from_player_num[pMsg->player]);
150 pMsg++;
151 y += 35;
152 }
153 }
154
155 DEVILUTION_END_NAMESPACE
156