Round 4: Some minor build system housekeeping, as well as removing some depricated...
[theoddone33/hhexen.git] / base / in_lude.c
1
2 //**************************************************************************
3 //**
4 //** in_lude.c : Heretic 2 : Raven Software, Corp.
5 //**
6 //** $RCSfile$
7 //** $Revision$
8 //** $Date$
9 //** $Author$
10 //**
11 //**************************************************************************
12
13 #include "h2def.h"
14 #include <ctype.h>
15
16 // MACROS ------------------------------------------------------------------
17
18 #define TEXTSPEED 3
19 #define TEXTWAIT 140
20
21 // TYPES -------------------------------------------------------------------
22
23 typedef enum
24 {
25         SINGLE,
26         COOPERATIVE,
27         DEATHMATCH
28 } gametype_t;
29
30 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
31
32 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
33
34 void IN_Start(void);
35 void IN_Ticker(void);
36 void IN_Drawer(void);
37
38 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
39
40 static void WaitStop(void);
41 static void Stop(void);
42 static void LoadPics(void);
43 static void UnloadPics(void);
44 static void CheckForSkip(void);
45 static void InitStats(void);
46 static void DrDeathTally(void);
47 static void DrNumber(int val, int x, int y, int wrapThresh);
48 static void DrNumberBold(int val, int x, int y, int wrapThresh);
49 static void DrawHubText(void);
50
51 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
52
53 // PUBLIC DATA DECLARATIONS ------------------------------------------------
54
55 boolean intermission;
56 char ClusterMessage[MAX_INTRMSN_MESSAGE_SIZE];
57
58 // PRIVATE DATA DEFINITIONS ------------------------------------------------
59
60 static boolean skipintermission;
61 static int interstate = 0;
62 static int intertime = -1;
63 static gametype_t gametype;
64 static int cnt;
65 static int slaughterboy; // in DM, the player with the most kills
66 static patch_t *patchINTERPIC;
67 static patch_t *FontBNumbers[10];
68 static patch_t *FontBNegative;
69 static patch_t *FontBSlash;
70 static patch_t *FontBPercent;
71 static int FontABaseLump;
72 static int FontBLump;
73 static int FontBLumpBase;
74
75 static signed int totalFrags[MAXPLAYERS];
76
77 static int HubCount;
78 static char *HubText;
79
80 // CODE --------------------------------------------------------------------
81
82 //========================================================================
83 //
84 // IN_Start
85 //
86 //========================================================================
87
88 extern void AM_Stop (void);
89
90 void IN_Start(void)
91 {
92         int i;
93         I_SetPalette(W_CacheLumpName("PLAYPAL", PU_CACHE));
94         InitStats();
95         LoadPics();
96         intermission = true;
97         interstate = 0;
98         skipintermission = false;
99         intertime = 0;
100         AM_Stop();
101         for(i = 0; i < MAXPLAYERS; i++)
102         {
103                 players[i].messageTics = 0;
104                 players[i].message[0] = 0;
105         }
106         SN_StopAllSequences();  
107 }
108
109 //========================================================================
110 //
111 // WaitStop
112 //
113 //========================================================================
114
115 void WaitStop(void)
116 {
117         if(!--cnt)
118         {
119                 Stop();
120 //              gamestate = GS_LEVEL;
121 //              G_DoLoadLevel();
122                 gameaction = ga_leavemap;
123 //              G_WorldDone();
124         }
125 }
126
127 //========================================================================
128 //
129 // Stop
130 //
131 //========================================================================
132
133 static void Stop(void)
134 {
135         intermission = false;
136         UnloadPics();
137         SB_state = -1;
138         BorderNeedRefresh = true;
139 }
140
141 //========================================================================
142 //
143 // InitStats
144 //
145 //      Initializes the stats for single player mode
146 //========================================================================
147
148 static char *ClusMsgLumpNames[] =
149 {
150         "clus1msg",
151         "clus2msg", 
152         "clus3msg",
153         "clus4msg", 
154         "clus5msg"
155 };
156
157 static void InitStats(void)
158 {
159         int i;
160         int j;
161         int oldCluster;
162         signed int slaughterfrags;
163         int posnum;
164         int slaughtercount;
165         int playercount;
166         char *msgLumpName;
167         int msgSize;
168         int msgLump;
169
170         extern int LeaveMap;
171
172         if(!deathmatch)
173         {
174                 gametype = SINGLE;
175                 HubCount = 0;
176                 oldCluster = P_GetMapCluster(gamemap);
177                 if(oldCluster != P_GetMapCluster(LeaveMap))
178                 {
179                         if(oldCluster >= 1 && oldCluster <= 5)
180                         {
181                                 msgLumpName = ClusMsgLumpNames[oldCluster-1];
182                                 msgLump = W_GetNumForName(msgLumpName);
183                                 msgSize = W_LumpLength(msgLump);
184                                 if(msgSize >= MAX_INTRMSN_MESSAGE_SIZE)
185                                 {
186                                         I_Error("Cluster message too long (%s)", msgLumpName);
187                                 }
188                                 W_ReadLump(msgLump, ClusterMessage);
189                                 ClusterMessage[msgSize] = 0; // Append terminator
190                                 HubText = ClusterMessage;
191                                 HubCount = strlen(HubText)*TEXTSPEED+TEXTWAIT;
192                                 S_StartSongName("hub", true);
193                         }
194                 }
195         }
196         else
197         {
198                 gametype = DEATHMATCH;
199                 slaughterboy = 0;
200                 slaughterfrags = -9999;
201                 posnum = 0;
202                 playercount = 0;
203                 slaughtercount = 0;
204                 for(i=0; i<MAXPLAYERS; i++)
205                 {
206                         totalFrags[i] = 0;
207                         if(playeringame[i])
208                         {
209                                 playercount++;
210                                 for(j=0; j<MAXPLAYERS; j++)
211                                 {
212                                         if(playeringame[j])
213                                         {
214                                                 totalFrags[i] += players[i].frags[j];
215                                         }
216                                 }
217                                 posnum++;
218                         }
219                         if(totalFrags[i] > slaughterfrags)
220                         {
221                                 slaughterboy = 1<<i;
222                                 slaughterfrags = totalFrags[i];
223                                 slaughtercount = 1;
224                         }
225                         else if(totalFrags[i] == slaughterfrags)
226                         {
227                                 slaughterboy |= 1<<i;
228                                 slaughtercount++;
229                         }
230                 }
231                 if(playercount == slaughtercount)
232                 { // don't do the slaughter stuff if everyone is equal
233                         slaughterboy = 0;
234                 }
235                 S_StartSongName("hub", true);
236         }
237 }
238
239 //========================================================================
240 //
241 // LoadPics
242 //
243 //========================================================================
244
245 static void LoadPics(void)
246 {
247         int i;
248
249         if(HubCount || gametype == DEATHMATCH)
250         {
251                 patchINTERPIC = W_CacheLumpName("INTERPIC", PU_STATIC);
252                 FontBLumpBase = W_GetNumForName("FONTB16");
253                 for(i=0; i<10; i++)
254                 {
255                         FontBNumbers[i] = W_CacheLumpNum(FontBLumpBase+i, PU_STATIC);
256                 }
257                 FontBLump = W_GetNumForName("FONTB_S")+1;
258                 FontBNegative = W_CacheLumpName("FONTB13", PU_STATIC);
259                 FontABaseLump = W_GetNumForName("FONTA_S")+1;
260         
261                 FontBSlash = W_CacheLumpName("FONTB15", PU_STATIC);
262                 FontBPercent = W_CacheLumpName("FONTB05", PU_STATIC);
263         }
264 }
265
266 //========================================================================
267 //
268 // UnloadPics
269 //
270 //========================================================================
271
272 static void UnloadPics(void)
273 {
274         int i;
275
276         if(HubCount || gametype == DEATHMATCH)
277         {
278                 Z_ChangeTag(patchINTERPIC, PU_CACHE);
279                 for(i=0; i<10; i++)
280                 {
281                         Z_ChangeTag(FontBNumbers[i], PU_CACHE);
282                 }
283                 Z_ChangeTag(FontBNegative, PU_CACHE);
284                 Z_ChangeTag(FontBSlash, PU_CACHE);
285                 Z_ChangeTag(FontBPercent, PU_CACHE);
286         }
287 }
288
289 //========================================================================
290 //
291 // IN_Ticker
292 //
293 //========================================================================
294
295 void IN_Ticker(void)
296 {
297         if(!intermission)
298         {
299                 return;
300         }
301         if(interstate)
302         {
303                 WaitStop();
304                 return;
305         }
306         skipintermission = false;
307         CheckForSkip();
308         intertime++;
309         if(skipintermission || (gametype == SINGLE && !HubCount))
310         {
311                 interstate = 1;
312                 cnt = 10;
313                 skipintermission = false;
314                 //S_StartSound(NULL, sfx_dorcls);
315         }
316 }
317
318 //========================================================================
319 //
320 // CheckForSkip
321 //
322 //      Check to see if any player hit a key
323 //========================================================================
324
325 static void CheckForSkip(void)
326 {
327         int i;
328         player_t *player;
329         static boolean triedToSkip;
330
331         for(i = 0, player = players; i < MAXPLAYERS; i++, player++)
332         {
333         if(playeringame[i])
334         {
335                         if(player->cmd.buttons&BT_ATTACK)
336                         {
337                                 if(!player->attackdown)
338                                 {
339                                         skipintermission = 1;
340                                 }
341                                 player->attackdown = true;
342                         }
343                         else
344                         {
345                                 player->attackdown = false;
346                         }
347                         if(player->cmd.buttons&BT_USE)
348                         {
349                                 if(!player->usedown)
350                                 {
351                                         skipintermission = 1;
352                                 }
353                                 player->usedown = true;
354                         }
355                         else
356                         {
357                                 player->usedown = false;
358                         }
359                 }
360         }
361         if(deathmatch && intertime < 140)
362         { // wait for 4 seconds before allowing a skip
363                 if(skipintermission == 1)
364                 {
365                         triedToSkip = true;
366                         skipintermission = 0;
367                 }
368         }
369         else
370         {
371                 if(triedToSkip)
372                 {
373                         skipintermission = 1;
374                         triedToSkip = false;
375                 }
376         }
377 }
378
379 //========================================================================
380 //
381 // IN_Drawer
382 //
383 //========================================================================
384
385 void IN_Drawer(void)
386 {
387         if(!intermission)
388         {
389                 return;
390         }
391         if(interstate)
392         {
393                 return;
394         }
395         UpdateState |= I_FULLSCRN;
396         memcpy(screen, (byte *)patchINTERPIC, SCREENWIDTH*SCREENHEIGHT);
397
398         if(gametype == SINGLE)
399         {
400                 if(HubCount)
401                 {
402                         DrawHubText();
403                 }
404         }
405         else
406         {
407                 DrDeathTally();
408         }
409 }
410
411 //========================================================================
412 //
413 // DrDeathTally
414 //
415 //========================================================================
416
417 #define TALLY_EFFECT_TICKS 20
418 #define TALLY_FINAL_X_DELTA (23*FRACUNIT)
419 #define TALLY_FINAL_Y_DELTA (13*FRACUNIT)
420 #define TALLY_START_XPOS (178*FRACUNIT)
421 #define TALLY_STOP_XPOS (90*FRACUNIT)
422 #define TALLY_START_YPOS (132*FRACUNIT)
423 #define TALLY_STOP_YPOS (83*FRACUNIT)
424 #define TALLY_TOP_X 85
425 #define TALLY_TOP_Y 9
426 #define TALLY_LEFT_X 7
427 #define TALLY_LEFT_Y 71
428 #define TALLY_TOTALS_X 291
429
430 static void DrDeathTally(void)
431 {
432         int i, j;
433         fixed_t xPos, yPos;
434         fixed_t xDelta, yDelta;
435         fixed_t xStart, scale;
436         int x, y;
437         boolean bold;
438         static boolean showTotals;
439         int temp;
440
441         V_DrawPatch(TALLY_TOP_X, TALLY_TOP_Y,
442                 W_CacheLumpName("tallytop", PU_CACHE));
443         V_DrawPatch(TALLY_LEFT_X, TALLY_LEFT_Y,
444                 W_CacheLumpName("tallylft", PU_CACHE));
445         if(intertime < TALLY_EFFECT_TICKS)
446         {
447                 showTotals = false;
448                 scale = (intertime*FRACUNIT)/TALLY_EFFECT_TICKS;
449                 xDelta = FixedMul(scale, TALLY_FINAL_X_DELTA);
450                 yDelta = FixedMul(scale, TALLY_FINAL_Y_DELTA);
451                 xStart = TALLY_START_XPOS-FixedMul(scale,
452                         TALLY_START_XPOS-TALLY_STOP_XPOS);
453                 yPos = TALLY_START_YPOS-FixedMul(scale,
454                         TALLY_START_YPOS-TALLY_STOP_YPOS);
455         }
456         else
457         {
458                 xDelta = TALLY_FINAL_X_DELTA;
459                 yDelta = TALLY_FINAL_Y_DELTA;
460                 xStart = TALLY_STOP_XPOS;
461                 yPos = TALLY_STOP_YPOS;
462         }
463         if(intertime >= TALLY_EFFECT_TICKS && showTotals == false)
464         {
465                 showTotals = true;
466                 S_StartSound(NULL, SFX_PLATFORM_STOP);
467         }
468         y = yPos>>FRACBITS;
469         for(i = 0; i < MAXPLAYERS; i++)
470         {
471                 xPos = xStart;
472                 for(j = 0; j < MAXPLAYERS; j++, xPos += xDelta)
473                 {
474                         x = xPos>>FRACBITS;
475                         bold = (i == consoleplayer || j == consoleplayer);
476                         if(playeringame[i] && playeringame[j])
477                         {
478                                 if(bold)
479                                 {
480                                         DrNumberBold(players[i].frags[j], x, y, 100);
481                                 }
482                                 else
483                                 {
484                                         DrNumber(players[i].frags[j], x, y, 100);
485                                 }
486                         }
487                         else
488                         {
489                                 temp = MN_TextAWidth("--")/2;
490                                 if(bold)
491                                 {
492                                         MN_DrTextAYellow("--", x-temp, y);
493                                 }
494                                 else
495                                 {
496                                         MN_DrTextA("--", x-temp, y);
497                                 }
498                         }
499                 }
500                 if(showTotals && playeringame[i]
501                         && !((slaughterboy&(1<<i)) && !(intertime&16)))
502                 {
503                         DrNumber(totalFrags[i], TALLY_TOTALS_X, y, 1000);
504                 }
505                 yPos += yDelta;
506                 y = yPos>>FRACBITS;
507         }
508 }
509
510 //==========================================================================
511 //
512 // DrNumber
513 //
514 //==========================================================================
515
516 static void DrNumber(int val, int x, int y, int wrapThresh)
517 {
518         char buff[8] = "XX";
519
520         if(!(val < -9 && wrapThresh < 1000))
521         {
522                 sprintf(buff, "%d", val >= wrapThresh ? val%wrapThresh : val);
523         }
524         MN_DrTextA(buff, x-MN_TextAWidth(buff)/2, y);
525 }
526
527 //==========================================================================
528 //
529 // DrNumberBold
530 //
531 //==========================================================================
532
533 static void DrNumberBold(int val, int x, int y, int wrapThresh)
534 {
535         char buff[8] = "XX";
536
537         if(!(val < -9 && wrapThresh < 1000))
538         {
539                 sprintf(buff, "%d", val >= wrapThresh ? val%wrapThresh : val);
540         }
541         MN_DrTextAYellow(buff, x-MN_TextAWidth(buff)/2, y);
542 }
543
544 //===========================================================================
545 //
546 // DrawHubText
547 //
548 //===========================================================================
549
550 static void DrawHubText(void)
551 {
552         int             count;
553         char    *ch;
554         int             c;
555         int             cx, cy;
556         patch_t *w;
557
558         cy = 5;
559         cx = 10;
560         ch = HubText;
561         count = (intertime-10)/TEXTSPEED;
562         if (count < 0)
563         {
564                 count = 0;
565         }
566         for(; count; count--)
567         {
568                 c = *ch++;
569                 if(!c)
570                 {
571                         break;
572                 }
573                 if(c == '\n')
574                 {
575                         cx = 10;
576                         cy += 9;
577                         continue;
578                 }
579                 if(c < 32)
580                 {
581                         continue;
582                 }
583                 c = toupper(c);
584                 if(c == 32)
585                 {
586                         cx += 5;
587                         continue;
588                 }
589                 w = W_CacheLumpNum(FontABaseLump+c-33, PU_CACHE);
590                 if(cx+w->width > SCREENWIDTH)
591                 {
592                         break;
593                 }
594                 V_DrawPatch(cx, cy, w);
595                 cx += w->width;
596         }
597 }