diff options
Diffstat (limited to 'apps/plugins/sdl/progs/wolf3d/wl_play.c')
-rw-r--r-- | apps/plugins/sdl/progs/wolf3d/wl_play.c | 1366 |
1 files changed, 1366 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/wolf3d/wl_play.c b/apps/plugins/sdl/progs/wolf3d/wl_play.c new file mode 100644 index 0000000000..79efcefe50 --- /dev/null +++ b/apps/plugins/sdl/progs/wolf3d/wl_play.c | |||
@@ -0,0 +1,1366 @@ | |||
1 | // WL_PLAY.C | ||
2 | |||
3 | #include "wl_def.h" | ||
4 | #pragma hdrstop | ||
5 | |||
6 | #include "wl_cloudsky.h" | ||
7 | #include "wl_shade.h" | ||
8 | |||
9 | /* | ||
10 | ============================================================================= | ||
11 | |||
12 | LOCAL CONSTANTS | ||
13 | |||
14 | ============================================================================= | ||
15 | */ | ||
16 | |||
17 | #define sc_Question 0x35 | ||
18 | |||
19 | /* | ||
20 | ============================================================================= | ||
21 | |||
22 | GLOBAL VARIABLES | ||
23 | |||
24 | ============================================================================= | ||
25 | */ | ||
26 | |||
27 | boolean madenoise; // true when shooting or screaming | ||
28 | |||
29 | exit_t playstate; | ||
30 | |||
31 | static musicnames lastmusicchunk = (musicnames) 0; | ||
32 | |||
33 | static int DebugOk; | ||
34 | |||
35 | objtype objlist[MAXACTORS]; | ||
36 | objtype *newobj, *obj, *player, *lastobj, *objfreelist, *killerobj; | ||
37 | |||
38 | boolean noclip, ammocheat; | ||
39 | int godmode, singlestep, extravbls = 0; | ||
40 | |||
41 | byte tilemap[MAPSIZE][MAPSIZE]; // wall values only | ||
42 | byte spotvis[MAPSIZE][MAPSIZE]; | ||
43 | objtype *actorat[MAPSIZE][MAPSIZE]; | ||
44 | |||
45 | // | ||
46 | // replacing refresh manager | ||
47 | // | ||
48 | unsigned tics; | ||
49 | |||
50 | // | ||
51 | // control info | ||
52 | // | ||
53 | boolean mouseenabled, joystickenabled; | ||
54 | int dirscan[4] = { sc_UpArrow, sc_RightArrow, sc_DownArrow, sc_LeftArrow }; | ||
55 | |||
56 | int buttonscan[NUMBUTTONS] = { sc_Return, sc_Alt, sc_LShift, sc_UpArrow, sc_1, sc_2, sc_3, sc_4, | ||
57 | sc_DownArrow, 0, 0, 0, sc_A, sc_D }; | ||
58 | int buttonmouse[4] = { bt_attack, bt_strafe, bt_use, bt_nobutton }; | ||
59 | int buttonjoy[32] = { | ||
60 | #ifdef _arch_dreamcast | ||
61 | bt_attack, bt_strafe, bt_use, bt_run, bt_esc, bt_prevweapon, bt_nobutton, bt_nextweapon, | ||
62 | bt_pause, bt_strafeleft, bt_straferight, bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton, | ||
63 | #else | ||
64 | bt_attack, bt_strafe, bt_use, bt_run, bt_strafeleft, bt_straferight, bt_esc, bt_pause, | ||
65 | bt_prevweapon, bt_nextweapon, bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton, | ||
66 | #endif | ||
67 | bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton, | ||
68 | bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton, bt_nobutton | ||
69 | }; | ||
70 | |||
71 | int viewsize; | ||
72 | |||
73 | boolean buttonheld[NUMBUTTONS]; | ||
74 | |||
75 | boolean demorecord, demoplayback; | ||
76 | int8_t *demoptr, *lastdemoptr; | ||
77 | memptr demobuffer; | ||
78 | |||
79 | // | ||
80 | // current user input | ||
81 | // | ||
82 | int controlx, controly; // range from -100 to 100 per tic | ||
83 | boolean buttonstate[NUMBUTTONS]; | ||
84 | |||
85 | int lastgamemusicoffset = 0; | ||
86 | |||
87 | |||
88 | //=========================================================================== | ||
89 | |||
90 | |||
91 | void CenterWindow (word w, word h); | ||
92 | void InitObjList (void); | ||
93 | void RemoveObj (objtype * gone); | ||
94 | void PollControls (void); | ||
95 | int StopMusic (void); | ||
96 | void StartMusic (void); | ||
97 | void ContinueMusic (int offs); | ||
98 | void PlayLoop (void); | ||
99 | |||
100 | /* | ||
101 | ============================================================================= | ||
102 | |||
103 | LOCAL VARIABLES | ||
104 | |||
105 | ============================================================================= | ||
106 | */ | ||
107 | |||
108 | |||
109 | objtype dummyobj; | ||
110 | |||
111 | // | ||
112 | // LIST OF SONGS FOR EACH VERSION | ||
113 | // | ||
114 | int songs[] = { | ||
115 | #ifndef SPEAR | ||
116 | // | ||
117 | // Episode One | ||
118 | // | ||
119 | GETTHEM_MUS, | ||
120 | SEARCHN_MUS, | ||
121 | POW_MUS, | ||
122 | SUSPENSE_MUS, | ||
123 | GETTHEM_MUS, | ||
124 | SEARCHN_MUS, | ||
125 | POW_MUS, | ||
126 | SUSPENSE_MUS, | ||
127 | |||
128 | WARMARCH_MUS, // Boss level | ||
129 | CORNER_MUS, // Secret level | ||
130 | |||
131 | // | ||
132 | // Episode Two | ||
133 | // | ||
134 | NAZI_OMI_MUS, | ||
135 | PREGNANT_MUS, | ||
136 | GOINGAFT_MUS, | ||
137 | HEADACHE_MUS, | ||
138 | NAZI_OMI_MUS, | ||
139 | PREGNANT_MUS, | ||
140 | HEADACHE_MUS, | ||
141 | GOINGAFT_MUS, | ||
142 | |||
143 | WARMARCH_MUS, // Boss level | ||
144 | DUNGEON_MUS, // Secret level | ||
145 | |||
146 | // | ||
147 | // Episode Three | ||
148 | // | ||
149 | INTROCW3_MUS, | ||
150 | NAZI_RAP_MUS, | ||
151 | TWELFTH_MUS, | ||
152 | ZEROHOUR_MUS, | ||
153 | INTROCW3_MUS, | ||
154 | NAZI_RAP_MUS, | ||
155 | TWELFTH_MUS, | ||
156 | ZEROHOUR_MUS, | ||
157 | |||
158 | ULTIMATE_MUS, // Boss level | ||
159 | PACMAN_MUS, // Secret level | ||
160 | |||
161 | // | ||
162 | // Episode Four | ||
163 | // | ||
164 | GETTHEM_MUS, | ||
165 | SEARCHN_MUS, | ||
166 | POW_MUS, | ||
167 | SUSPENSE_MUS, | ||
168 | GETTHEM_MUS, | ||
169 | SEARCHN_MUS, | ||
170 | POW_MUS, | ||
171 | SUSPENSE_MUS, | ||
172 | |||
173 | WARMARCH_MUS, // Boss level | ||
174 | CORNER_MUS, // Secret level | ||
175 | |||
176 | // | ||
177 | // Episode Five | ||
178 | // | ||
179 | NAZI_OMI_MUS, | ||
180 | PREGNANT_MUS, | ||
181 | GOINGAFT_MUS, | ||
182 | HEADACHE_MUS, | ||
183 | NAZI_OMI_MUS, | ||
184 | PREGNANT_MUS, | ||
185 | HEADACHE_MUS, | ||
186 | GOINGAFT_MUS, | ||
187 | |||
188 | WARMARCH_MUS, // Boss level | ||
189 | DUNGEON_MUS, // Secret level | ||
190 | |||
191 | // | ||
192 | // Episode Six | ||
193 | // | ||
194 | INTROCW3_MUS, | ||
195 | NAZI_RAP_MUS, | ||
196 | TWELFTH_MUS, | ||
197 | ZEROHOUR_MUS, | ||
198 | INTROCW3_MUS, | ||
199 | NAZI_RAP_MUS, | ||
200 | TWELFTH_MUS, | ||
201 | ZEROHOUR_MUS, | ||
202 | |||
203 | ULTIMATE_MUS, // Boss level | ||
204 | FUNKYOU_MUS // Secret level | ||
205 | #else | ||
206 | |||
207 | ////////////////////////////////////////////////////////////// | ||
208 | // | ||
209 | // SPEAR OF DESTINY TRACKS | ||
210 | // | ||
211 | ////////////////////////////////////////////////////////////// | ||
212 | XTIPTOE_MUS, | ||
213 | XFUNKIE_MUS, | ||
214 | XDEATH_MUS, | ||
215 | XGETYOU_MUS, // DON'T KNOW | ||
216 | ULTIMATE_MUS, // Trans Gr”sse | ||
217 | |||
218 | DUNGEON_MUS, | ||
219 | GOINGAFT_MUS, | ||
220 | POW_MUS, | ||
221 | TWELFTH_MUS, | ||
222 | ULTIMATE_MUS, // Barnacle Wilhelm BOSS | ||
223 | |||
224 | NAZI_OMI_MUS, | ||
225 | GETTHEM_MUS, | ||
226 | SUSPENSE_MUS, | ||
227 | SEARCHN_MUS, | ||
228 | ZEROHOUR_MUS, | ||
229 | ULTIMATE_MUS, // Super Mutant BOSS | ||
230 | |||
231 | XPUTIT_MUS, | ||
232 | ULTIMATE_MUS, // Death Knight BOSS | ||
233 | |||
234 | XJAZNAZI_MUS, // Secret level | ||
235 | XFUNKIE_MUS, // Secret level (DON'T KNOW) | ||
236 | |||
237 | XEVIL_MUS // Angel of Death BOSS | ||
238 | #endif | ||
239 | }; | ||
240 | |||
241 | |||
242 | /* | ||
243 | ============================================================================= | ||
244 | |||
245 | USER CONTROL | ||
246 | |||
247 | ============================================================================= | ||
248 | */ | ||
249 | |||
250 | /* | ||
251 | =================== | ||
252 | = | ||
253 | = PollKeyboardButtons | ||
254 | = | ||
255 | =================== | ||
256 | */ | ||
257 | |||
258 | void PollKeyboardButtons (void) | ||
259 | { | ||
260 | int i; | ||
261 | |||
262 | //LOGF("button state: "); | ||
263 | for (i = 0; i < NUMBUTTONS; i++) | ||
264 | { | ||
265 | if (Keyboard[buttonscan[i]]) | ||
266 | { | ||
267 | buttonstate[i] = true; | ||
268 | LOGF("enabling bit %d in buttonstate"); | ||
269 | } | ||
270 | //LOGF("%d ", buttonstate[i]); | ||
271 | } | ||
272 | //LOGF("\n"); | ||
273 | } | ||
274 | |||
275 | |||
276 | /* | ||
277 | =================== | ||
278 | = | ||
279 | = PollMouseButtons | ||
280 | = | ||
281 | =================== | ||
282 | */ | ||
283 | |||
284 | void PollMouseButtons (void) | ||
285 | { | ||
286 | int buttons = IN_MouseButtons (); | ||
287 | |||
288 | if (buttons & 1) | ||
289 | buttonstate[buttonmouse[0]] = true; | ||
290 | if (buttons & 2) | ||
291 | buttonstate[buttonmouse[1]] = true; | ||
292 | if (buttons & 4) | ||
293 | buttonstate[buttonmouse[2]] = true; | ||
294 | } | ||
295 | |||
296 | |||
297 | |||
298 | /* | ||
299 | =================== | ||
300 | = | ||
301 | = PollJoystickButtons | ||
302 | = | ||
303 | =================== | ||
304 | */ | ||
305 | |||
306 | void PollJoystickButtons (void) | ||
307 | { | ||
308 | int buttons = IN_JoyButtons(); | ||
309 | |||
310 | for(int i = 0, val = 1; i < JoyNumButtons; i++, val <<= 1) | ||
311 | { | ||
312 | if(buttons & val) | ||
313 | buttonstate[buttonjoy[i]] = true; | ||
314 | } | ||
315 | } | ||
316 | |||
317 | |||
318 | /* | ||
319 | =================== | ||
320 | = | ||
321 | = PollKeyboardMove | ||
322 | = | ||
323 | =================== | ||
324 | */ | ||
325 | |||
326 | void PollKeyboardMove (void) | ||
327 | { | ||
328 | int delta = buttonstate[bt_run] ? RUNMOVE * tics : BASEMOVE * tics; | ||
329 | |||
330 | if (Keyboard[dirscan[di_north]]) | ||
331 | controly -= delta; | ||
332 | if (Keyboard[dirscan[di_south]]) | ||
333 | controly += delta; | ||
334 | if (Keyboard[dirscan[di_west]]) | ||
335 | controlx -= delta; | ||
336 | if (Keyboard[dirscan[di_east]]) | ||
337 | controlx += delta; | ||
338 | } | ||
339 | |||
340 | |||
341 | /* | ||
342 | =================== | ||
343 | = | ||
344 | = PollMouseMove | ||
345 | = | ||
346 | =================== | ||
347 | */ | ||
348 | |||
349 | void PollMouseMove (void) | ||
350 | { | ||
351 | int mousexmove, mouseymove; | ||
352 | |||
353 | SDL_GetMouseState(&mousexmove, &mouseymove); | ||
354 | if(IN_IsInputGrabbed()) | ||
355 | IN_CenterMouse(); | ||
356 | |||
357 | mousexmove -= screenWidth / 2; | ||
358 | mouseymove -= screenHeight / 2; | ||
359 | |||
360 | controlx += mousexmove * 10 / (13 - mouseadjustment); | ||
361 | controly += mouseymove * 20 / (13 - mouseadjustment); | ||
362 | } | ||
363 | |||
364 | |||
365 | /* | ||
366 | =================== | ||
367 | = | ||
368 | = PollJoystickMove | ||
369 | = | ||
370 | =================== | ||
371 | */ | ||
372 | |||
373 | void PollJoystickMove (void) | ||
374 | { | ||
375 | int joyx, joyy; | ||
376 | |||
377 | IN_GetJoyDelta (&joyx, &joyy); | ||
378 | |||
379 | int delta = buttonstate[bt_run] ? RUNMOVE * tics : BASEMOVE * tics; | ||
380 | |||
381 | if (joyx > 64 || buttonstate[bt_turnright]) | ||
382 | controlx += delta; | ||
383 | else if (joyx < -64 || buttonstate[bt_turnleft]) | ||
384 | controlx -= delta; | ||
385 | if (joyy > 64 || buttonstate[bt_movebackward]) | ||
386 | controly += delta; | ||
387 | else if (joyy < -64 || buttonstate[bt_moveforward]) | ||
388 | controly -= delta; | ||
389 | } | ||
390 | |||
391 | /* | ||
392 | =================== | ||
393 | = | ||
394 | = PollControls | ||
395 | = | ||
396 | = Gets user or demo input, call once each frame | ||
397 | = | ||
398 | = controlx set between -100 and 100 per tic | ||
399 | = controly | ||
400 | = buttonheld[] the state of the buttons LAST frame | ||
401 | = buttonstate[] the state of the buttons THIS frame | ||
402 | = | ||
403 | =================== | ||
404 | */ | ||
405 | |||
406 | void PollControls (void) | ||
407 | { | ||
408 | int max, min, i; | ||
409 | byte buttonbits; | ||
410 | |||
411 | IN_ProcessEvents(); | ||
412 | |||
413 | // | ||
414 | // get timing info for last frame | ||
415 | // | ||
416 | if (demoplayback || demorecord) // demo recording and playback needs to be constant | ||
417 | { | ||
418 | // wait up to DEMOTICS Wolf tics | ||
419 | uint32_t curtime = SDL_GetTicks(); | ||
420 | lasttimecount += DEMOTICS; | ||
421 | int32_t timediff = (lasttimecount * 100) / 7 - curtime; | ||
422 | if(timediff > 0) | ||
423 | SDL_Delay(timediff); | ||
424 | |||
425 | if(timediff < -2 * DEMOTICS) // more than 2-times DEMOTICS behind? | ||
426 | lasttimecount = (curtime * 7) / 100; // yes, set to current timecount | ||
427 | |||
428 | tics = DEMOTICS; | ||
429 | } | ||
430 | else | ||
431 | CalcTics (); | ||
432 | |||
433 | controlx = 0; | ||
434 | controly = 0; | ||
435 | memcpy (buttonheld, buttonstate, sizeof (buttonstate)); | ||
436 | memset (buttonstate, 0, sizeof (buttonstate)); | ||
437 | |||
438 | if (demoplayback) | ||
439 | { | ||
440 | // | ||
441 | // read commands from demo buffer | ||
442 | // | ||
443 | buttonbits = *demoptr++; | ||
444 | for (i = 0; i < NUMBUTTONS; i++) | ||
445 | { | ||
446 | buttonstate[i] = buttonbits & 1; | ||
447 | buttonbits >>= 1; | ||
448 | } | ||
449 | |||
450 | controlx = *demoptr++; | ||
451 | controly = *demoptr++; | ||
452 | LOGF("%d %d %d", buttonbits, controlx, controly); | ||
453 | |||
454 | if (demoptr == lastdemoptr) | ||
455 | playstate = ex_completed; // demo is done | ||
456 | |||
457 | controlx *= (int) tics; | ||
458 | controly *= (int) tics; | ||
459 | |||
460 | return; | ||
461 | } | ||
462 | |||
463 | |||
464 | // | ||
465 | // get button states | ||
466 | // | ||
467 | PollKeyboardButtons (); | ||
468 | |||
469 | // if (mouseenabled && IN_IsInputGrabbed()) | ||
470 | // PollMouseButtons (); | ||
471 | |||
472 | if (joystickenabled) | ||
473 | PollJoystickButtons (); | ||
474 | |||
475 | // | ||
476 | // get movements | ||
477 | // | ||
478 | PollKeyboardMove (); | ||
479 | |||
480 | // if (mouseenabled && IN_IsInputGrabbed()) | ||
481 | // PollMouseMove (); | ||
482 | |||
483 | if (joystickenabled) | ||
484 | PollJoystickMove (); | ||
485 | |||
486 | // | ||
487 | // bound movement to a maximum | ||
488 | // | ||
489 | max = 100 * tics; | ||
490 | min = -max; | ||
491 | if (controlx > max) | ||
492 | controlx = max; | ||
493 | else if (controlx < min) | ||
494 | controlx = min; | ||
495 | |||
496 | if (controly > max) | ||
497 | controly = max; | ||
498 | else if (controly < min) | ||
499 | controly = min; | ||
500 | |||
501 | if (demorecord) | ||
502 | { | ||
503 | // | ||
504 | // save info out to demo buffer | ||
505 | // | ||
506 | controlx /= (int) tics; | ||
507 | controly /= (int) tics; | ||
508 | |||
509 | buttonbits = 0; | ||
510 | |||
511 | // TODO: Support 32-bit buttonbits | ||
512 | for (i = NUMBUTTONS - 1; i >= 0; i--) | ||
513 | { | ||
514 | buttonbits <<= 1; | ||
515 | if (buttonstate[i]) | ||
516 | buttonbits |= 1; | ||
517 | } | ||
518 | |||
519 | *demoptr++ = buttonbits; | ||
520 | *demoptr++ = controlx; | ||
521 | *demoptr++ = controly; | ||
522 | |||
523 | if (demoptr >= lastdemoptr - 8) | ||
524 | playstate = ex_completed; | ||
525 | else | ||
526 | { | ||
527 | controlx *= (int) tics; | ||
528 | controly *= (int) tics; | ||
529 | } | ||
530 | } | ||
531 | } | ||
532 | |||
533 | |||
534 | |||
535 | //========================================================================== | ||
536 | |||
537 | |||
538 | |||
539 | /////////////////////////////////////////////////////////////////////////// | ||
540 | // | ||
541 | // CenterWindow() - Generates a window of a given width & height in the | ||
542 | // middle of the screen | ||
543 | // | ||
544 | /////////////////////////////////////////////////////////////////////////// | ||
545 | #define MAXX 320 | ||
546 | #define MAXY 160 | ||
547 | |||
548 | void CenterWindow (word w, word h) | ||
549 | { | ||
550 | US_DrawWindow (((MAXX / 8) - w) / 2, ((MAXY / 8) - h) / 2, w, h); | ||
551 | } | ||
552 | |||
553 | //=========================================================================== | ||
554 | |||
555 | |||
556 | /* | ||
557 | ===================== | ||
558 | = | ||
559 | = CheckKeys | ||
560 | = | ||
561 | ===================== | ||
562 | */ | ||
563 | |||
564 | void CheckKeys (void) | ||
565 | { | ||
566 | ScanCode scan; | ||
567 | |||
568 | |||
569 | if (screenfaded || demoplayback) // don't do anything with a faded screen | ||
570 | return; | ||
571 | |||
572 | scan = LastScan; | ||
573 | |||
574 | |||
575 | #ifdef SPEAR | ||
576 | // | ||
577 | // SECRET CHEAT CODE: TAB-G-F10 | ||
578 | // | ||
579 | if (Keyboard[sc_Tab] && Keyboard[sc_G] && Keyboard[sc_F10]) | ||
580 | { | ||
581 | WindowH = 160; | ||
582 | if (godmode) | ||
583 | { | ||
584 | Message ("God mode OFF"); | ||
585 | SD_PlaySound (NOBONUSSND); | ||
586 | } | ||
587 | else | ||
588 | { | ||
589 | Message ("God mode ON"); | ||
590 | SD_PlaySound (ENDBONUS2SND); | ||
591 | } | ||
592 | |||
593 | IN_Ack (); | ||
594 | godmode ^= 1; | ||
595 | DrawPlayBorderSides (); | ||
596 | IN_ClearKeysDown (); | ||
597 | return; | ||
598 | } | ||
599 | #endif | ||
600 | |||
601 | |||
602 | // | ||
603 | // SECRET CHEAT CODE: 'MLI' | ||
604 | // | ||
605 | if (Keyboard[sc_M] && Keyboard[sc_L] && Keyboard[sc_I]) | ||
606 | { | ||
607 | gamestate.health = 100; | ||
608 | gamestate.ammo = 99; | ||
609 | gamestate.keys = 3; | ||
610 | gamestate.score = 0; | ||
611 | gamestate.TimeCount += 42000L; | ||
612 | GiveWeapon (wp_chaingun); | ||
613 | DrawWeapon (); | ||
614 | DrawHealth (); | ||
615 | DrawKeys (); | ||
616 | DrawAmmo (); | ||
617 | DrawScore (); | ||
618 | |||
619 | ClearMemory (); | ||
620 | CA_CacheGrChunk (STARTFONT + 1); | ||
621 | ClearSplitVWB (); | ||
622 | |||
623 | Message (STR_CHEATER1 "\n" | ||
624 | STR_CHEATER2 "\n\n" STR_CHEATER3 "\n" STR_CHEATER4 "\n" STR_CHEATER5); | ||
625 | |||
626 | UNCACHEGRCHUNK (STARTFONT + 1); | ||
627 | IN_ClearKeysDown (); | ||
628 | IN_Ack (); | ||
629 | |||
630 | if (viewsize < 17) | ||
631 | DrawPlayBorder (); | ||
632 | } | ||
633 | |||
634 | // | ||
635 | // OPEN UP DEBUG KEYS | ||
636 | // | ||
637 | #ifdef DEBUGKEYS | ||
638 | if (Keyboard[sc_BackSpace] && Keyboard[sc_LShift] && Keyboard[sc_Alt] && param_debugmode) | ||
639 | { | ||
640 | ClearMemory (); | ||
641 | CA_CacheGrChunk (STARTFONT + 1); | ||
642 | ClearSplitVWB (); | ||
643 | |||
644 | Message ("Debugging keys are\nnow available!"); | ||
645 | UNCACHEGRCHUNK (STARTFONT + 1); | ||
646 | IN_ClearKeysDown (); | ||
647 | IN_Ack (); | ||
648 | |||
649 | DrawPlayBorderSides (); | ||
650 | DebugOk = 1; | ||
651 | } | ||
652 | #endif | ||
653 | |||
654 | // | ||
655 | // TRYING THE KEEN CHEAT CODE! | ||
656 | // | ||
657 | if (Keyboard[sc_B] && Keyboard[sc_A] && Keyboard[sc_T]) | ||
658 | { | ||
659 | ClearMemory (); | ||
660 | CA_CacheGrChunk (STARTFONT + 1); | ||
661 | ClearSplitVWB (); | ||
662 | |||
663 | Message ("Commander Keen is also\n" | ||
664 | "available from Apogee, but\n" | ||
665 | "then, you already know\n" "that - right, Cheatmeister?!"); | ||
666 | |||
667 | UNCACHEGRCHUNK (STARTFONT + 1); | ||
668 | IN_ClearKeysDown (); | ||
669 | IN_Ack (); | ||
670 | |||
671 | if (viewsize < 18) | ||
672 | DrawPlayBorder (); | ||
673 | } | ||
674 | |||
675 | // | ||
676 | // pause key weirdness can't be checked as a scan code | ||
677 | // | ||
678 | if(buttonstate[bt_pause]) Paused = true; | ||
679 | if(Paused) | ||
680 | { | ||
681 | int lastoffs = StopMusic(); | ||
682 | LatchDrawPic (20 - 4, 80 - 2 * 8, PAUSEDPIC); | ||
683 | VH_UpdateScreen(); | ||
684 | IN_Ack (); | ||
685 | Paused = false; | ||
686 | ContinueMusic(lastoffs); | ||
687 | if (MousePresent && IN_IsInputGrabbed()) | ||
688 | IN_CenterMouse(); // Clear accumulated mouse movement | ||
689 | lasttimecount = GetTimeCount(); | ||
690 | return; | ||
691 | } | ||
692 | |||
693 | // | ||
694 | // F1-F7/ESC to enter control panel | ||
695 | // | ||
696 | if ( | ||
697 | #ifndef DEBCHECK | ||
698 | scan == sc_F10 || | ||
699 | #endif | ||
700 | scan == sc_F9 || scan == sc_F7 || scan == sc_F8) // pop up quit dialog | ||
701 | { | ||
702 | short oldmapon = gamestate.mapon; | ||
703 | short oldepisode = gamestate.episode; | ||
704 | ClearMemory (); | ||
705 | ClearSplitVWB (); | ||
706 | US_ControlPanel (scan); | ||
707 | |||
708 | DrawPlayBorderSides (); | ||
709 | |||
710 | SETFONTCOLOR (0, 15); | ||
711 | IN_ClearKeysDown (); | ||
712 | return; | ||
713 | } | ||
714 | |||
715 | if ((scan >= sc_F1 && scan <= sc_F9) || scan == sc_Escape || buttonstate[bt_esc]) | ||
716 | { | ||
717 | int lastoffs = StopMusic (); | ||
718 | ClearMemory (); | ||
719 | VW_FadeOut (); | ||
720 | |||
721 | US_ControlPanel (buttonstate[bt_esc] ? sc_Escape : scan); | ||
722 | |||
723 | SETFONTCOLOR (0, 15); | ||
724 | IN_ClearKeysDown (); | ||
725 | VW_FadeOut(); | ||
726 | if(viewsize != 21) | ||
727 | DrawPlayScreen (); | ||
728 | if (!startgame && !loadedgame) | ||
729 | ContinueMusic (lastoffs); | ||
730 | if (loadedgame) | ||
731 | playstate = ex_abort; | ||
732 | lasttimecount = GetTimeCount(); | ||
733 | if (MousePresent && IN_IsInputGrabbed()) | ||
734 | IN_CenterMouse(); // Clear accumulated mouse movement | ||
735 | return; | ||
736 | } | ||
737 | |||
738 | // | ||
739 | // TAB-? debug keys | ||
740 | // | ||
741 | #ifdef DEBUGKEYS | ||
742 | if (Keyboard[sc_Tab] && DebugOk) | ||
743 | { | ||
744 | CA_CacheGrChunk (STARTFONT); | ||
745 | fontnumber = 0; | ||
746 | SETFONTCOLOR (0, 15); | ||
747 | if (DebugKeys () && viewsize < 20) | ||
748 | DrawPlayBorder (); // dont let the blue borders flash | ||
749 | |||
750 | if (MousePresent && IN_IsInputGrabbed()) | ||
751 | IN_CenterMouse(); // Clear accumulated mouse movement | ||
752 | |||
753 | lasttimecount = GetTimeCount(); | ||
754 | return; | ||
755 | } | ||
756 | #endif | ||
757 | } | ||
758 | |||
759 | |||
760 | //=========================================================================== | ||
761 | |||
762 | /* | ||
763 | ############################################################################# | ||
764 | |||
765 | The objlist data structure | ||
766 | |||
767 | ############################################################################# | ||
768 | |||
769 | objlist containt structures for every actor currently playing. The structure | ||
770 | is accessed as a linked list starting at *player, ending when ob->next == | ||
771 | NULL. GetNewObj inserts a new object at the end of the list, meaning that | ||
772 | if an actor spawn another actor, the new one WILL get to think and react the | ||
773 | same frame. RemoveObj unlinks the given object and returns it to the free | ||
774 | list, but does not damage the objects ->next pointer, so if the current object | ||
775 | removes itself, a linked list following loop can still safely get to the | ||
776 | next element. | ||
777 | |||
778 | <backwardly linked free list> | ||
779 | |||
780 | ############################################################################# | ||
781 | */ | ||
782 | |||
783 | |||
784 | /* | ||
785 | ========================= | ||
786 | = | ||
787 | = InitActorList | ||
788 | = | ||
789 | = Call to clear out the actor object lists returning them all to the free | ||
790 | = list. Allocates a special spot for the player. | ||
791 | = | ||
792 | ========================= | ||
793 | */ | ||
794 | |||
795 | int objcount; | ||
796 | |||
797 | void InitActorList (void) | ||
798 | { | ||
799 | int i; | ||
800 | |||
801 | // | ||
802 | // init the actor lists | ||
803 | // | ||
804 | for (i = 0; i < MAXACTORS; i++) | ||
805 | { | ||
806 | objlist[i].prev = &objlist[i + 1]; | ||
807 | objlist[i].next = NULL; | ||
808 | } | ||
809 | |||
810 | objlist[MAXACTORS - 1].prev = NULL; | ||
811 | |||
812 | objfreelist = &objlist[0]; | ||
813 | lastobj = NULL; | ||
814 | |||
815 | objcount = 0; | ||
816 | |||
817 | // | ||
818 | // give the player the first free spots | ||
819 | // | ||
820 | GetNewActor (); | ||
821 | player = newobj; | ||
822 | |||
823 | } | ||
824 | |||
825 | //=========================================================================== | ||
826 | |||
827 | /* | ||
828 | ========================= | ||
829 | = | ||
830 | = GetNewActor | ||
831 | = | ||
832 | = Sets the global variable new to point to a free spot in objlist. | ||
833 | = The free spot is inserted at the end of the liked list | ||
834 | = | ||
835 | = When the object list is full, the caller can either have it bomb out ot | ||
836 | = return a dummy object pointer that will never get used | ||
837 | = | ||
838 | ========================= | ||
839 | */ | ||
840 | |||
841 | void GetNewActor (void) | ||
842 | { | ||
843 | if (!objfreelist) | ||
844 | Quit ("GetNewActor: No free spots in objlist!"); | ||
845 | |||
846 | newobj = objfreelist; | ||
847 | objfreelist = newobj->prev; | ||
848 | memset (newobj, 0, sizeof (*newobj)); | ||
849 | |||
850 | if (lastobj) | ||
851 | lastobj->next = newobj; | ||
852 | newobj->prev = lastobj; // new->next is allready NULL from memset | ||
853 | |||
854 | newobj->active = ac_no; | ||
855 | lastobj = newobj; | ||
856 | |||
857 | objcount++; | ||
858 | } | ||
859 | |||
860 | //=========================================================================== | ||
861 | |||
862 | /* | ||
863 | ========================= | ||
864 | = | ||
865 | = RemoveObj | ||
866 | = | ||
867 | = Add the given object back into the free list, and unlink it from it's | ||
868 | = neighbors | ||
869 | = | ||
870 | ========================= | ||
871 | */ | ||
872 | |||
873 | void RemoveObj (objtype * gone) | ||
874 | { | ||
875 | if (gone == player) | ||
876 | Quit ("RemoveObj: Tried to remove the player!"); | ||
877 | |||
878 | gone->state = NULL; | ||
879 | |||
880 | // | ||
881 | // fix the next object's back link | ||
882 | // | ||
883 | if (gone == lastobj) | ||
884 | lastobj = (objtype *) gone->prev; | ||
885 | else | ||
886 | gone->next->prev = gone->prev; | ||
887 | |||
888 | // | ||
889 | // fix the previous object's forward link | ||
890 | // | ||
891 | gone->prev->next = gone->next; | ||
892 | |||
893 | // | ||
894 | // add it back in to the free list | ||
895 | // | ||
896 | gone->prev = objfreelist; | ||
897 | objfreelist = gone; | ||
898 | |||
899 | objcount--; | ||
900 | } | ||
901 | |||
902 | /* | ||
903 | ============================================================================= | ||
904 | |||
905 | MUSIC STUFF | ||
906 | |||
907 | ============================================================================= | ||
908 | */ | ||
909 | |||
910 | |||
911 | /* | ||
912 | ================= | ||
913 | = | ||
914 | = StopMusic | ||
915 | = | ||
916 | ================= | ||
917 | */ | ||
918 | int StopMusic (void) | ||
919 | { | ||
920 | int lastoffs = SD_MusicOff (); | ||
921 | |||
922 | UNCACHEAUDIOCHUNK (STARTMUSIC + lastmusicchunk); | ||
923 | |||
924 | return lastoffs; | ||
925 | } | ||
926 | |||
927 | //========================================================================== | ||
928 | |||
929 | |||
930 | /* | ||
931 | ================= | ||
932 | = | ||
933 | = StartMusic | ||
934 | = | ||
935 | ================= | ||
936 | */ | ||
937 | |||
938 | void StartMusic () | ||
939 | { | ||
940 | SD_MusicOff (); | ||
941 | lastmusicchunk = (musicnames) songs[gamestate.mapon + gamestate.episode * 10]; | ||
942 | SD_StartMusic(STARTMUSIC + lastmusicchunk); | ||
943 | } | ||
944 | |||
945 | void ContinueMusic (int offs) | ||
946 | { | ||
947 | SD_MusicOff (); | ||
948 | lastmusicchunk = (musicnames) songs[gamestate.mapon + gamestate.episode * 10]; | ||
949 | SD_ContinueMusic(STARTMUSIC + lastmusicchunk, offs); | ||
950 | } | ||
951 | |||
952 | /* | ||
953 | ============================================================================= | ||
954 | |||
955 | PALETTE SHIFTING STUFF | ||
956 | |||
957 | ============================================================================= | ||
958 | */ | ||
959 | |||
960 | #define NUMREDSHIFTS 6 | ||
961 | #define REDSTEPS 8 | ||
962 | |||
963 | #define NUMWHITESHIFTS 3 | ||
964 | #define WHITESTEPS 20 | ||
965 | #define WHITETICS 6 | ||
966 | |||
967 | |||
968 | SDL_Color redshifts[NUMREDSHIFTS][256]; | ||
969 | SDL_Color whiteshifts[NUMWHITESHIFTS][256]; | ||
970 | |||
971 | int damagecount, bonuscount; | ||
972 | boolean palshifted; | ||
973 | |||
974 | /* | ||
975 | ===================== | ||
976 | = | ||
977 | = InitRedShifts | ||
978 | = | ||
979 | ===================== | ||
980 | */ | ||
981 | |||
982 | void InitRedShifts (void) | ||
983 | { | ||
984 | SDL_Color *workptr, *baseptr; | ||
985 | int i, j, delta; | ||
986 | |||
987 | |||
988 | // | ||
989 | // fade through intermediate frames | ||
990 | // | ||
991 | for (i = 1; i <= NUMREDSHIFTS; i++) | ||
992 | { | ||
993 | workptr = redshifts[i - 1]; | ||
994 | baseptr = gamepal; | ||
995 | |||
996 | for (j = 0; j <= 255; j++) | ||
997 | { | ||
998 | delta = 256 - baseptr->r; | ||
999 | workptr->r = baseptr->r + delta * i / REDSTEPS; | ||
1000 | delta = -baseptr->g; | ||
1001 | workptr->g = baseptr->g + delta * i / REDSTEPS; | ||
1002 | delta = -baseptr->b; | ||
1003 | workptr->b = baseptr->b + delta * i / REDSTEPS; | ||
1004 | baseptr++; | ||
1005 | workptr++; | ||
1006 | } | ||
1007 | rb->yield(); | ||
1008 | } | ||
1009 | |||
1010 | for (i = 1; i <= NUMWHITESHIFTS; i++) | ||
1011 | { | ||
1012 | workptr = whiteshifts[i - 1]; | ||
1013 | baseptr = gamepal; | ||
1014 | |||
1015 | for (j = 0; j <= 255; j++) | ||
1016 | { | ||
1017 | delta = 256 - baseptr->r; | ||
1018 | workptr->r = baseptr->r + delta * i / WHITESTEPS; | ||
1019 | delta = 248 - baseptr->g; | ||
1020 | workptr->g = baseptr->g + delta * i / WHITESTEPS; | ||
1021 | delta = 0-baseptr->b; | ||
1022 | workptr->b = baseptr->b + delta * i / WHITESTEPS; | ||
1023 | baseptr++; | ||
1024 | workptr++; | ||
1025 | } | ||
1026 | rb->yield(); | ||
1027 | } | ||
1028 | } | ||
1029 | |||
1030 | |||
1031 | /* | ||
1032 | ===================== | ||
1033 | = | ||
1034 | = ClearPaletteShifts | ||
1035 | = | ||
1036 | ===================== | ||
1037 | */ | ||
1038 | |||
1039 | void ClearPaletteShifts (void) | ||
1040 | { | ||
1041 | bonuscount = damagecount = 0; | ||
1042 | palshifted = false; | ||
1043 | } | ||
1044 | |||
1045 | |||
1046 | /* | ||
1047 | ===================== | ||
1048 | = | ||
1049 | = StartBonusFlash | ||
1050 | = | ||
1051 | ===================== | ||
1052 | */ | ||
1053 | |||
1054 | void StartBonusFlash (void) | ||
1055 | { | ||
1056 | bonuscount = NUMWHITESHIFTS * WHITETICS; // white shift palette | ||
1057 | } | ||
1058 | |||
1059 | |||
1060 | /* | ||
1061 | ===================== | ||
1062 | = | ||
1063 | = StartDamageFlash | ||
1064 | = | ||
1065 | ===================== | ||
1066 | */ | ||
1067 | |||
1068 | void StartDamageFlash (int damage) | ||
1069 | { | ||
1070 | damagecount += damage; | ||
1071 | } | ||
1072 | |||
1073 | |||
1074 | /* | ||
1075 | ===================== | ||
1076 | = | ||
1077 | = UpdatePaletteShifts | ||
1078 | = | ||
1079 | ===================== | ||
1080 | */ | ||
1081 | |||
1082 | void UpdatePaletteShifts (void) | ||
1083 | { | ||
1084 | int red, white; | ||
1085 | |||
1086 | if (bonuscount) | ||
1087 | { | ||
1088 | white = bonuscount / WHITETICS + 1; | ||
1089 | if (white > NUMWHITESHIFTS) | ||
1090 | white = NUMWHITESHIFTS; | ||
1091 | bonuscount -= tics; | ||
1092 | if (bonuscount < 0) | ||
1093 | bonuscount = 0; | ||
1094 | } | ||
1095 | else | ||
1096 | white = 0; | ||
1097 | |||
1098 | |||
1099 | if (damagecount) | ||
1100 | { | ||
1101 | red = damagecount / 10 + 1; | ||
1102 | if (red > NUMREDSHIFTS) | ||
1103 | red = NUMREDSHIFTS; | ||
1104 | |||
1105 | damagecount -= tics; | ||
1106 | if (damagecount < 0) | ||
1107 | damagecount = 0; | ||
1108 | } | ||
1109 | else | ||
1110 | red = 0; | ||
1111 | |||
1112 | if (red) | ||
1113 | { | ||
1114 | VL_SetPalette (redshifts[red - 1], false); | ||
1115 | palshifted = true; | ||
1116 | } | ||
1117 | else if (white) | ||
1118 | { | ||
1119 | VL_SetPalette (whiteshifts[white - 1], false); | ||
1120 | palshifted = true; | ||
1121 | } | ||
1122 | else if (palshifted) | ||
1123 | { | ||
1124 | VL_SetPalette (gamepal, false); // back to normal | ||
1125 | palshifted = false; | ||
1126 | } | ||
1127 | } | ||
1128 | |||
1129 | |||
1130 | /* | ||
1131 | ===================== | ||
1132 | = | ||
1133 | = FinishPaletteShifts | ||
1134 | = | ||
1135 | = Resets palette to normal if needed | ||
1136 | = | ||
1137 | ===================== | ||
1138 | */ | ||
1139 | |||
1140 | void FinishPaletteShifts (void) | ||
1141 | { | ||
1142 | if (palshifted) | ||
1143 | { | ||
1144 | palshifted = 0; | ||
1145 | VL_SetPalette (gamepal, true); | ||
1146 | } | ||
1147 | } | ||
1148 | |||
1149 | |||
1150 | /* | ||
1151 | ============================================================================= | ||
1152 | |||
1153 | CORE PLAYLOOP | ||
1154 | |||
1155 | ============================================================================= | ||
1156 | */ | ||
1157 | |||
1158 | |||
1159 | /* | ||
1160 | ===================== | ||
1161 | = | ||
1162 | = DoActor | ||
1163 | = | ||
1164 | ===================== | ||
1165 | */ | ||
1166 | |||
1167 | void DoActor (objtype * ob) | ||
1168 | { | ||
1169 | void (*think) (objtype *); | ||
1170 | |||
1171 | if (!ob->active && !areabyplayer[ob->areanumber]) | ||
1172 | return; | ||
1173 | |||
1174 | if (!(ob->flags & (FL_NONMARK | FL_NEVERMARK))) | ||
1175 | actorat[ob->tilex][ob->tiley] = NULL; | ||
1176 | |||
1177 | // | ||
1178 | // non transitional object | ||
1179 | // | ||
1180 | |||
1181 | if (!ob->ticcount) | ||
1182 | { | ||
1183 | think = (void (*)(objtype *)) ob->state->think; | ||
1184 | if (think) | ||
1185 | { | ||
1186 | think (ob); | ||
1187 | if (!ob->state) | ||
1188 | { | ||
1189 | RemoveObj (ob); | ||
1190 | return; | ||
1191 | } | ||
1192 | } | ||
1193 | |||
1194 | if (ob->flags & FL_NEVERMARK) | ||
1195 | return; | ||
1196 | |||
1197 | if ((ob->flags & FL_NONMARK) && actorat[ob->tilex][ob->tiley]) | ||
1198 | return; | ||
1199 | |||
1200 | actorat[ob->tilex][ob->tiley] = ob; | ||
1201 | return; | ||
1202 | } | ||
1203 | |||
1204 | // | ||
1205 | // transitional object | ||
1206 | // | ||
1207 | ob->ticcount -= (short) tics; | ||
1208 | while (ob->ticcount <= 0) | ||
1209 | { | ||
1210 | think = (void (*)(objtype *)) ob->state->action; // end of state action | ||
1211 | if (think) | ||
1212 | { | ||
1213 | think (ob); | ||
1214 | if (!ob->state) | ||
1215 | { | ||
1216 | RemoveObj (ob); | ||
1217 | return; | ||
1218 | } | ||
1219 | } | ||
1220 | |||
1221 | ob->state = ob->state->next; | ||
1222 | |||
1223 | if (!ob->state) | ||
1224 | { | ||
1225 | RemoveObj (ob); | ||
1226 | return; | ||
1227 | } | ||
1228 | |||
1229 | if (!ob->state->tictime) | ||
1230 | { | ||
1231 | ob->ticcount = 0; | ||
1232 | goto think; | ||
1233 | } | ||
1234 | |||
1235 | ob->ticcount += ob->state->tictime; | ||
1236 | } | ||
1237 | |||
1238 | think: | ||
1239 | // | ||
1240 | // think | ||
1241 | // | ||
1242 | think = (void (*)(objtype *)) ob->state->think; | ||
1243 | if (think) | ||
1244 | { | ||
1245 | think (ob); | ||
1246 | if (!ob->state) | ||
1247 | { | ||
1248 | RemoveObj (ob); | ||
1249 | return; | ||
1250 | } | ||
1251 | } | ||
1252 | |||
1253 | if (ob->flags & FL_NEVERMARK) | ||
1254 | return; | ||
1255 | |||
1256 | if ((ob->flags & FL_NONMARK) && actorat[ob->tilex][ob->tiley]) | ||
1257 | return; | ||
1258 | |||
1259 | actorat[ob->tilex][ob->tiley] = ob; | ||
1260 | } | ||
1261 | |||
1262 | //========================================================================== | ||
1263 | |||
1264 | |||
1265 | /* | ||
1266 | =================== | ||
1267 | = | ||
1268 | = PlayLoop | ||
1269 | = | ||
1270 | =================== | ||
1271 | */ | ||
1272 | int32_t funnyticount; | ||
1273 | |||
1274 | |||
1275 | void PlayLoop (void) | ||
1276 | { | ||
1277 | #if defined(USE_FEATUREFLAGS) && defined(USE_CLOUDSKY) | ||
1278 | if(GetFeatureFlags() & FF_CLOUDSKY) | ||
1279 | InitSky(); | ||
1280 | #endif | ||
1281 | |||
1282 | #ifdef USE_SHADING | ||
1283 | InitLevelShadeTable(); | ||
1284 | #endif | ||
1285 | |||
1286 | playstate = ex_stillplaying; | ||
1287 | lasttimecount = GetTimeCount(); | ||
1288 | frameon = 0; | ||
1289 | anglefrac = 0; | ||
1290 | facecount = 0; | ||
1291 | funnyticount = 0; | ||
1292 | memset (buttonstate, 0, sizeof (buttonstate)); | ||
1293 | ClearPaletteShifts (); | ||
1294 | |||
1295 | if (MousePresent && IN_IsInputGrabbed()) | ||
1296 | IN_CenterMouse(); // Clear accumulated mouse movement | ||
1297 | |||
1298 | if (demoplayback) | ||
1299 | IN_StartAck (); | ||
1300 | |||
1301 | do | ||
1302 | { | ||
1303 | PollControls (); | ||
1304 | |||
1305 | // | ||
1306 | // actor thinking | ||
1307 | // | ||
1308 | madenoise = false; | ||
1309 | |||
1310 | MoveDoors (); | ||
1311 | MovePWalls (); | ||
1312 | |||
1313 | for (obj = player; obj; obj = obj->next) | ||
1314 | DoActor (obj); | ||
1315 | |||
1316 | UpdatePaletteShifts (); | ||
1317 | |||
1318 | ThreeDRefresh (); | ||
1319 | |||
1320 | // | ||
1321 | // MAKE FUNNY FACE IF BJ DOESN'T MOVE FOR AWHILE | ||
1322 | // | ||
1323 | #ifdef SPEAR | ||
1324 | funnyticount += tics; | ||
1325 | if (funnyticount > 30l * 70) | ||
1326 | { | ||
1327 | funnyticount = 0; | ||
1328 | if(viewsize != 21) | ||
1329 | StatusDrawFace(BJWAITING1PIC + (US_RndT () & 1)); | ||
1330 | facecount = 0; | ||
1331 | } | ||
1332 | #endif | ||
1333 | |||
1334 | gamestate.TimeCount += tics; | ||
1335 | |||
1336 | UpdateSoundLoc (); // JAB | ||
1337 | if (screenfaded) | ||
1338 | VW_FadeIn (); | ||
1339 | |||
1340 | CheckKeys (); | ||
1341 | |||
1342 | // | ||
1343 | // debug aids | ||
1344 | // | ||
1345 | if (singlestep) | ||
1346 | { | ||
1347 | VW_WaitVBL (singlestep); | ||
1348 | lasttimecount = GetTimeCount(); | ||
1349 | } | ||
1350 | if (extravbls) | ||
1351 | VW_WaitVBL (extravbls); | ||
1352 | |||
1353 | if (demoplayback) | ||
1354 | { | ||
1355 | if (IN_CheckAck ()) | ||
1356 | { | ||
1357 | IN_ClearKeysDown (); | ||
1358 | playstate = ex_abort; | ||
1359 | } | ||
1360 | } | ||
1361 | } | ||
1362 | while (!playstate && !startgame); | ||
1363 | |||
1364 | if (playstate != ex_died) | ||
1365 | FinishPaletteShifts (); | ||
1366 | } | ||