diff options
Diffstat (limited to 'apps/plugins/sdl/progs/wolf3d/wl_game.c')
-rw-r--r-- | apps/plugins/sdl/progs/wolf3d/wl_game.c | 1601 |
1 files changed, 1601 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/wolf3d/wl_game.c b/apps/plugins/sdl/progs/wolf3d/wl_game.c new file mode 100644 index 0000000000..445cf00153 --- /dev/null +++ b/apps/plugins/sdl/progs/wolf3d/wl_game.c | |||
@@ -0,0 +1,1601 @@ | |||
1 | // WL_GAME.C | ||
2 | |||
3 | #include "wl_def.h" | ||
4 | #pragma hdrstop | ||
5 | |||
6 | |||
7 | /* | ||
8 | ============================================================================= | ||
9 | |||
10 | LOCAL CONSTANTS | ||
11 | |||
12 | ============================================================================= | ||
13 | */ | ||
14 | |||
15 | |||
16 | /* | ||
17 | ============================================================================= | ||
18 | |||
19 | GLOBAL VARIABLES | ||
20 | |||
21 | ============================================================================= | ||
22 | */ | ||
23 | |||
24 | boolean ingame,fizzlein; | ||
25 | gametype gamestate; | ||
26 | byte bordercol=VIEWCOLOR; // color of the Change View/Ingame border | ||
27 | |||
28 | #ifdef SPEAR | ||
29 | int32_t spearx,speary; | ||
30 | unsigned spearangle; | ||
31 | boolean spearflag; | ||
32 | #endif | ||
33 | |||
34 | #ifdef USE_FEATUREFLAGS | ||
35 | int ffDataTopLeft, ffDataTopRight, ffDataBottomLeft, ffDataBottomRight; | ||
36 | #endif | ||
37 | |||
38 | // | ||
39 | // ELEVATOR BACK MAPS - REMEMBER (-1)!! | ||
40 | // | ||
41 | int ElevatorBackTo[]={1,1,7,3,5,3}; | ||
42 | |||
43 | void SetupGameLevel (void); | ||
44 | void DrawPlayScreen (void); | ||
45 | void LoadLatchMem (void); | ||
46 | void GameLoop (void); | ||
47 | |||
48 | /* | ||
49 | ============================================================================= | ||
50 | |||
51 | LOCAL VARIABLES | ||
52 | |||
53 | ============================================================================= | ||
54 | */ | ||
55 | |||
56 | |||
57 | |||
58 | //=========================================================================== | ||
59 | //=========================================================================== | ||
60 | |||
61 | |||
62 | /* | ||
63 | ========================== | ||
64 | = | ||
65 | = SetSoundLoc - Given the location of an object (in terms of global | ||
66 | = coordinates, held in globalsoundx and globalsoundy), munges the values | ||
67 | = for an approximate distance from the left and right ear, and puts | ||
68 | = those values into leftchannel and rightchannel. | ||
69 | = | ||
70 | = JAB | ||
71 | = | ||
72 | ========================== | ||
73 | */ | ||
74 | |||
75 | int leftchannel, rightchannel; | ||
76 | #define ATABLEMAX 15 | ||
77 | byte righttable[ATABLEMAX][ATABLEMAX * 2] = { | ||
78 | { 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 6, 0, 0, 0, 0, 0, 1, 3, 5, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
79 | { 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 6, 4, 0, 0, 0, 0, 0, 2, 4, 6, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
80 | { 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 4, 1, 0, 0, 0, 1, 2, 4, 6, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
81 | { 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 6, 5, 4, 2, 1, 0, 1, 2, 3, 5, 7, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
82 | { 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 5, 4, 3, 2, 2, 3, 3, 5, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
83 | { 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 4, 4, 4, 4, 5, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
84 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 5, 5, 5, 6, 6, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
85 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
86 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
87 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
88 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
89 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
90 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
91 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
92 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8} | ||
93 | }; | ||
94 | byte lefttable[ATABLEMAX][ATABLEMAX * 2] = { | ||
95 | { 8, 8, 8, 8, 8, 8, 8, 8, 5, 3, 1, 0, 0, 0, 0, 0, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8}, | ||
96 | { 8, 8, 8, 8, 8, 8, 8, 8, 6, 4, 2, 0, 0, 0, 0, 0, 4, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8}, | ||
97 | { 8, 8, 8, 8, 8, 8, 8, 8, 6, 4, 2, 1, 0, 0, 0, 1, 4, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8}, | ||
98 | { 8, 8, 8, 8, 8, 8, 8, 8, 7, 5, 3, 2, 1, 0, 1, 2, 4, 5, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8}, | ||
99 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 6, 5, 3, 3, 2, 2, 3, 4, 5, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
100 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 5, 4, 4, 4, 4, 5, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
101 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 6, 6, 5, 5, 5, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
102 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
103 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
104 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
105 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
106 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
107 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
108 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}, | ||
109 | { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8} | ||
110 | }; | ||
111 | |||
112 | void | ||
113 | SetSoundLoc(fixed gx,fixed gy) | ||
114 | { | ||
115 | fixed xt,yt; | ||
116 | int x,y; | ||
117 | |||
118 | // | ||
119 | // translate point to view centered coordinates | ||
120 | // | ||
121 | gx -= viewx; | ||
122 | gy -= viewy; | ||
123 | |||
124 | // | ||
125 | // calculate newx | ||
126 | // | ||
127 | xt = FixedMul(gx,viewcos); | ||
128 | yt = FixedMul(gy,viewsin); | ||
129 | x = (xt - yt) >> TILESHIFT; | ||
130 | |||
131 | // | ||
132 | // calculate newy | ||
133 | // | ||
134 | xt = FixedMul(gx,viewsin); | ||
135 | yt = FixedMul(gy,viewcos); | ||
136 | y = (yt + xt) >> TILESHIFT; | ||
137 | |||
138 | if (y >= ATABLEMAX) | ||
139 | y = ATABLEMAX - 1; | ||
140 | else if (y <= -ATABLEMAX) | ||
141 | y = -ATABLEMAX; | ||
142 | if (x < 0) | ||
143 | x = -x; | ||
144 | if (x >= ATABLEMAX) | ||
145 | x = ATABLEMAX - 1; | ||
146 | leftchannel = lefttable[x][y + ATABLEMAX]; | ||
147 | rightchannel = righttable[x][y + ATABLEMAX]; | ||
148 | |||
149 | #if 0 | ||
150 | CenterWindow(8,1); | ||
151 | US_PrintSigned(leftchannel); | ||
152 | US_Print(","); | ||
153 | US_PrintSigned(rightchannel); | ||
154 | VW_UpdateScreen(); | ||
155 | #endif | ||
156 | } | ||
157 | |||
158 | /* | ||
159 | ========================== | ||
160 | = | ||
161 | = SetSoundLocGlobal - Sets up globalsoundx & globalsoundy and then calls | ||
162 | = UpdateSoundLoc() to transform that into relative channel volumes. Those | ||
163 | = values are then passed to the Sound Manager so that they'll be used for | ||
164 | = the next sound played (if possible). | ||
165 | = | ||
166 | = JAB | ||
167 | = | ||
168 | ========================== | ||
169 | */ | ||
170 | void PlaySoundLocGlobal(word s,fixed gx,fixed gy) | ||
171 | { | ||
172 | SetSoundLoc(gx, gy); | ||
173 | SD_PositionSound(leftchannel, rightchannel); | ||
174 | |||
175 | int channel = SD_PlaySound((soundnames) s); | ||
176 | if(channel) | ||
177 | { | ||
178 | channelSoundPos[channel - 1].globalsoundx = gx; | ||
179 | channelSoundPos[channel - 1].globalsoundy = gy; | ||
180 | channelSoundPos[channel - 1].valid = 1; | ||
181 | } | ||
182 | } | ||
183 | |||
184 | void UpdateSoundLoc(void) | ||
185 | { | ||
186 | /* if (SoundPositioned) | ||
187 | { | ||
188 | SetSoundLoc(globalsoundx,globalsoundy); | ||
189 | SD_SetPosition(leftchannel,rightchannel); | ||
190 | }*/ | ||
191 | |||
192 | for(int i = 0; i < MIX_CHANNELS; i++) | ||
193 | { | ||
194 | if(channelSoundPos[i].valid) | ||
195 | { | ||
196 | SetSoundLoc(channelSoundPos[i].globalsoundx, | ||
197 | channelSoundPos[i].globalsoundy); | ||
198 | SD_SetPosition(i, leftchannel, rightchannel); | ||
199 | } | ||
200 | } | ||
201 | } | ||
202 | |||
203 | /* | ||
204 | ** JAB End | ||
205 | */ | ||
206 | |||
207 | /* | ||
208 | ========================== | ||
209 | = | ||
210 | = ScanInfoPlane | ||
211 | = | ||
212 | = Spawn all actors and mark down special places | ||
213 | = | ||
214 | ========================== | ||
215 | */ | ||
216 | |||
217 | static void ScanInfoPlane(void) | ||
218 | { | ||
219 | unsigned x,y; | ||
220 | int tile; | ||
221 | word *start; | ||
222 | |||
223 | start = mapsegs[1]; | ||
224 | for (y=0;y<mapheight;y++) | ||
225 | { | ||
226 | for (x=0;x<mapwidth;x++) | ||
227 | { | ||
228 | tile = *start++; | ||
229 | if (!tile) | ||
230 | continue; | ||
231 | |||
232 | switch (tile) | ||
233 | { | ||
234 | case 19: | ||
235 | case 20: | ||
236 | case 21: | ||
237 | case 22: | ||
238 | SpawnPlayer(x,y,NORTH+tile-19); | ||
239 | break; | ||
240 | |||
241 | case 23: | ||
242 | case 24: | ||
243 | case 25: | ||
244 | case 26: | ||
245 | case 27: | ||
246 | case 28: | ||
247 | case 29: | ||
248 | case 30: | ||
249 | |||
250 | case 31: | ||
251 | case 32: | ||
252 | case 33: | ||
253 | case 34: | ||
254 | case 35: | ||
255 | case 36: | ||
256 | case 37: | ||
257 | case 38: | ||
258 | |||
259 | case 39: | ||
260 | case 40: | ||
261 | case 41: | ||
262 | case 42: | ||
263 | case 43: | ||
264 | case 44: | ||
265 | case 45: | ||
266 | case 46: | ||
267 | |||
268 | case 47: | ||
269 | case 48: | ||
270 | case 49: | ||
271 | case 50: | ||
272 | case 51: | ||
273 | case 52: | ||
274 | case 53: | ||
275 | case 54: | ||
276 | |||
277 | case 55: | ||
278 | case 56: | ||
279 | case 57: | ||
280 | case 58: | ||
281 | case 59: | ||
282 | case 60: | ||
283 | case 61: | ||
284 | case 62: | ||
285 | |||
286 | case 63: | ||
287 | case 64: | ||
288 | case 65: | ||
289 | case 66: | ||
290 | case 67: | ||
291 | case 68: | ||
292 | case 69: | ||
293 | case 70: | ||
294 | case 71: | ||
295 | case 72: | ||
296 | #ifdef SPEAR | ||
297 | case 73: // TRUCK AND SPEAR! | ||
298 | case 74: | ||
299 | #elif defined(USE_DIR3DSPR) // just for the example | ||
300 | case 73: | ||
301 | #endif | ||
302 | SpawnStatic(x,y,tile-23); | ||
303 | break; | ||
304 | |||
305 | // | ||
306 | // P wall | ||
307 | // | ||
308 | case 98: | ||
309 | if (!loadedgame) | ||
310 | gamestate.secrettotal++; | ||
311 | break; | ||
312 | |||
313 | // | ||
314 | // guard | ||
315 | // | ||
316 | case 180: | ||
317 | case 181: | ||
318 | case 182: | ||
319 | case 183: | ||
320 | if (gamestate.difficulty<gd_hard) | ||
321 | break; | ||
322 | tile -= 36; | ||
323 | case 144: | ||
324 | case 145: | ||
325 | case 146: | ||
326 | case 147: | ||
327 | if (gamestate.difficulty<gd_medium) | ||
328 | break; | ||
329 | tile -= 36; | ||
330 | case 108: | ||
331 | case 109: | ||
332 | case 110: | ||
333 | case 111: | ||
334 | SpawnStand(en_guard,x,y,tile-108); | ||
335 | break; | ||
336 | |||
337 | |||
338 | case 184: | ||
339 | case 185: | ||
340 | case 186: | ||
341 | case 187: | ||
342 | if (gamestate.difficulty<gd_hard) | ||
343 | break; | ||
344 | tile -= 36; | ||
345 | case 148: | ||
346 | case 149: | ||
347 | case 150: | ||
348 | case 151: | ||
349 | if (gamestate.difficulty<gd_medium) | ||
350 | break; | ||
351 | tile -= 36; | ||
352 | case 112: | ||
353 | case 113: | ||
354 | case 114: | ||
355 | case 115: | ||
356 | SpawnPatrol(en_guard,x,y,tile-112); | ||
357 | break; | ||
358 | |||
359 | case 124: | ||
360 | SpawnDeadGuard (x,y); | ||
361 | break; | ||
362 | // | ||
363 | // officer | ||
364 | // | ||
365 | case 188: | ||
366 | case 189: | ||
367 | case 190: | ||
368 | case 191: | ||
369 | if (gamestate.difficulty<gd_hard) | ||
370 | break; | ||
371 | tile -= 36; | ||
372 | case 152: | ||
373 | case 153: | ||
374 | case 154: | ||
375 | case 155: | ||
376 | if (gamestate.difficulty<gd_medium) | ||
377 | break; | ||
378 | tile -= 36; | ||
379 | case 116: | ||
380 | case 117: | ||
381 | case 118: | ||
382 | case 119: | ||
383 | SpawnStand(en_officer,x,y,tile-116); | ||
384 | break; | ||
385 | |||
386 | |||
387 | case 192: | ||
388 | case 193: | ||
389 | case 194: | ||
390 | case 195: | ||
391 | if (gamestate.difficulty<gd_hard) | ||
392 | break; | ||
393 | tile -= 36; | ||
394 | case 156: | ||
395 | case 157: | ||
396 | case 158: | ||
397 | case 159: | ||
398 | if (gamestate.difficulty<gd_medium) | ||
399 | break; | ||
400 | tile -= 36; | ||
401 | case 120: | ||
402 | case 121: | ||
403 | case 122: | ||
404 | case 123: | ||
405 | SpawnPatrol(en_officer,x,y,tile-120); | ||
406 | break; | ||
407 | |||
408 | |||
409 | // | ||
410 | // ss | ||
411 | // | ||
412 | case 198: | ||
413 | case 199: | ||
414 | case 200: | ||
415 | case 201: | ||
416 | if (gamestate.difficulty<gd_hard) | ||
417 | break; | ||
418 | tile -= 36; | ||
419 | case 162: | ||
420 | case 163: | ||
421 | case 164: | ||
422 | case 165: | ||
423 | if (gamestate.difficulty<gd_medium) | ||
424 | break; | ||
425 | tile -= 36; | ||
426 | case 126: | ||
427 | case 127: | ||
428 | case 128: | ||
429 | case 129: | ||
430 | SpawnStand(en_ss,x,y,tile-126); | ||
431 | break; | ||
432 | |||
433 | |||
434 | case 202: | ||
435 | case 203: | ||
436 | case 204: | ||
437 | case 205: | ||
438 | if (gamestate.difficulty<gd_hard) | ||
439 | break; | ||
440 | tile -= 36; | ||
441 | case 166: | ||
442 | case 167: | ||
443 | case 168: | ||
444 | case 169: | ||
445 | if (gamestate.difficulty<gd_medium) | ||
446 | break; | ||
447 | tile -= 36; | ||
448 | case 130: | ||
449 | case 131: | ||
450 | case 132: | ||
451 | case 133: | ||
452 | SpawnPatrol(en_ss,x,y,tile-130); | ||
453 | break; | ||
454 | |||
455 | // | ||
456 | // dogs | ||
457 | // | ||
458 | case 206: | ||
459 | case 207: | ||
460 | case 208: | ||
461 | case 209: | ||
462 | if (gamestate.difficulty<gd_hard) | ||
463 | break; | ||
464 | tile -= 36; | ||
465 | case 170: | ||
466 | case 171: | ||
467 | case 172: | ||
468 | case 173: | ||
469 | if (gamestate.difficulty<gd_medium) | ||
470 | break; | ||
471 | tile -= 36; | ||
472 | case 134: | ||
473 | case 135: | ||
474 | case 136: | ||
475 | case 137: | ||
476 | SpawnStand(en_dog,x,y,tile-134); | ||
477 | break; | ||
478 | |||
479 | |||
480 | case 210: | ||
481 | case 211: | ||
482 | case 212: | ||
483 | case 213: | ||
484 | if (gamestate.difficulty<gd_hard) | ||
485 | break; | ||
486 | tile -= 36; | ||
487 | case 174: | ||
488 | case 175: | ||
489 | case 176: | ||
490 | case 177: | ||
491 | if (gamestate.difficulty<gd_medium) | ||
492 | break; | ||
493 | tile -= 36; | ||
494 | case 138: | ||
495 | case 139: | ||
496 | case 140: | ||
497 | case 141: | ||
498 | SpawnPatrol(en_dog,x,y,tile-138); | ||
499 | break; | ||
500 | |||
501 | // | ||
502 | // boss | ||
503 | // | ||
504 | #ifndef SPEAR | ||
505 | case 214: | ||
506 | SpawnBoss (x,y); | ||
507 | break; | ||
508 | case 197: | ||
509 | SpawnGretel (x,y); | ||
510 | break; | ||
511 | case 215: | ||
512 | SpawnGift (x,y); | ||
513 | break; | ||
514 | case 179: | ||
515 | SpawnFat (x,y); | ||
516 | break; | ||
517 | case 196: | ||
518 | SpawnSchabbs (x,y); | ||
519 | break; | ||
520 | case 160: | ||
521 | SpawnFakeHitler (x,y); | ||
522 | break; | ||
523 | case 178: | ||
524 | SpawnHitler (x,y); | ||
525 | break; | ||
526 | #else | ||
527 | case 106: | ||
528 | SpawnSpectre (x,y); | ||
529 | break; | ||
530 | case 107: | ||
531 | SpawnAngel (x,y); | ||
532 | break; | ||
533 | case 125: | ||
534 | SpawnTrans (x,y); | ||
535 | break; | ||
536 | case 142: | ||
537 | SpawnUber (x,y); | ||
538 | break; | ||
539 | case 143: | ||
540 | SpawnWill (x,y); | ||
541 | break; | ||
542 | case 161: | ||
543 | SpawnDeath (x,y); | ||
544 | break; | ||
545 | |||
546 | #endif | ||
547 | |||
548 | // | ||
549 | // mutants | ||
550 | // | ||
551 | case 252: | ||
552 | case 253: | ||
553 | case 254: | ||
554 | case 255: | ||
555 | if (gamestate.difficulty<gd_hard) | ||
556 | break; | ||
557 | tile -= 18; | ||
558 | case 234: | ||
559 | case 235: | ||
560 | case 236: | ||
561 | case 237: | ||
562 | if (gamestate.difficulty<gd_medium) | ||
563 | break; | ||
564 | tile -= 18; | ||
565 | case 216: | ||
566 | case 217: | ||
567 | case 218: | ||
568 | case 219: | ||
569 | SpawnStand(en_mutant,x,y,tile-216); | ||
570 | break; | ||
571 | |||
572 | case 256: | ||
573 | case 257: | ||
574 | case 258: | ||
575 | case 259: | ||
576 | if (gamestate.difficulty<gd_hard) | ||
577 | break; | ||
578 | tile -= 18; | ||
579 | case 238: | ||
580 | case 239: | ||
581 | case 240: | ||
582 | case 241: | ||
583 | if (gamestate.difficulty<gd_medium) | ||
584 | break; | ||
585 | tile -= 18; | ||
586 | case 220: | ||
587 | case 221: | ||
588 | case 222: | ||
589 | case 223: | ||
590 | SpawnPatrol(en_mutant,x,y,tile-220); | ||
591 | break; | ||
592 | |||
593 | // | ||
594 | // ghosts | ||
595 | // | ||
596 | #ifndef SPEAR | ||
597 | case 224: | ||
598 | SpawnGhosts (en_blinky,x,y); | ||
599 | break; | ||
600 | case 225: | ||
601 | SpawnGhosts (en_clyde,x,y); | ||
602 | break; | ||
603 | case 226: | ||
604 | SpawnGhosts (en_pinky,x,y); | ||
605 | break; | ||
606 | case 227: | ||
607 | SpawnGhosts (en_inky,x,y); | ||
608 | break; | ||
609 | #endif | ||
610 | } | ||
611 | } | ||
612 | } | ||
613 | } | ||
614 | |||
615 | //========================================================================== | ||
616 | |||
617 | /* | ||
618 | ================== | ||
619 | = | ||
620 | = SetupGameLevel | ||
621 | = | ||
622 | ================== | ||
623 | */ | ||
624 | |||
625 | void SetupGameLevel (void) | ||
626 | { | ||
627 | int x,y; | ||
628 | word *map; | ||
629 | word tile; | ||
630 | |||
631 | |||
632 | if (!loadedgame) | ||
633 | { | ||
634 | gamestate.TimeCount | ||
635 | = gamestate.secrettotal | ||
636 | = gamestate.killtotal | ||
637 | = gamestate.treasuretotal | ||
638 | = gamestate.secretcount | ||
639 | = gamestate.killcount | ||
640 | = gamestate.treasurecount | ||
641 | = pwallstate = pwallpos = facetimes = 0; | ||
642 | LastAttacker = NULL; | ||
643 | killerobj = NULL; | ||
644 | } | ||
645 | |||
646 | if (demoplayback || demorecord) | ||
647 | US_InitRndT (false); | ||
648 | else | ||
649 | US_InitRndT (true); | ||
650 | |||
651 | // | ||
652 | // load the level | ||
653 | // | ||
654 | CA_CacheMap (gamestate.mapon+10*gamestate.episode); | ||
655 | mapon-=gamestate.episode*10; | ||
656 | |||
657 | #ifdef USE_FEATUREFLAGS | ||
658 | // Temporary definition to make things clearer | ||
659 | #define MXX MAPSIZE - 1 | ||
660 | |||
661 | // Read feature flags data from map corners and overwrite corners with adjacent tiles | ||
662 | ffDataTopLeft = MAPSPOT(0, 0, 0); MAPSPOT(0, 0, 0) = MAPSPOT(1, 0, 0); | ||
663 | ffDataTopRight = MAPSPOT(MXX, 0, 0); MAPSPOT(MXX, 0, 0) = MAPSPOT(MXX, 1, 0); | ||
664 | ffDataBottomRight = MAPSPOT(MXX, MXX, 0); MAPSPOT(MXX, MXX, 0) = MAPSPOT(MXX - 1, MXX, 0); | ||
665 | ffDataBottomLeft = MAPSPOT(0, MXX, 0); MAPSPOT(0, MXX, 0) = MAPSPOT(0, MXX - 1, 0); | ||
666 | |||
667 | #undef MXX | ||
668 | #endif | ||
669 | |||
670 | // | ||
671 | // copy the wall data to a data segment array | ||
672 | // | ||
673 | memset (tilemap,0,sizeof(tilemap)); | ||
674 | memset (actorat,0,sizeof(actorat)); | ||
675 | map = mapsegs[0]; | ||
676 | for (y=0;y<mapheight;y++) | ||
677 | { | ||
678 | for (x=0;x<mapwidth;x++) | ||
679 | { | ||
680 | tile = *map++; | ||
681 | if (tile<AREATILE) | ||
682 | { | ||
683 | // solid wall | ||
684 | tilemap[x][y] = (byte) tile; | ||
685 | actorat[x][y] = (objtype *)(uintptr_t) tile; | ||
686 | } | ||
687 | else | ||
688 | { | ||
689 | // area floor | ||
690 | tilemap[x][y] = 0; | ||
691 | actorat[x][y] = 0; | ||
692 | } | ||
693 | } | ||
694 | } | ||
695 | |||
696 | // | ||
697 | // spawn doors | ||
698 | // | ||
699 | InitActorList (); // start spawning things with a clean slate | ||
700 | InitDoorList (); | ||
701 | InitStaticList (); | ||
702 | |||
703 | map = mapsegs[0]; | ||
704 | for (y=0;y<mapheight;y++) | ||
705 | { | ||
706 | for (x=0;x<mapwidth;x++) | ||
707 | { | ||
708 | tile = *map++; | ||
709 | if (tile >= 90 && tile <= 101) | ||
710 | { | ||
711 | // door | ||
712 | switch (tile) | ||
713 | { | ||
714 | case 90: | ||
715 | case 92: | ||
716 | case 94: | ||
717 | case 96: | ||
718 | case 98: | ||
719 | case 100: | ||
720 | SpawnDoor (x,y,1,(tile-90)/2); | ||
721 | break; | ||
722 | case 91: | ||
723 | case 93: | ||
724 | case 95: | ||
725 | case 97: | ||
726 | case 99: | ||
727 | case 101: | ||
728 | SpawnDoor (x,y,0,(tile-91)/2); | ||
729 | break; | ||
730 | } | ||
731 | } | ||
732 | } | ||
733 | } | ||
734 | |||
735 | // | ||
736 | // spawn actors | ||
737 | // | ||
738 | ScanInfoPlane (); | ||
739 | |||
740 | |||
741 | // | ||
742 | // take out the ambush markers | ||
743 | // | ||
744 | map = mapsegs[0]; | ||
745 | for (y=0;y<mapheight;y++) | ||
746 | { | ||
747 | for (x=0;x<mapwidth;x++) | ||
748 | { | ||
749 | tile = *map++; | ||
750 | if (tile == AMBUSHTILE) | ||
751 | { | ||
752 | tilemap[x][y] = 0; | ||
753 | if ( (unsigned)(uintptr_t)actorat[x][y] == AMBUSHTILE) | ||
754 | actorat[x][y] = NULL; | ||
755 | |||
756 | if (*map >= AREATILE) | ||
757 | tile = *map; | ||
758 | if (*(map-1-mapwidth) >= AREATILE) | ||
759 | tile = *(map-1-mapwidth); | ||
760 | if (*(map-1+mapwidth) >= AREATILE) | ||
761 | tile = *(map-1+mapwidth); | ||
762 | if ( *(map-2) >= AREATILE) | ||
763 | tile = *(map-2); | ||
764 | |||
765 | *(map-1) = tile; | ||
766 | } | ||
767 | } | ||
768 | } | ||
769 | |||
770 | |||
771 | // | ||
772 | // have the caching manager load and purge stuff to make sure all marks | ||
773 | // are in memory | ||
774 | // | ||
775 | CA_LoadAllSounds (); | ||
776 | } | ||
777 | |||
778 | |||
779 | //========================================================================== | ||
780 | |||
781 | |||
782 | /* | ||
783 | =================== | ||
784 | = | ||
785 | = DrawPlayBorderSides | ||
786 | = | ||
787 | = To fix window overwrites | ||
788 | = | ||
789 | =================== | ||
790 | */ | ||
791 | void DrawPlayBorderSides(void) | ||
792 | { | ||
793 | if(viewsize == 21) return; | ||
794 | |||
795 | const int sw = screenWidth; | ||
796 | const int sh = screenHeight; | ||
797 | const int vw = viewwidth; | ||
798 | const int vh = viewheight; | ||
799 | const int px = scaleFactor; // size of one "pixel" | ||
800 | |||
801 | const int h = sh - px * STATUSLINES; | ||
802 | const int xl = sw / 2 - vw / 2; | ||
803 | const int yl = (h - vh) / 2; | ||
804 | |||
805 | if(xl != 0) | ||
806 | { | ||
807 | VWB_BarScaledCoord(0, 0, xl - px, h, bordercol); // left side | ||
808 | VWB_BarScaledCoord(xl + vw + px, 0, xl - px * 2, h, bordercol); // right side | ||
809 | } | ||
810 | |||
811 | if(yl != 0) | ||
812 | { | ||
813 | VWB_BarScaledCoord(0, 0, sw, yl - px, bordercol); // upper side | ||
814 | VWB_BarScaledCoord(0, yl + vh + px, sw, yl - px, bordercol); // lower side | ||
815 | } | ||
816 | |||
817 | if(xl != 0) | ||
818 | { | ||
819 | // Paint game view border lines | ||
820 | VWB_BarScaledCoord(xl - px, yl - px, vw + px, px, 0); // upper border | ||
821 | VWB_BarScaledCoord(xl, yl + vh, vw + px, px, bordercol - 2); // lower border | ||
822 | VWB_BarScaledCoord(xl - px, yl - px, px, vh + px, 0); // left border | ||
823 | VWB_BarScaledCoord(xl + vw, yl - px, px, vh + px * 2, bordercol - 2); // right border | ||
824 | VWB_BarScaledCoord(xl - px, yl + vh, px, px, bordercol - 3); // lower left highlight | ||
825 | } | ||
826 | else | ||
827 | { | ||
828 | // Just paint a lower border line | ||
829 | VWB_BarScaledCoord(0, yl+vh, vw, px, bordercol-2); // lower border | ||
830 | } | ||
831 | } | ||
832 | |||
833 | |||
834 | /* | ||
835 | =================== | ||
836 | = | ||
837 | = DrawStatusBorder | ||
838 | = | ||
839 | =================== | ||
840 | */ | ||
841 | |||
842 | void DrawStatusBorder (byte color) | ||
843 | { | ||
844 | int statusborderw = (screenWidth-scaleFactor*320)/2; | ||
845 | |||
846 | VWB_BarScaledCoord (0,0,screenWidth,screenHeight-scaleFactor*(STATUSLINES-3),color); | ||
847 | VWB_BarScaledCoord (0,screenHeight-scaleFactor*(STATUSLINES-3), | ||
848 | statusborderw+scaleFactor*8,scaleFactor*(STATUSLINES-4),color); | ||
849 | VWB_BarScaledCoord (0,screenHeight-scaleFactor*2,screenWidth,scaleFactor*2,color); | ||
850 | VWB_BarScaledCoord (screenWidth-statusborderw-scaleFactor*8, screenHeight-scaleFactor*(STATUSLINES-3), | ||
851 | statusborderw+scaleFactor*8,scaleFactor*(STATUSLINES-4),color); | ||
852 | |||
853 | VWB_BarScaledCoord (statusborderw+scaleFactor*9, screenHeight-scaleFactor*3, | ||
854 | scaleFactor*97, scaleFactor*1, color-1); | ||
855 | VWB_BarScaledCoord (statusborderw+scaleFactor*106, screenHeight-scaleFactor*3, | ||
856 | scaleFactor*161, scaleFactor*1, color-2); | ||
857 | VWB_BarScaledCoord (statusborderw+scaleFactor*267, screenHeight-scaleFactor*3, | ||
858 | scaleFactor*44, scaleFactor*1, color-3); | ||
859 | VWB_BarScaledCoord (screenWidth-statusborderw-scaleFactor*9, screenHeight-scaleFactor*(STATUSLINES-4), | ||
860 | scaleFactor*1, scaleFactor*20, color-2); | ||
861 | VWB_BarScaledCoord (screenWidth-statusborderw-scaleFactor*9, screenHeight-scaleFactor*(STATUSLINES/2-4), | ||
862 | scaleFactor*1, scaleFactor*14, color-3); | ||
863 | } | ||
864 | |||
865 | |||
866 | /* | ||
867 | =================== | ||
868 | = | ||
869 | = DrawPlayBorder | ||
870 | = | ||
871 | =================== | ||
872 | */ | ||
873 | |||
874 | void DrawPlayBorder (void) | ||
875 | { | ||
876 | const int px = scaleFactor; // size of one "pixel" | ||
877 | |||
878 | if (bordercol != VIEWCOLOR) | ||
879 | DrawStatusBorder(bordercol); | ||
880 | else | ||
881 | { | ||
882 | const int statusborderw = (screenWidth-px*320)/2; | ||
883 | VWB_BarScaledCoord (0, screenHeight-px*STATUSLINES, | ||
884 | statusborderw+px*8, px*STATUSLINES, bordercol); | ||
885 | VWB_BarScaledCoord (screenWidth-statusborderw-px*8, screenHeight-px*STATUSLINES, | ||
886 | statusborderw+px*8, px*STATUSLINES, bordercol); | ||
887 | } | ||
888 | |||
889 | if((unsigned) viewheight == screenHeight) return; | ||
890 | |||
891 | VWB_BarScaledCoord (0,0,screenWidth,screenHeight-px*STATUSLINES,bordercol); | ||
892 | |||
893 | const int xl = screenWidth/2-viewwidth/2; | ||
894 | const int yl = (screenHeight-px*STATUSLINES-viewheight)/2; | ||
895 | VWB_BarScaledCoord (xl,yl,viewwidth,viewheight,0); | ||
896 | |||
897 | if(xl != 0) | ||
898 | { | ||
899 | // Paint game view border lines | ||
900 | VWB_BarScaledCoord(xl-px, yl-px, viewwidth+px, px, 0); // upper border | ||
901 | VWB_BarScaledCoord(xl, yl+viewheight, viewwidth+px, px, bordercol-2); // lower border | ||
902 | VWB_BarScaledCoord(xl-px, yl-px, px, viewheight+px, 0); // left border | ||
903 | VWB_BarScaledCoord(xl+viewwidth, yl-px, px, viewheight+2*px, bordercol-2); // right border | ||
904 | VWB_BarScaledCoord(xl-px, yl+viewheight, px, px, bordercol-3); // lower left highlight | ||
905 | } | ||
906 | else | ||
907 | { | ||
908 | // Just paint a lower border line | ||
909 | VWB_BarScaledCoord(0, yl+viewheight, viewwidth, px, bordercol-2); // lower border | ||
910 | } | ||
911 | } | ||
912 | |||
913 | |||
914 | /* | ||
915 | =================== | ||
916 | = | ||
917 | = DrawPlayScreen | ||
918 | = | ||
919 | =================== | ||
920 | */ | ||
921 | |||
922 | void DrawPlayScreen (void) | ||
923 | { | ||
924 | VWB_DrawPicScaledCoord ((screenWidth-scaleFactor*320)/2,screenHeight-scaleFactor*STATUSLINES,STATUSBARPIC); | ||
925 | DrawPlayBorder (); | ||
926 | |||
927 | DrawFace (); | ||
928 | DrawHealth (); | ||
929 | DrawLives (); | ||
930 | DrawLevel (); | ||
931 | DrawAmmo (); | ||
932 | DrawKeys (); | ||
933 | DrawWeapon (); | ||
934 | DrawScore (); | ||
935 | } | ||
936 | |||
937 | // Uses LatchDrawPic instead of StatusDrawPic | ||
938 | void LatchNumberHERE (int x, int y, unsigned width, int32_t number) | ||
939 | { | ||
940 | unsigned length,c; | ||
941 | char str[20]; | ||
942 | |||
943 | ltoa (number,str,10); | ||
944 | |||
945 | length = (unsigned) strlen (str); | ||
946 | |||
947 | while (length<width) | ||
948 | { | ||
949 | LatchDrawPic (x,y,N_BLANKPIC); | ||
950 | x++; | ||
951 | width--; | ||
952 | } | ||
953 | |||
954 | c = length <= width ? 0 : length-width; | ||
955 | |||
956 | while (c<length) | ||
957 | { | ||
958 | LatchDrawPic (x,y,str[c]-'0'+ N_0PIC); | ||
959 | x++; | ||
960 | c++; | ||
961 | } | ||
962 | } | ||
963 | |||
964 | void ShowActStatus() | ||
965 | { | ||
966 | // Draw status bar without borders | ||
967 | byte *source = grsegs[STATUSBARPIC]; | ||
968 | int picnum = STATUSBARPIC - STARTPICS; | ||
969 | int width = pictable[picnum].width; | ||
970 | int height = pictable[picnum].height; | ||
971 | int destx = (screenWidth-scaleFactor*320)/2 + 9 * scaleFactor; | ||
972 | int desty = screenHeight - (height - 4) * scaleFactor; | ||
973 | VL_MemToScreenScaledCoord_ex(source, width, height, 9, 4, destx, desty, width - 18, height - 7); | ||
974 | |||
975 | ingame = false; | ||
976 | DrawFace (); | ||
977 | DrawHealth (); | ||
978 | DrawLives (); | ||
979 | DrawLevel (); | ||
980 | DrawAmmo (); | ||
981 | DrawKeys (); | ||
982 | DrawWeapon (); | ||
983 | DrawScore (); | ||
984 | ingame = true; | ||
985 | } | ||
986 | |||
987 | |||
988 | //========================================================================== | ||
989 | |||
990 | /* | ||
991 | ================== | ||
992 | = | ||
993 | = StartDemoRecord | ||
994 | = | ||
995 | ================== | ||
996 | */ | ||
997 | |||
998 | char demoname[13] = "DEMO?."; | ||
999 | |||
1000 | #ifndef REMDEBUG | ||
1001 | #define MAXDEMOSIZE 8192 | ||
1002 | |||
1003 | void StartDemoRecord (int levelnumber) | ||
1004 | { | ||
1005 | demobuffer=malloc(MAXDEMOSIZE); | ||
1006 | CHECKMALLOCRESULT(demobuffer); | ||
1007 | demoptr = (int8_t *) demobuffer; | ||
1008 | lastdemoptr = demoptr+MAXDEMOSIZE; | ||
1009 | |||
1010 | *demoptr = levelnumber; | ||
1011 | demoptr += 4; // leave space for length | ||
1012 | demorecord = true; | ||
1013 | } | ||
1014 | |||
1015 | |||
1016 | /* | ||
1017 | ================== | ||
1018 | = | ||
1019 | = FinishDemoRecord | ||
1020 | = | ||
1021 | ================== | ||
1022 | */ | ||
1023 | |||
1024 | void FinishDemoRecord (void) | ||
1025 | { | ||
1026 | int32_t length,level; | ||
1027 | |||
1028 | demorecord = false; | ||
1029 | |||
1030 | length = (int32_t) (demoptr - (int8_t *)demobuffer); | ||
1031 | |||
1032 | demoptr = ((int8_t *)demobuffer)+1; | ||
1033 | demoptr[0] = (int8_t) length; | ||
1034 | demoptr[1] = (int8_t) (length >> 8); | ||
1035 | demoptr[2] = 0; | ||
1036 | |||
1037 | VW_FadeIn(); | ||
1038 | CenterWindow(24,3); | ||
1039 | PrintY+=6; | ||
1040 | fontnumber=0; | ||
1041 | SETFONTCOLOR(0,15); | ||
1042 | US_Print(" Demo number (0-9): "); | ||
1043 | VW_UpdateScreen(); | ||
1044 | |||
1045 | if (US_LineInput (px,py,str,NULL,true,1,0)) | ||
1046 | { | ||
1047 | level = atoi (str); | ||
1048 | if (level>=0 && level<=9) | ||
1049 | { | ||
1050 | demoname[4] = (char)('0'+level); | ||
1051 | CA_WriteFile (demoname,demobuffer,length); | ||
1052 | } | ||
1053 | } | ||
1054 | |||
1055 | free(demobuffer); | ||
1056 | } | ||
1057 | |||
1058 | //========================================================================== | ||
1059 | |||
1060 | /* | ||
1061 | ================== | ||
1062 | = | ||
1063 | = RecordDemo | ||
1064 | = | ||
1065 | = Fades the screen out, then starts a demo. Exits with the screen faded | ||
1066 | = | ||
1067 | ================== | ||
1068 | */ | ||
1069 | |||
1070 | void RecordDemo (void) | ||
1071 | { | ||
1072 | int level,esc,maps; | ||
1073 | |||
1074 | CenterWindow(26,3); | ||
1075 | PrintY+=6; | ||
1076 | CA_CacheGrChunk(STARTFONT); | ||
1077 | fontnumber=0; | ||
1078 | SETFONTCOLOR(0,15); | ||
1079 | #ifndef SPEAR | ||
1080 | #ifdef UPLOAD | ||
1081 | US_Print(" Demo which level(1-10): "); maps = 10; | ||
1082 | #else | ||
1083 | US_Print(" Demo which level(1-60): "); maps = 60; | ||
1084 | #endif | ||
1085 | #else | ||
1086 | US_Print(" Demo which level(1-21): "); maps = 21; | ||
1087 | #endif | ||
1088 | VW_UpdateScreen(); | ||
1089 | VW_FadeIn (); | ||
1090 | esc = !US_LineInput (px,py,str,NULL,true,2,0); | ||
1091 | if (esc) | ||
1092 | return; | ||
1093 | |||
1094 | level = atoi (str); | ||
1095 | level--; | ||
1096 | |||
1097 | if (level >= maps || level < 0) | ||
1098 | return; | ||
1099 | |||
1100 | VW_FadeOut (); | ||
1101 | |||
1102 | #ifndef SPEAR | ||
1103 | NewGame (gd_hard,level/10); | ||
1104 | gamestate.mapon = level%10; | ||
1105 | #else | ||
1106 | NewGame (gd_hard,0); | ||
1107 | gamestate.mapon = level; | ||
1108 | #endif | ||
1109 | |||
1110 | StartDemoRecord (level); | ||
1111 | |||
1112 | DrawPlayScreen (); | ||
1113 | VW_FadeIn (); | ||
1114 | |||
1115 | startgame = false; | ||
1116 | demorecord = true; | ||
1117 | |||
1118 | SetupGameLevel (); | ||
1119 | StartMusic (); | ||
1120 | |||
1121 | if(usedoublebuffering) VH_UpdateScreen(); | ||
1122 | fizzlein = true; | ||
1123 | |||
1124 | PlayLoop (); | ||
1125 | |||
1126 | demoplayback = false; | ||
1127 | |||
1128 | StopMusic (); | ||
1129 | VW_FadeOut (); | ||
1130 | ClearMemory (); | ||
1131 | |||
1132 | FinishDemoRecord (); | ||
1133 | } | ||
1134 | #else | ||
1135 | void FinishDemoRecord (void) {return;} | ||
1136 | void RecordDemo (void) {return;} | ||
1137 | #endif | ||
1138 | |||
1139 | |||
1140 | |||
1141 | //========================================================================== | ||
1142 | |||
1143 | /* | ||
1144 | ================== | ||
1145 | = | ||
1146 | = PlayDemo | ||
1147 | = | ||
1148 | = Fades the screen out, then starts a demo. Exits with the screen unfaded | ||
1149 | = | ||
1150 | ================== | ||
1151 | */ | ||
1152 | |||
1153 | void PlayDemo (int demonumber) | ||
1154 | { | ||
1155 | int length; | ||
1156 | #ifdef DEMOSEXTERN | ||
1157 | // debug: load chunk | ||
1158 | #ifndef SPEARDEMO | ||
1159 | int dems[4]={T_DEMO0,T_DEMO1,T_DEMO2,T_DEMO3}; | ||
1160 | #else | ||
1161 | int dems[1]={T_DEMO0}; | ||
1162 | #endif | ||
1163 | |||
1164 | CA_CacheGrChunk(dems[demonumber]); | ||
1165 | demoptr = (int8_t *) grsegs[dems[demonumber]]; | ||
1166 | #else | ||
1167 | demoname[4] = '0'+demonumber; | ||
1168 | CA_LoadFile (demoname,&demobuffer); | ||
1169 | demoptr = (int8_t *)demobuffer; | ||
1170 | #endif | ||
1171 | |||
1172 | NewGame (1,0); | ||
1173 | gamestate.mapon = *demoptr++; | ||
1174 | LOGF("%d", gamestate.mapon); | ||
1175 | gamestate.difficulty = gd_hard; | ||
1176 | /* FIXME POSSIBLE BUG */ | ||
1177 | length = READWORD((uint8_t **)&demoptr); | ||
1178 | LOGF("%d", length); | ||
1179 | // TODO: Seems like the original demo format supports 16 MB demos | ||
1180 | // But T_DEM00 and T_DEM01 of Wolf have a 0xd8 as third length size... | ||
1181 | demoptr++; | ||
1182 | lastdemoptr = demoptr-4+length; | ||
1183 | |||
1184 | VW_FadeOut (); | ||
1185 | |||
1186 | SETFONTCOLOR(0,15); | ||
1187 | DrawPlayScreen (); | ||
1188 | |||
1189 | startgame = false; | ||
1190 | demoplayback = true; | ||
1191 | |||
1192 | SetupGameLevel (); | ||
1193 | StartMusic (); | ||
1194 | |||
1195 | PlayLoop (); | ||
1196 | |||
1197 | #ifdef DEMOSEXTERN | ||
1198 | UNCACHEGRCHUNK(dems[demonumber]); | ||
1199 | #else | ||
1200 | MM_FreePtr (&demobuffer); | ||
1201 | #endif | ||
1202 | |||
1203 | demoplayback = false; | ||
1204 | |||
1205 | StopMusic (); | ||
1206 | ClearMemory (); | ||
1207 | } | ||
1208 | |||
1209 | //========================================================================== | ||
1210 | |||
1211 | /* | ||
1212 | ================== | ||
1213 | = | ||
1214 | = Died | ||
1215 | = | ||
1216 | ================== | ||
1217 | */ | ||
1218 | |||
1219 | #define DEATHROTATE 2 | ||
1220 | |||
1221 | void Died (void) | ||
1222 | { | ||
1223 | float fangle; | ||
1224 | int32_t dx,dy; | ||
1225 | int iangle,curangle,clockwise,counter,change; | ||
1226 | |||
1227 | if (screenfaded) | ||
1228 | { | ||
1229 | ThreeDRefresh (); | ||
1230 | VW_FadeIn (); | ||
1231 | } | ||
1232 | |||
1233 | gamestate.weapon = (weapontype) -1; // take away weapon | ||
1234 | SD_PlaySound (PLAYERDEATHSND); | ||
1235 | |||
1236 | // | ||
1237 | // swing around to face attacker | ||
1238 | // | ||
1239 | if(killerobj) | ||
1240 | { | ||
1241 | dx = killerobj->x - player->x; | ||
1242 | dy = player->y - killerobj->y; | ||
1243 | |||
1244 | fangle = (float) atan2((float) dy, (float) dx); // returns -pi to pi | ||
1245 | if (fangle<0) | ||
1246 | fangle = (float) (M_PI*2+fangle); | ||
1247 | |||
1248 | iangle = (int) (fangle/(M_PI*2)*ANGLES); | ||
1249 | } | ||
1250 | else | ||
1251 | { | ||
1252 | iangle = player->angle + ANGLES / 2; | ||
1253 | if(iangle >= ANGLES) iangle -= ANGLES; | ||
1254 | } | ||
1255 | |||
1256 | if (player->angle > iangle) | ||
1257 | { | ||
1258 | counter = player->angle - iangle; | ||
1259 | clockwise = ANGLES-player->angle + iangle; | ||
1260 | } | ||
1261 | else | ||
1262 | { | ||
1263 | clockwise = iangle - player->angle; | ||
1264 | counter = player->angle + ANGLES-iangle; | ||
1265 | } | ||
1266 | |||
1267 | curangle = player->angle; | ||
1268 | |||
1269 | if (clockwise<counter) | ||
1270 | { | ||
1271 | // | ||
1272 | // rotate clockwise | ||
1273 | // | ||
1274 | if (curangle>iangle) | ||
1275 | curangle -= ANGLES; | ||
1276 | do | ||
1277 | { | ||
1278 | change = tics*DEATHROTATE; | ||
1279 | if (curangle + change > iangle) | ||
1280 | change = iangle-curangle; | ||
1281 | |||
1282 | curangle += change; | ||
1283 | player->angle += change; | ||
1284 | if (player->angle >= ANGLES) | ||
1285 | player->angle -= ANGLES; | ||
1286 | |||
1287 | ThreeDRefresh (); | ||
1288 | CalcTics (); | ||
1289 | } while (curangle != iangle); | ||
1290 | } | ||
1291 | else | ||
1292 | { | ||
1293 | // | ||
1294 | // rotate counterclockwise | ||
1295 | // | ||
1296 | if (curangle<iangle) | ||
1297 | curangle += ANGLES; | ||
1298 | do | ||
1299 | { | ||
1300 | change = -(int)tics*DEATHROTATE; | ||
1301 | if (curangle + change < iangle) | ||
1302 | change = iangle-curangle; | ||
1303 | |||
1304 | curangle += change; | ||
1305 | player->angle += change; | ||
1306 | if (player->angle < 0) | ||
1307 | player->angle += ANGLES; | ||
1308 | |||
1309 | ThreeDRefresh (); | ||
1310 | CalcTics (); | ||
1311 | } while (curangle != iangle); | ||
1312 | } | ||
1313 | |||
1314 | // | ||
1315 | // fade to red | ||
1316 | // | ||
1317 | FinishPaletteShifts (); | ||
1318 | |||
1319 | if(usedoublebuffering) VH_UpdateScreen(); | ||
1320 | |||
1321 | VL_BarScaledCoord (viewscreenx,viewscreeny,viewwidth,viewheight,4); | ||
1322 | |||
1323 | IN_ClearKeysDown (); | ||
1324 | |||
1325 | FizzleFade(screenBuffer,viewscreenx,viewscreeny,viewwidth,viewheight,70,false); | ||
1326 | |||
1327 | IN_UserInput(100); | ||
1328 | SD_WaitSoundDone (); | ||
1329 | ClearMemory(); | ||
1330 | |||
1331 | gamestate.lives--; | ||
1332 | |||
1333 | if (gamestate.lives > -1) | ||
1334 | { | ||
1335 | gamestate.health = 100; | ||
1336 | gamestate.weapon = gamestate.bestweapon | ||
1337 | = gamestate.chosenweapon = wp_pistol; | ||
1338 | gamestate.ammo = STARTAMMO; | ||
1339 | gamestate.keys = 0; | ||
1340 | pwallstate = pwallpos = 0; | ||
1341 | gamestate.attackframe = gamestate.attackcount = | ||
1342 | gamestate.weaponframe = 0; | ||
1343 | |||
1344 | if(viewsize != 21) | ||
1345 | { | ||
1346 | DrawKeys (); | ||
1347 | DrawWeapon (); | ||
1348 | DrawAmmo (); | ||
1349 | DrawHealth (); | ||
1350 | DrawFace (); | ||
1351 | DrawLives (); | ||
1352 | } | ||
1353 | } | ||
1354 | } | ||
1355 | |||
1356 | //========================================================================== | ||
1357 | |||
1358 | /* | ||
1359 | =================== | ||
1360 | = | ||
1361 | = GameLoop | ||
1362 | = | ||
1363 | =================== | ||
1364 | */ | ||
1365 | |||
1366 | void GameLoop (void) | ||
1367 | { | ||
1368 | boolean died; | ||
1369 | #ifdef MYPROFILE | ||
1370 | clock_t start,end; | ||
1371 | #endif | ||
1372 | |||
1373 | restartgame: | ||
1374 | ClearMemory (); | ||
1375 | SETFONTCOLOR(0,15); | ||
1376 | VW_FadeOut(); | ||
1377 | DrawPlayScreen (); | ||
1378 | died = false; | ||
1379 | do | ||
1380 | { | ||
1381 | if (!loadedgame) | ||
1382 | gamestate.score = gamestate.oldscore; | ||
1383 | if(!died || viewsize != 21) DrawScore(); | ||
1384 | |||
1385 | startgame = false; | ||
1386 | if (!loadedgame) | ||
1387 | SetupGameLevel (); | ||
1388 | |||
1389 | #ifdef SPEAR | ||
1390 | if (gamestate.mapon == 20) // give them the key allways | ||
1391 | { | ||
1392 | gamestate.keys |= 1; | ||
1393 | DrawKeys (); | ||
1394 | } | ||
1395 | #endif | ||
1396 | |||
1397 | ingame = true; | ||
1398 | if(loadedgame) | ||
1399 | { | ||
1400 | ContinueMusic(lastgamemusicoffset); | ||
1401 | loadedgame = false; | ||
1402 | } | ||
1403 | else StartMusic (); | ||
1404 | |||
1405 | if (!died) | ||
1406 | PreloadGraphics (); // TODO: Let this do something useful! | ||
1407 | else | ||
1408 | { | ||
1409 | died = false; | ||
1410 | fizzlein = true; | ||
1411 | } | ||
1412 | |||
1413 | DrawLevel (); | ||
1414 | |||
1415 | #ifdef SPEAR | ||
1416 | startplayloop: | ||
1417 | #endif | ||
1418 | PlayLoop (); | ||
1419 | |||
1420 | #ifdef SPEAR | ||
1421 | if (spearflag) | ||
1422 | { | ||
1423 | SD_StopSound(); | ||
1424 | SD_PlaySound(GETSPEARSND); | ||
1425 | if (DigiMode != sds_Off) | ||
1426 | { | ||
1427 | Delay(150); | ||
1428 | } | ||
1429 | else | ||
1430 | SD_WaitSoundDone(); | ||
1431 | |||
1432 | ClearMemory (); | ||
1433 | gamestate.oldscore = gamestate.score; | ||
1434 | gamestate.mapon = 20; | ||
1435 | SetupGameLevel (); | ||
1436 | StartMusic (); | ||
1437 | player->x = spearx; | ||
1438 | player->y = speary; | ||
1439 | player->angle = (short)spearangle; | ||
1440 | spearflag = false; | ||
1441 | Thrust (0,0); | ||
1442 | goto startplayloop; | ||
1443 | } | ||
1444 | #endif | ||
1445 | |||
1446 | StopMusic (); | ||
1447 | ingame = false; | ||
1448 | |||
1449 | if (demorecord && playstate != ex_warped) | ||
1450 | FinishDemoRecord (); | ||
1451 | |||
1452 | if (startgame || loadedgame) | ||
1453 | goto restartgame; | ||
1454 | |||
1455 | switch (playstate) | ||
1456 | { | ||
1457 | case ex_completed: | ||
1458 | case ex_secretlevel: | ||
1459 | if(viewsize == 21) DrawPlayScreen(); | ||
1460 | gamestate.keys = 0; | ||
1461 | DrawKeys (); | ||
1462 | VW_FadeOut (); | ||
1463 | |||
1464 | ClearMemory (); | ||
1465 | |||
1466 | LevelCompleted (); // do the intermission | ||
1467 | if(viewsize == 21) DrawPlayScreen(); | ||
1468 | |||
1469 | #ifdef SPEARDEMO | ||
1470 | if (gamestate.mapon == 1) | ||
1471 | { | ||
1472 | died = true; // don't "get psyched!" | ||
1473 | |||
1474 | VW_FadeOut (); | ||
1475 | |||
1476 | ClearMemory (); | ||
1477 | |||
1478 | CheckHighScore (gamestate.score,gamestate.mapon+1); | ||
1479 | #ifndef JAPAN | ||
1480 | strcpy(MainMenu[viewscores].string,STR_VS); | ||
1481 | #endif | ||
1482 | MainMenu[viewscores].routine = CP_ViewScores; | ||
1483 | return; | ||
1484 | } | ||
1485 | #endif | ||
1486 | |||
1487 | #ifdef JAPDEMO | ||
1488 | if (gamestate.mapon == 3) | ||
1489 | { | ||
1490 | died = true; // don't "get psyched!" | ||
1491 | |||
1492 | VW_FadeOut (); | ||
1493 | |||
1494 | ClearMemory (); | ||
1495 | |||
1496 | CheckHighScore (gamestate.score,gamestate.mapon+1); | ||
1497 | #ifndef JAPAN | ||
1498 | strcpy(MainMenu[viewscores].string,STR_VS); | ||
1499 | #endif | ||
1500 | MainMenu[viewscores].routine = CP_ViewScores; | ||
1501 | return; | ||
1502 | } | ||
1503 | #endif | ||
1504 | |||
1505 | gamestate.oldscore = gamestate.score; | ||
1506 | |||
1507 | #ifndef SPEAR | ||
1508 | // | ||
1509 | // COMING BACK FROM SECRET LEVEL | ||
1510 | // | ||
1511 | if (gamestate.mapon == 9) | ||
1512 | gamestate.mapon = ElevatorBackTo[gamestate.episode]; // back from secret | ||
1513 | else | ||
1514 | // | ||
1515 | // GOING TO SECRET LEVEL | ||
1516 | // | ||
1517 | if (playstate == ex_secretlevel) | ||
1518 | gamestate.mapon = 9; | ||
1519 | #else | ||
1520 | |||
1521 | #define FROMSECRET1 3 | ||
1522 | #define FROMSECRET2 11 | ||
1523 | |||
1524 | // | ||
1525 | // GOING TO SECRET LEVEL | ||
1526 | // | ||
1527 | if (playstate == ex_secretlevel) | ||
1528 | switch(gamestate.mapon) | ||
1529 | { | ||
1530 | case FROMSECRET1: gamestate.mapon = 18; break; | ||
1531 | case FROMSECRET2: gamestate.mapon = 19; break; | ||
1532 | } | ||
1533 | else | ||
1534 | // | ||
1535 | // COMING BACK FROM SECRET LEVEL | ||
1536 | // | ||
1537 | if (gamestate.mapon == 18 || gamestate.mapon == 19) | ||
1538 | switch(gamestate.mapon) | ||
1539 | { | ||
1540 | case 18: gamestate.mapon = FROMSECRET1+1; break; | ||
1541 | case 19: gamestate.mapon = FROMSECRET2+1; break; | ||
1542 | } | ||
1543 | #endif | ||
1544 | else | ||
1545 | // | ||
1546 | // GOING TO NEXT LEVEL | ||
1547 | // | ||
1548 | gamestate.mapon++; | ||
1549 | break; | ||
1550 | |||
1551 | case ex_died: | ||
1552 | Died (); | ||
1553 | died = true; // don't "get psyched!" | ||
1554 | |||
1555 | if (gamestate.lives > -1) | ||
1556 | break; // more lives left | ||
1557 | |||
1558 | VW_FadeOut (); | ||
1559 | if(screenHeight % 200 != 0) | ||
1560 | VL_ClearScreen(0); | ||
1561 | |||
1562 | #ifdef _arch_dreamcast | ||
1563 | DC_StatusClearLCD(); | ||
1564 | #endif | ||
1565 | |||
1566 | ClearMemory (); | ||
1567 | |||
1568 | CheckHighScore (gamestate.score,gamestate.mapon+1); | ||
1569 | #ifndef JAPAN | ||
1570 | strcpy(MainMenu[viewscores].string,STR_VS); | ||
1571 | #endif | ||
1572 | MainMenu[viewscores].routine = CP_ViewScores; | ||
1573 | return; | ||
1574 | |||
1575 | case ex_victorious: | ||
1576 | if(viewsize == 21) DrawPlayScreen(); | ||
1577 | #ifndef SPEAR | ||
1578 | VW_FadeOut (); | ||
1579 | #else | ||
1580 | VL_FadeOut (0,255,0,17,17,300); | ||
1581 | #endif | ||
1582 | ClearMemory (); | ||
1583 | |||
1584 | Victory (); | ||
1585 | |||
1586 | ClearMemory (); | ||
1587 | |||
1588 | CheckHighScore (gamestate.score,gamestate.mapon+1); | ||
1589 | #ifndef JAPAN | ||
1590 | strcpy(MainMenu[viewscores].string,STR_VS); | ||
1591 | #endif | ||
1592 | MainMenu[viewscores].routine = CP_ViewScores; | ||
1593 | return; | ||
1594 | |||
1595 | default: | ||
1596 | if(viewsize == 21) DrawPlayScreen(); | ||
1597 | ClearMemory (); | ||
1598 | break; | ||
1599 | } | ||
1600 | } while (1); | ||
1601 | } | ||