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