]> icculus.org git repositories - theoddone33/hheretic.git/blob - base/ct_chat.c
Initial revision
[theoddone33/hheretic.git] / base / ct_chat.c
1 //
2 // Chat mode
3 //
4
5 #include <string.h>
6 #include <ctype.h>
7 #include "doomdef.h"
8 #include "p_local.h"
9 #include "soundst.h"
10
11 #define QUEUESIZE               128
12 #define MESSAGESIZE     128
13 #define MESSAGELEN      265
14
15 #define CT_PLR_GREEN            1
16 #define CT_PLR_YELLOW   2
17 #define CT_PLR_RED              3
18 #define CT_PLR_BLUE             4
19 #define CT_PLR_ALL              5
20
21 #define CT_KEY_GREEN            'g'
22 #define CT_KEY_YELLOW   'y'
23 #define CT_KEY_RED              'r'
24 #define CT_KEY_BLUE             'b'
25 #define CT_KEY_ALL              't'
26 #define CT_ESCAPE                       6
27
28 // Public data
29
30 void CT_Init(void);
31 void CT_Drawer(void);
32 boolean CT_Responder(event_t *ev);
33 void CT_Ticker(void);
34 char CT_dequeueChatChar(void);
35
36 boolean chatmodeon;
37
38 // Private data
39
40 void CT_queueChatChar(char ch);
41 void CT_ClearChatMessage(int player);
42 void CT_AddChar(int player, char c);
43 void CT_BackSpace(int player);
44
45 int head;
46 int tail;
47 byte ChatQueue[QUEUESIZE];
48 int chat_dest[MAXPLAYERS];
49 char chat_msg[MAXPLAYERS][MESSAGESIZE];
50 char plr_lastmsg[MAXPLAYERS][MESSAGESIZE+9]; // add in the length of the pre-string
51 int msgptr[MAXPLAYERS];
52 int msglen[MAXPLAYERS];
53
54 boolean cheated;
55
56 static int FontABaseLump;
57
58 char *CT_FromPlrText[MAXPLAYERS] =
59 {
60         "GREEN:  ",
61         "YELLOW:  ",
62         "RED:  ",
63         "BLUE:  "
64 };
65
66 char *chat_macros[10];
67
68 boolean altdown;
69 boolean shiftdown;
70
71
72 //===========================================================================
73 //
74 // CT_Init
75 //
76 //      Initialize chat mode data
77 //===========================================================================
78
79 void CT_Init(void)
80 {
81         int i;
82
83         head = 0; //initialize the queue index
84         tail = 0;
85         chatmodeon = false;
86         memset(ChatQueue, 0, QUEUESIZE);
87         for(i = 0; i < MAXPLAYERS; i++)
88         {
89                 chat_dest[i] = 0;
90                 msgptr[i] = 0;
91                 memset(plr_lastmsg[i], 0, MESSAGESIZE);
92                 memset(chat_msg[i], 0, MESSAGESIZE);
93         }
94         FontABaseLump = W_GetNumForName("FONTA_S")+1;
95         return;
96 }
97
98 //===========================================================================
99 //
100 // CT_Stop
101 //
102 //===========================================================================
103
104 void CT_Stop(void)
105 {
106         chatmodeon = false;
107         return;
108 }
109
110 //===========================================================================
111 //
112 // CT_Responder
113 //
114 //===========================================================================
115
116 boolean CT_Responder(event_t *ev)
117 {
118         char *macro;
119
120         int sendto;
121
122         if(!netgame)
123         {
124                 return false;
125         }
126         if(ev->data1 == KEY_LALT || ev->data2 == KEY_RALT)
127         {
128                 altdown = (ev->type == ev_keydown);
129                 return false;
130         }
131         if(ev->data1 == KEY_RSHIFT)
132         {
133                 shiftdown = (ev->type == ev_keydown);
134                 return false;
135         }
136         if(ev->type != ev_keydown)
137         {
138                 return false;
139         }
140         if(!chatmodeon)
141         {
142                 sendto = 0;
143                 if(ev->data1 == CT_KEY_ALL)
144                 {
145                         sendto = CT_PLR_ALL;
146                 }
147                 else if(ev->data1 == CT_KEY_GREEN)
148                 {
149                         sendto = CT_PLR_GREEN;
150                 }
151                 else if(ev->data1 == CT_KEY_YELLOW)
152                 {
153                         sendto = CT_PLR_YELLOW;
154                 }
155                 else if(ev->data1 == CT_KEY_RED)
156                 {
157                         sendto = CT_PLR_RED;
158                 }
159                 else if(ev->data1 == CT_KEY_BLUE)
160                 {
161                         sendto = CT_PLR_BLUE;
162                 }
163                 if(sendto == 0 || (sendto != CT_PLR_ALL && !playeringame[sendto-1])
164                         || sendto == consoleplayer+1)
165                 {
166                         return false;
167                 }
168                 CT_queueChatChar(sendto);
169                 chatmodeon = true;
170                 return true;
171         }
172         else
173         {
174                 if(altdown)
175                 {
176                         if(ev->data1 >= '0' && ev->data1 <= '9')
177                         {
178                                 if(ev->data1 == '0')
179                                 { // macro 0 comes after macro 9
180                                         ev->data1 = '9'+1;
181                                 }
182                                 macro = chat_macros[ev->data1-'1'];
183                                 CT_queueChatChar(KEY_ENTER); //send old message
184                                 CT_queueChatChar(chat_dest[consoleplayer]); // chose the dest.
185                                 while(*macro)
186                                 {
187                                         CT_queueChatChar(toupper(*macro++));
188                                 }
189                                 CT_queueChatChar(KEY_ENTER); //send it off...
190                                 CT_Stop();
191                                 return true;
192                         }
193                 }
194                 if(ev->data1 == KEY_ENTER)
195                 {
196                         CT_queueChatChar(KEY_ENTER);
197                         CT_Stop();
198                         return true;
199                 }
200                 else if(ev->data1 == KEY_ESCAPE)
201                 {
202                         CT_queueChatChar(CT_ESCAPE);
203                         CT_Stop();
204                         return true;
205                 }
206                 else if(ev->data1 >= 'a' && ev->data1 <= 'z')
207                 {
208                         CT_queueChatChar(ev->data1-32);
209                         return true;
210                 }
211                 else if(shiftdown)
212                 {
213                         if(ev->data1 == '1')
214                         {
215                                 CT_queueChatChar('!');
216                                 return true;
217                         }
218                         else if(ev->data1 == '/')
219                         {
220                                 CT_queueChatChar('?');
221                                 return true;
222                         }
223                 }
224                 else
225                 {
226                         if(ev->data1 == ' ' || ev->data1 == ',' || ev->data1 == '.'
227                         || (ev->data1 >= '0' && ev->data1 <= '9') || ev->data1 == '\''
228                         || ev->data1 == KEY_BACKSPACE || ev->data1 == '-' || ev->data1 == '=')
229                         {
230                                 CT_queueChatChar(ev->data1);
231                                 return true;
232                         }
233                 }
234         }
235         return false;
236 }
237
238 //===========================================================================
239 //
240 // CT_Ticker
241 //
242 //===========================================================================
243
244 void CT_Ticker(void)
245 {
246         int i;
247         int j;
248         char c;
249         int numplayers;
250
251         for(i=0; i < MAXPLAYERS; i++)
252         {
253                 if(!playeringame[i])
254                 {
255                         continue;
256                 }
257                 if((c = players[i].cmd.chatchar) != 0)
258                 {
259                         if(c <= 5)
260                         {
261                                 chat_dest[i] = c;
262                                 continue;
263                         }
264                         else if(c == CT_ESCAPE)
265                         {
266                                 CT_ClearChatMessage(i);
267                         }
268                         else if(c == KEY_ENTER)
269                         {
270                                 numplayers = 0;
271                                 for(j = 0; j < MAXPLAYERS; j++)
272                                 {
273                                         numplayers += playeringame[j];
274                                 }
275                                 CT_AddChar(i, 0); // set the end of message character
276                                 if(numplayers > 2)
277                                 {
278                                         strcpy(plr_lastmsg[i], CT_FromPlrText[i]);
279                                         strcat(plr_lastmsg[i], chat_msg[i]);
280                                 }
281                                 else
282                                 {
283                                         strcpy(plr_lastmsg[i], chat_msg[i]);
284                                 }
285                                 if(i != consoleplayer && (chat_dest[i] == consoleplayer+1
286                                         || chat_dest[i] == CT_PLR_ALL) && *chat_msg[i])
287                                 {
288                                         P_SetMessage(&players[consoleplayer], plr_lastmsg[i], 
289                                                 true);
290                                         S_StartSound(NULL, sfx_chat);
291                                 }
292                                 else if(i == consoleplayer && (*chat_msg[i]))
293                                 {
294                                         if(numplayers > 1)
295                                         {
296                                                 P_SetMessage(&players[consoleplayer], "-MESSAGE SENT-", 
297                                                         true);
298                                                 S_StartSound(NULL, sfx_chat);
299                                         }
300                                         else
301                                         {
302                                                 P_SetMessage(&players[consoleplayer],
303                                                         "THERE ARE NO OTHER PLAYERS IN THE GAME!", true);
304                                                 S_StartSound(NULL, sfx_chat);
305                                         }
306                                 }
307                                 CT_ClearChatMessage(i);
308                         }
309                         else if(c == KEY_BACKSPACE)
310                         {
311                                 CT_BackSpace(i);
312                         }
313                         else
314                         {
315                                 CT_AddChar(i, c);
316                         }
317                 }
318         }
319         return;
320 }
321
322 //===========================================================================
323 //
324 // CT_Drawer
325 //
326 //===========================================================================
327
328 void CT_Drawer(void)
329 {
330         int i;
331         int x;
332         patch_t *patch;
333
334         if(chatmodeon)
335         {
336                 x = 25;
337                 for(i = 0; i < msgptr[consoleplayer]; i++)
338                 {
339                         if(chat_msg[consoleplayer][i] < 33)
340                         {
341                                 x += 6;
342                         }
343                         else
344                         {
345                                 patch=W_CacheLumpNum(FontABaseLump+
346                                         chat_msg[consoleplayer][i]-33, PU_CACHE);
347                                 V_DrawPatch(x, 10, patch);
348                                 x += patch->width;
349                         }
350                 }
351                 V_DrawPatch(x, 10, W_CacheLumpName("FONTA59", PU_CACHE));
352                 BorderTopRefresh = true;
353                 UpdateState |= I_MESSAGES;
354         }
355 }
356
357 //===========================================================================
358 //
359 // CT_queueChatChar
360 //
361 //===========================================================================
362
363 void CT_queueChatChar(char ch)
364 {
365         if(((tail+1)&(QUEUESIZE-1)) == head)
366         { // the queue is full
367                 return;
368         }
369         ChatQueue[tail] = ch;
370         tail = (tail+1)&(QUEUESIZE-1);
371 }
372
373 //===========================================================================
374 //
375 // CT_dequeueChatChar
376 //
377 //===========================================================================
378
379 char CT_dequeueChatChar(void)
380 {
381         byte temp;
382
383         if(head == tail)
384         { // queue is empty
385                 return 0;
386         }
387         temp = ChatQueue[head];
388         head = (head+1)&(QUEUESIZE-1);
389         return temp;
390 }
391
392 //===========================================================================
393 //
394 // CT_AddChar
395 //
396 //===========================================================================
397
398 void CT_AddChar(int player, char c)
399 {
400         patch_t *patch;
401
402         if(msgptr[player]+1 >= MESSAGESIZE || msglen[player] >= MESSAGELEN)
403         { // full.
404                 return;
405         }
406         chat_msg[player][msgptr[player]] = c;
407         msgptr[player]++;
408         if(c < 33)
409         {
410                 msglen[player] += 6;
411         }
412         else
413         {
414                 patch = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
415                 msglen[player] += patch->width;
416         }
417 }
418
419 //===========================================================================
420 //
421 // CT_BackSpace
422 //
423 //      Backs up a space, when the user hits (obviously) backspace
424 //===========================================================================
425
426 void CT_BackSpace(int player)
427 {
428         patch_t *patch;
429         char c;
430
431         if(msgptr[player] == 0)
432         { // message is already blank
433                 return;
434         }
435         msgptr[player]--;
436         c = chat_msg[player][msgptr[player]];
437         if(c < 33)
438         {
439                 msglen[player] -= 6;
440         }
441         else
442         {
443                 patch = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
444                 msglen[player] -= patch->width;
445         }
446         chat_msg[player][msgptr[player]] = 0;
447 }
448
449 //===========================================================================
450 //
451 // CT_ClearChatMessage
452 //
453 //      Clears out the data for the chat message, but the player's message
454 //              is still saved in plrmsg.
455 //===========================================================================
456
457 void CT_ClearChatMessage(int player)
458 {
459         memset(chat_msg[player], 0, MESSAGESIZE);
460         msgptr[player] = 0;
461         msglen[player] = 0;
462 }