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