1 //
2 // Copyright(C) 1993-1996 Id Software, Inc.
3 // Copyright(C) 1993-2008 Raven Software
4 // Copyright(C) 2005-2014 Simon Howard
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16
17
18 // HEADER FILES ------------------------------------------------------------
19
20 #include "h2def.h"
21 #include "i_system.h"
22 #include "i_video.h"
23 #include "p_local.h"
24 #include "s_sound.h"
25 #include <ctype.h>
26 #include "v_video.h"
27 #include "i_swap.h"
28
29 // MACROS ------------------------------------------------------------------
30
31 #define TEXTSPEED 3
32 #define TEXTWAIT 250
33
34 // TYPES -------------------------------------------------------------------
35
36 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
37
38 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
39
40 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
41
42 static void TextWrite(void);
43 static void DrawPic(void);
44 static void InitializeFade(boolean fadeIn);
45 static void DeInitializeFade(void);
46 static void FadePic(void);
47 static char *GetFinaleText(int sequence);
48
49 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
50
51 extern boolean automapactive;
52 extern boolean viewactive;
53
54 // PUBLIC DATA DECLARATIONS ------------------------------------------------
55
56 // PRIVATE DATA DEFINITIONS ------------------------------------------------
57
58 static int FinaleStage;
59 static int FinaleCount;
60 static int FinaleEndCount;
61 static int FinaleLumpNum;
62 static int FontABaseLump;
63 static char *FinaleText;
64
65 static fixed_t *Palette;
66 static fixed_t *PaletteDelta;
67 static byte *RealPalette;
68
69 // CODE --------------------------------------------------------------------
70
71 //===========================================================================
72 //
73 // F_StartFinale
74 //
75 //===========================================================================
76
F_StartFinale(void)77 void F_StartFinale(void)
78 {
79 gameaction = ga_nothing;
80 gamestate = GS_FINALE;
81 viewactive = false;
82 automapactive = false;
83 P_ClearMessage(&players[consoleplayer]);
84
85 FinaleStage = 0;
86 FinaleCount = 0;
87 FinaleText = GetFinaleText(0);
88 FinaleEndCount = 70;
89 FinaleLumpNum = W_GetNumForName("FINALE1");
90 FontABaseLump = W_GetNumForName("FONTA_S") + 1;
91 InitializeFade(1);
92
93 // S_ChangeMusic(mus_victor, true);
94 S_StartSongName("hall", false); // don't loop the song
95 }
96
97 //===========================================================================
98 //
99 // F_Responder
100 //
101 //===========================================================================
102
F_Responder(event_t * event)103 boolean F_Responder(event_t * event)
104 {
105 return false;
106 }
107
108 //===========================================================================
109 //
110 // F_Ticker
111 //
112 //===========================================================================
113
F_Ticker(void)114 void F_Ticker(void)
115 {
116 FinaleCount++;
117 if (FinaleStage < 5 && FinaleCount >= FinaleEndCount)
118 {
119 FinaleCount = 0;
120 FinaleStage++;
121 switch (FinaleStage)
122 {
123 case 1: // Text 1
124 FinaleEndCount = strlen(FinaleText) * TEXTSPEED + TEXTWAIT;
125 break;
126 case 2: // Pic 2, Text 2
127 FinaleText = GetFinaleText(1);
128 FinaleEndCount = strlen(FinaleText) * TEXTSPEED + TEXTWAIT;
129 FinaleLumpNum = W_GetNumForName("FINALE2");
130 S_StartSongName("orb", false);
131 break;
132 case 3: // Pic 2 -- Fade out
133 FinaleEndCount = 70;
134 DeInitializeFade();
135 InitializeFade(0);
136 break;
137 case 4: // Pic 3 -- Fade in
138 FinaleLumpNum = W_GetNumForName("FINALE3");
139 FinaleEndCount = 71;
140 DeInitializeFade();
141 InitializeFade(1);
142 S_StartSongName("chess", true);
143 break;
144 case 5: // Pic 3 , Text 3
145 FinaleText = GetFinaleText(2);
146 DeInitializeFade();
147 break;
148 default:
149 break;
150 }
151 return;
152 }
153 if (FinaleStage == 0 || FinaleStage == 3 || FinaleStage == 4)
154 {
155 FadePic();
156 }
157 }
158
159 //===========================================================================
160 //
161 // TextWrite
162 //
163 //===========================================================================
164
TextWrite(void)165 static void TextWrite(void)
166 {
167 int count;
168 char *ch;
169 int c;
170 int cx, cy;
171 patch_t *w;
172
173 memcpy(I_VideoBuffer, W_CacheLumpNum(FinaleLumpNum, PU_CACHE),
174 SCREENWIDTH * SCREENHEIGHT);
175 if (FinaleStage == 5)
176 { // Chess pic, draw the correct character graphic
177 if (netgame)
178 {
179 V_DrawPatch(20, 0, W_CacheLumpName("chessall", PU_CACHE));
180 }
181 else if (PlayerClass[consoleplayer])
182 {
183 V_DrawPatch(60, 0, W_CacheLumpNum(W_GetNumForName("chessc")
184 + PlayerClass[consoleplayer] -
185 1, PU_CACHE));
186 }
187 }
188 // Draw the actual text
189 if (FinaleStage == 5)
190 {
191 cy = 135;
192 }
193 else
194 {
195 cy = 5;
196 }
197 cx = 20;
198 ch = FinaleText;
199 count = (FinaleCount - 10) / TEXTSPEED;
200 if (count < 0)
201 {
202 count = 0;
203 }
204 for (; count; count--)
205 {
206 c = *ch++;
207 if (!c)
208 {
209 break;
210 }
211 if (c == '\n')
212 {
213 cx = 20;
214 cy += 9;
215 continue;
216 }
217 if (c < 32)
218 {
219 continue;
220 }
221 c = toupper(c);
222 if (c == 32)
223 {
224 cx += 5;
225 continue;
226 }
227 w = W_CacheLumpNum(FontABaseLump + c - 33, PU_CACHE);
228 if (cx + SHORT(w->width) > SCREENWIDTH)
229 {
230 break;
231 }
232 V_DrawPatch(cx, cy, w);
233 cx += SHORT(w->width);
234 }
235 }
236
237 //===========================================================================
238 //
239 // InitializeFade
240 //
241 //===========================================================================
242
InitializeFade(boolean fadeIn)243 static void InitializeFade(boolean fadeIn)
244 {
245 unsigned i;
246
247 Palette = Z_Malloc(768 * sizeof(fixed_t), PU_STATIC, 0);
248 PaletteDelta = Z_Malloc(768 * sizeof(fixed_t), PU_STATIC, 0);
249 RealPalette = Z_Malloc(768 * sizeof(byte), PU_STATIC, 0);
250
251 if (fadeIn)
252 {
253 memset(RealPalette, 0, 768 * sizeof(byte));
254 for (i = 0; i < 768; i++)
255 {
256 Palette[i] = 0;
257 PaletteDelta[i] = FixedDiv((*((byte *) W_CacheLumpName("playpal",
258 PU_CACHE) +
259 i)) << FRACBITS, 70 * FRACUNIT);
260 }
261 }
262 else
263 {
264 for (i = 0; i < 768; i++)
265 {
266 RealPalette[i] =
267 *((byte *) W_CacheLumpName("playpal", PU_CACHE) + i);
268 Palette[i] = RealPalette[i] << FRACBITS;
269 PaletteDelta[i] = FixedDiv(Palette[i], -70 * FRACUNIT);
270 }
271 }
272 I_SetPalette(RealPalette);
273 }
274
275 //===========================================================================
276 //
277 // DeInitializeFade
278 //
279 //===========================================================================
280
DeInitializeFade(void)281 static void DeInitializeFade(void)
282 {
283 Z_Free(Palette);
284 Z_Free(PaletteDelta);
285 Z_Free(RealPalette);
286 }
287
288 //===========================================================================
289 //
290 // FadePic
291 //
292 //===========================================================================
293
FadePic(void)294 static void FadePic(void)
295 {
296 unsigned i;
297
298 for (i = 0; i < 768; i++)
299 {
300 Palette[i] += PaletteDelta[i];
301 RealPalette[i] = Palette[i] >> FRACBITS;
302 }
303 I_SetPalette(RealPalette);
304 }
305
306 //===========================================================================
307 //
308 // DrawPic
309 //
310 //===========================================================================
311
DrawPic(void)312 static void DrawPic(void)
313 {
314 memcpy(I_VideoBuffer, W_CacheLumpNum(FinaleLumpNum, PU_CACHE),
315 SCREENWIDTH * SCREENHEIGHT);
316 if (FinaleStage == 4 || FinaleStage == 5)
317 { // Chess pic, draw the correct character graphic
318 if (netgame)
319 {
320 V_DrawPatch(20, 0, W_CacheLumpName("chessall", PU_CACHE));
321 }
322 else if (PlayerClass[consoleplayer])
323 {
324 V_DrawPatch(60, 0, W_CacheLumpNum(W_GetNumForName("chessc")
325 + PlayerClass[consoleplayer] -
326 1, PU_CACHE));
327 }
328 }
329 }
330
331 //===========================================================================
332 //
333 // F_Drawer
334 //
335 //===========================================================================
336
F_Drawer(void)337 void F_Drawer(void)
338 {
339 switch (FinaleStage)
340 {
341 case 0: // Fade in initial finale screen
342 DrawPic();
343 break;
344 case 1:
345 case 2:
346 TextWrite();
347 break;
348 case 3: // Fade screen out
349 DrawPic();
350 break;
351 case 4: // Fade in chess screen
352 DrawPic();
353 break;
354 case 5:
355 TextWrite();
356 break;
357 }
358 UpdateState |= I_FULLSCRN;
359 }
360
361 //==========================================================================
362 //
363 // GetFinaleText
364 //
365 //==========================================================================
366
GetFinaleText(int sequence)367 static char *GetFinaleText(int sequence)
368 {
369 char *msgLumpName;
370 int msgSize;
371 int msgLump;
372 static char *winMsgLumpNames[] = {
373 "win1msg",
374 "win2msg",
375 "win3msg"
376 };
377
378 msgLumpName = winMsgLumpNames[sequence];
379 msgLump = W_GetNumForName(msgLumpName);
380 msgSize = W_LumpLength(msgLump);
381 if (msgSize >= MAX_INTRMSN_MESSAGE_SIZE)
382 {
383 I_Error("Finale message too long (%s)", msgLumpName);
384 }
385 W_ReadLump(msgLump, ClusterMessage);
386 ClusterMessage[msgSize] = 0; // Append terminator
387 return ClusterMessage;
388 }
389