1 /***************************************************************************
2 * WITCHAVEN.C - main game code for Witchaven game *
3 * *
4 ***************************************************************************/
5
6 #define WHAVEN
7 #define GAME
8 #define SVGA
9
10 #include "witchaven.h"
11
12 #include "keyboard.h"
13 #include "control.h"
14 #include "config.h"
15 #include "compat.h"
16 #include "baselayer.h"
17 #include "renderlayer.h"
18 #include "build.h"
19 #include "common.h"
20 #include "objects.h"
21 #include "player.h"
22 #include "effects.h"
23 #include "menu.h"
24 #include "input.h"
25 #include "animation.h"
26 #include "tags.h"
27 #include "network.h"
28 #include "sound.h"
29 #include "grpscan.h"
30 #include "osdcmds.h"
31 #include "common_game.h"
32
33 #ifdef _WIN32
34 # include "winbits.h"
35 #endif /* _WIN32 */
36
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40 extern const char* s_buildRev;
41 extern const char* s_buildTimestamp;
42 #ifdef __cplusplus
43 }
44 #endif
45
46 const char* AppProperName = APPNAME;
47 const char* AppTechnicalName = APPBASENAME;
48
49 static char g_rootDir[BMAX_PATH];
50
51 int mouseaiming, aimmode, mouseflip;
52 int runkey_mode, auto_run;
53
54
55 #if defined GEKKO
56 # define FPS_YOFFSET 16
57 #else
58 # define FPS_YOFFSET 0
59 #endif
60
61
M32RunScript(const char * s)62 void M32RunScript(const char* s) { UNREFERENCED_PARAMETER(s); }
app_crashhandler(void)63 void app_crashhandler(void)
64 {
65 shutdown();
66 }
67
68 void InstallEngine();
69
70 int32_t synctics;
71 int32_t globhiz, globloz, globhihit, globlohit;
72
73 char option[NUMOPTIONS] = { 0,0,0,0,0,0,1,0 };
74
75 // TODO / FIXME / CHECKME - old Build visibility variable. What happened it?
76 int32_t visibility;
77
78 int svga = 0; // REVERT / CHECKME - was originally 0
79 int delaycnt, engineinitflag, timerinitflag, videoinitflag;
80 int netgame = 0;
81 int gametype;
82 int godmode = 0; // WH2
83
84 char boardname[BMAX_PATH];
85 char tempboard[BMAX_PATH];
86 char loadgamename[BMAX_PATH];
87
88 int32_t* animateptr[MAXANIMATES];
89 int32_t animategoal[MAXANIMATES];
90 int32_t animatevel[MAXANIMATES];
91 int32_t animatecnt = 0;
92
93 // WH2 variables
94 int treasurescnt = 0;
95 int treasuresfound = 0;
96 int killcnt = 0;
97 int kills = 0;
98 int expgained = 0;
99 int bonus = 0;
100 int overtheshoulder;
101 static char detailmode = 0;
102 static char ready2send = 0;
103 int32_t screentilt = 0;
104 extern int32_t cachecount, transarea;
105 extern char chainstat;
106
107
108 uint32_t flags32[32]={
109 0x80000000,0x40000000,0x20000000,0x10000000,
110 0x08000000,0x04000000,0x02000000,0x01000000,
111 0x00800000,0x00400000,0x00200000,0x00100000,
112 0x00080000,0x00040000,0x00020000,0x00010000,
113 0x00008000,0x00004000,0x00002000,0x00001000,
114 0x00000800,0x00000400,0x00000200,0x00000100,
115 0x00000080,0x00000040,0x00000020,0x00000010,
116 0x00000008,0x00000004,0x00000002,0x00000001
117 };
118
119 extern short cddrive;
120
121 int32_t followx, followy;
122
123 int ratcnt = 0;
124 int gameactivated = 0;
125 int escapetomenu = 0;
126
127 int32_t difficulty = 2;
128 int32_t goreon = 1;
129
130 int32_t totsynctics, frames;
131
132 extern bool followmode;
133 extern int loadedgame;
134 extern char tempbuf[50];
135 extern int musiclevel;
136 extern int digilevel;
137
138 struct Delayitem delayitem[MAXSECTORS];
139
140 int32_t brightness = 0;
141 int32_t gbrightness = 0;
142
143 int swingcnt;
144 short spikecnt;
145 short spikesector[64];
146
147 short goblinspritelist[100];
148 short goblinwarcnt;
149
150 short lavadrylandsector[32];
151 short lavadrylandcnt;
152
153 short xpanningsectorlist[64], xpanningsectorcnt;
154 short ypanningwalllist[64], ypanningwallcnt;
155 short floorpanninglist[64], floorpanningcnt;
156 short skypanlist[64], skypancnt;
157
158 short crushsectorlist[32], crushsectorcnt;
159 short crushsectoranim[32], crushsectordone[32];
160
161 short revolvesector[16], revolveang[16], revolveclip[16], revolvecnt;
162 int revolvex[16][16], revolvey[16][16];
163 int revolvepivotx[16], revolvepivoty[16];
164
165 short dragsectorlist[16], dragxdir[16], dragydir[16], dragsectorcnt;
166 int dragx1[16], dragy1[16], dragx2[16], dragy2[16], dragfloorz[16];
167
168 short warpsectorlist[16], warpsectorcnt;
169
170 short bobbingsectorlist[16], bobbingsectorcnt;
171
172 //JSA ends
173
174 int justteleported = 0;
175
176 short ironbarsector[16],ironbarscnt;
177 int ironbarsgoal1[16],ironbarsgoal2[16];
178 short ironbarsdone[16], ironbarsanim[16];
179 int ironbarsgoal[16];
180
181 extern int mapon;
182 int mapflag;
183
184 extern char option2[];
185 extern short mousekeys[];
186
187 static int32_t nonsharedtimer;
188
189 int adjusthp(int hp);
190 void playloop();
191 void readpalettetable();
192 void drawoverheadmap(Player *plr);
193
194 int32_t g_commandSetup = 0;
195 int32_t g_noSetup = 0;
196 int32_t g_noAutoLoad = 0;
197
198 //////////
199
200 enum gametokens
201 {
202 T_INCLUDE = 0,
203 T_INTERFACE = 0,
204 T_LOADGRP = 1,
205 T_MODE = 1,
206 T_CACHESIZE = 2,
207 T_ALLOW = 2,
208 T_NOAUTOLOAD,
209 T_INCLUDEDEFAULT,
210 T_MUSIC,
211 T_SOUND,
212 T_FILE,
213 T_CUTSCENE,
214 T_ANIMSOUNDS,
215 T_NOFLOORPALRANGE,
216 T_ID,
217 T_MINPITCH,
218 T_MAXPITCH,
219 T_PRIORITY,
220 T_TYPE,
221 T_DISTANCE,
222 T_VOLUME,
223 T_DELAY,
224 T_RENAMEFILE,
225 T_GLOBALGAMEFLAGS,
226 T_ASPECT,
227 T_FORCEFILTER,
228 T_FORCENOFILTER,
229 T_TEXTUREFILTER,
230 T_NEWGAMECHOICES,
231 T_CHOICE,
232 T_NAME,
233 T_LOCKED,
234 T_HIDDEN,
235 T_USERCONTENT,
236 };
237
238 int witchaven_globalflags;
239
240 static int parsedefinitions_game(scriptfile*, int);
241
parsedefinitions_game_include(const char * fileName,scriptfile * pScript,const char * cmdtokptr,int const firstPass)242 static void parsedefinitions_game_include(const char* fileName, scriptfile* pScript, const char* cmdtokptr, int const firstPass)
243 {
244 scriptfile* included = scriptfile_fromfile(fileName);
245
246 if (!included)
247 {
248 if (!Bstrcasecmp(cmdtokptr, "null") || pScript == NULL) // this is a bit overboard to prevent unused parameter warnings
249 {
250 // initprintf("Warning: Failed including %s as module\n", fn);
251 }
252 /*
253 else
254 {
255 initprintf("Warning: Failed including %s on line %s:%d\n",
256 fn, script->filename,scriptfile_getlinum(script,cmdtokptr));
257 }
258 */
259 }
260 else
261 {
262 parsedefinitions_game(included, firstPass);
263 scriptfile_close(included);
264 }
265 }
266
parsedefinitions_game(scriptfile * pScript,int firstPass)267 static int parsedefinitions_game(scriptfile* pScript, int firstPass)
268 {
269 int token;
270 char* pToken;
271
272 static const tokenlist tokens[] =
273 {
274 { "include", T_INCLUDE },
275 { "#include", T_INCLUDE },
276 { "includedefault", T_INCLUDEDEFAULT },
277 { "#includedefault", T_INCLUDEDEFAULT },
278 { "loadgrp", T_LOADGRP },
279 { "cachesize", T_CACHESIZE },
280 { "noautoload", T_NOAUTOLOAD },
281 { "renamefile", T_RENAMEFILE },
282 { "globalgameflags", T_GLOBALGAMEFLAGS },
283 };
284
285 do
286 {
287 token = getatoken(pScript, tokens, ARRAY_SIZE(tokens));
288 pToken = pScript->ltextptr;
289
290 switch (token)
291 {
292 case T_LOADGRP:
293 {
294 char* fileName;
295
296 pathsearchmode = 1;
297 if (!scriptfile_getstring(pScript, &fileName) && firstPass)
298 {
299 if (initgroupfile(fileName) == -1)
300 initprintf("Could not find file \"%s\".\n", fileName);
301 else
302 {
303 initprintf("Using file \"%s\" as game data.\n", fileName);
304 if (!g_noAutoLoad && !gSetup.noautoload)
305 G_DoAutoload(fileName);
306 }
307 }
308
309 pathsearchmode = 0;
310 }
311 break;
312 case T_CACHESIZE:
313 {
314 int32_t cacheSize;
315
316 if (scriptfile_getnumber(pScript, &cacheSize) || !firstPass)
317 break;
318
319 if (cacheSize > 0)
320 MAXCACHE1DSIZE = cacheSize << 10;
321 }
322 break;
323 case T_INCLUDE:
324 {
325 char* fileName;
326
327 if (!scriptfile_getstring(pScript, &fileName))
328 parsedefinitions_game_include(fileName, pScript, pToken, firstPass);
329
330 break;
331 }
332 case T_INCLUDEDEFAULT:
333 {
334 parsedefinitions_game_include(G_DefaultDefFile(), pScript, pToken, firstPass);
335 break;
336 }
337 case T_NOAUTOLOAD:
338 if (firstPass)
339 g_noAutoLoad = 1;
340 break;
341 case T_GLOBALGAMEFLAGS: scriptfile_getnumber(pScript, &witchaven_globalflags); break;
342 case T_EOF: return 0;
343 default: break;
344 }
345 } while (1);
346
347 return 0;
348 }
349
loaddefinitions_game(const char * fileName,int32_t firstPass)350 int loaddefinitions_game(const char* fileName, int32_t firstPass)
351 {
352 scriptfile* pScript = scriptfile_fromfile(fileName);
353
354 if (pScript)
355 parsedefinitions_game(pScript, firstPass);
356
357 for (char const* m : g_defModules)
358 parsedefinitions_game_include(m, NULL, "null", firstPass);
359
360 if (pScript)
361 scriptfile_close(pScript);
362
363 scriptfile_clearsymbols();
364
365 return 0;
366 }
367
368 #define FPS_COLOR(x) ((x) ? COLOR_RED : COLOR_WHITE)
369
370 #define COLOR_RED redcol
371 #define COLOR_WHITE whitecol
372
373 #define LOW_FPS ((videoGetRenderMode() == REND_CLASSIC) ? 35 : 50)
374 #define SLOW_FRAME_TIME 20
375
G_PrintFPS(void)376 static void G_PrintFPS(void)
377 {
378 static char tempbuf[256];
379 static int32_t frameCount;
380 static double cumulativeFrameDelay;
381 static double lastFrameTime;
382 static float lastFPS; // , minFPS = std::numeric_limits<float>::max(), maxFPS;
383 //static double minGameUpdate = std::numeric_limits<double>::max(), maxGameUpdate;
384
385 double frameTime = timerGetHiTicks();
386 double frameDelay = frameTime - lastFrameTime;
387 cumulativeFrameDelay += frameDelay;
388
389 if (frameDelay >= 0)
390 {
391 int32_t x = (xdim <= 640);
392
393 if (r_showfps)
394 {
395 int32_t chars = Bsprintf(tempbuf, "%.1f ms, %5.1f fps", frameDelay, lastFPS);
396
397 printext256(windowxy2.x - (chars << (3 - x)) + 1, windowxy1.y + 2 + FPS_YOFFSET, blackcol, -1, tempbuf, x);
398 printext256(windowxy2.x - (chars << (3 - x)), windowxy1.y + 1 + FPS_YOFFSET,
399 FPS_COLOR(lastFPS < LOW_FPS), -1, tempbuf, x);
400 }
401
402 if (cumulativeFrameDelay >= 1000.0)
403 {
404 lastFPS = 1000.f * frameCount / cumulativeFrameDelay;
405 // g_frameRate = Blrintf(lastFPS);
406 frameCount = 0;
407 cumulativeFrameDelay = 0.0;
408 }
409 frameCount++;
410 }
411 lastFrameTime = frameTime;
412 }
413
faketimerhandler(void)414 void faketimerhandler(void)
415 {
416 return;
417 }
418
419 //
420 // basic text functions
421 //
422
cls80x25(int top,int mid,int bot)423 void cls80x25(int top,int mid,int bot)
424 {
425 }
426
tprintf(int x,int y,const char * fmt,...)427 void tprintf(int x, int y, const char *fmt,...)
428 {
429 }
430
rp_delay(int goal)431 void rp_delay(int goal)
432 {
433 bool bExit = false;
434
435 int32_t dagoal = (int)totalclock+goal;
436
437 while (!bExit)
438 {
439 handleevents();
440 if (totalclock == dagoal) {
441 bExit = true;
442 }
443 }
444 }
445
446 //
447 // game code
448 //
449
showadditionalinfo()450 void showadditionalinfo()
451 {
452 printf("average synctics = %ld\n", totsynctics / frames);
453 }
454
455 int crashflag;
456
shutdown()457 void shutdown()
458 {
459 CONFIG_WriteSetup(0);
460
461 #if 0
462 int fil = open("pref.dat", O_BINARY|O_TRUNC|O_CREAT|O_WRONLY, S_IREAD | S_IWRITE);
463 if (fil != NULL)
464 {
465 write(fil, &goreon, 2);
466 write(fil, &brightness, 2);
467 write(fil, &gbrightness, 2);
468 write(fil, &digilevel, 2);
469 write(fil, &musiclevel, 2);
470 write(fil, &difficulty, 2);
471 close(fil);
472 }
473 #endif
474
475 SND_Shutdown();
476
477 //TODO netshutdown();
478
479 // if (engineinitflag) {
480 engineUnInit();
481 // }
482
483 if (SoundMode) {
484 //TODO SND_UnDoBuffers();
485 }
486
487 if (videoinitflag) {
488 // TODO setvmode(oldvmode);
489 }
490
491 //CHECKME uninitkeys();
492 uninitgroupfile();
493
494 if (crashflag) {
495 return;
496 }
497
498 exit(EXIT_SUCCESS);
499 }
500
crash(const char * fmt)501 void crash(const char* fmt)
502 {
503 crashflag = 1;
504 shutdown();
505
506 printf("\n%s\n", fmt);
507 printf("\n\n\n\n\n\n\n\n");
508 }
509
doanimations(int32_t numtics)510 void doanimations(int32_t numtics)
511 {
512 for (int i = animatecnt - 1; i >= 0; i--)
513 {
514 int animval = *animateptr[i];
515 if (animval < animategoal[i])
516 {
517 animval += (numtics * animatevel[i]);
518 if (animval > animategoal[i]) {
519 animval = animategoal[i];
520 }
521 }
522 if (animval > animategoal[i])
523 {
524 animval -= (numtics * animatevel[i]);
525 if (animval < animategoal[i]) {
526 animval = animategoal[i];
527 }
528 }
529 *animateptr[i] = animval;
530 if (animval == animategoal[i])
531 {
532 animatecnt--;
533 animateptr[i] = animateptr[animatecnt];
534 animategoal[i] = animategoal[animatecnt];
535 animatevel[i] = animatevel[animatecnt];
536 }
537 }
538 }
539
getanimationgoal(int32_t * animptr)540 int32_t getanimationgoal(int32_t *animptr)
541 {
542 int j = -1;
543 for (int i = 0; i < animatecnt; i++)
544 {
545 if (animptr == animateptr[i])
546 {
547 j = i;
548 break;
549 }
550 }
551
552 return j;
553 }
554
setanimation(int32_t * animptr,int32_t thegoal,int32_t thevel)555 int32_t setanimation(int32_t*animptr, int32_t thegoal, int32_t thevel)
556 {
557 if (animatecnt >= MAXANIMATES-1) {
558 return(-1);
559 }
560
561 int j = animatecnt;
562
563 for (int i = 0; i < animatecnt; i++)
564 {
565 if (animptr == animateptr[i])
566 {
567 j = i;
568 break;
569 }
570 }
571
572 animateptr[j] = animptr;
573 animategoal[j] = thegoal;
574 animatevel[j] = thevel;
575
576 if (j == animatecnt) {
577 animatecnt++;
578 }
579
580 return animatecnt - 1;
581 }
582
setdelayfunc(void (* func)(int),int item,int delay)583 void setdelayfunc(void (*func)(int),int item,int delay)
584 {
585 for (int i = 0; i < delaycnt; i++)
586 {
587 if (delayitem[i].func == func && delayitem[i].item == item)
588 {
589 if (delay == 0) {
590 delayitem[i].func = NULL;
591 }
592 delayitem[i].timer = delay;
593 return;
594 }
595 }
596
597 if (delay > 0)
598 {
599 delayitem[delaycnt].func = func;
600 delayitem[delaycnt].item = item;
601 delayitem[delaycnt].timer = delay;
602 delaycnt++;
603 }
604 }
605
dodelayitems(int tics)606 void dodelayitems(int tics)
607 {
608 int cnt = delaycnt;
609
610 for (int i = 0; i < cnt; i++)
611 {
612 if (delayitem[i].func == NULL)
613 {
614 int j = delaycnt - 1;
615 memmove(&delayitem[i], &delayitem[j], sizeof(Delayitem));
616 delaycnt = j;
617 }
618
619 if (delayitem[i].timer > 0)
620 {
621 if ((delayitem[i].timer -= tics) <= 0)
622 {
623 delayitem[i].timer = 0;
624 (*delayitem[i].func)(delayitem[i].item);
625 delayitem[i].func = NULL;
626 }
627 }
628 }
629 }
630
setup3dscreen()631 void setup3dscreen()
632 {
633 int32_t dax, day, dax2, day2;
634
635 Player *plr = &player[pyrn];
636
637 videoSetGameMode(gSetup.fullscreen, gSetup.xdim, gSetup.ydim, gSetup.bpp, 0);
638
639 videoinitflag = 1;
640
641 #if 0 // TODO
642 switch (option[0])
643 {
644 case 1:
645 {
646 if (svga == 0)
647 {
648 dax = 160 - (plr->screensize >> 1);
649 dax2 = dax + plr->screensize - 1;
650 day = 84 - (((plr->screensize * 168) / 320) >> 1);
651 day2 = STATUSSCREEN - 1;
652 videoSetViewableArea(dax, day, dax2, day2);
653 }
654 else {
655 videoSetViewableArea(0, 0, vesares[option[6] & 15][0] - 1, vesares[option[6] & 15][1] - 1);
656 }
657 break;
658 }
659 default:
660 videoSetViewableArea(0, 0, 319, 199);
661 break;
662 }
663
664 if (svga == 0)
665 {
666 if(plr->screensize <= 320)
667 permanentwritesprite(0,0,BACKGROUND,0,0,0,319,199,0);
668 if(plr->screensize <= 320)
669 permanentwritesprite(0,200-46,NEWSTATUSBAR,0,0,0,319,199,0);
670 }
671 else if(svga == 1)
672 {
673 permanentwritesprite(0,0,SVGAMENU,0,0,0,639,239,0);
674 permanentwritesprite(0,240,SVGAMENU2,0,0,240,639,479,0);
675 }
676 #endif
677 }
678
setupboard(char * fname)679 void setupboard(char* fname)
680 {
681 int endwall, i, j, k, startwall;
682 int32_t dax, day;
683 short treesize;
684 int32_t dasector;
685 int32_t dax2, day2;
686 int16_t daang;
687
688 Player* plr = &player[pyrn];
689 randomseed = 17;
690
691 vec3_t startPos;
692 int status = engineLoadBoard(fname, 0, &startPos, &daang, &plr->sector);
693 if (status == -2)
694 status = engineLoadBoardV5V6(fname, 0, &startPos, &daang, &plr->sector);
695
696 if (status == -1) {
697 crash("Board not found");
698 }
699
700 plr->x = startPos.x;
701 plr->y = startPos.y;
702 plr->z = startPos.z;
703
704 plr->ang = daang;
705
706 #ifdef YAX_ENABLE
707 yax_update(1);
708 #endif
709
710 psky_t* pSky = tileSetupSky(0);
711
712 pSky->tileofs[0] = 0;
713 pSky->tileofs[1] = 0;
714 pSky->tileofs[2] = 0;
715 pSky->tileofs[3] = 0;
716 pSky->yoffs = 256;
717 pSky->lognumtiles = 2;
718 pSky->horizfrac = 65536;
719 pSky->yscale = 65536;
720 parallaxtype = 2;
721 g_visibility = 2048;
722
723 // TODO precache();
724
725 ratcnt = 0;
726 swingcnt = 0;
727 xpanningsectorcnt = 0;
728 ypanningwallcnt = 0;
729 floorpanningcnt = 0;
730 crushsectorcnt = 0;
731 revolvecnt = 0;
732 warpsectorcnt = 0;
733 dragsectorcnt = 0;
734 ironbarscnt = 0;
735 spikecnt = 0;
736 bobbingsectorcnt = 0;
737 goblinwarcnt = 0;
738 lavadrylandcnt = 0;
739
740 for (i = 0; i < MAXSPRITES; i++) // setup sector effect options
741 {
742 if (sprite[i].picnum == FRED && sprite[i].pal == 1) {
743 deletesprite(i);
744 }
745
746 if (sprite[i].picnum == RAT) {
747 ratcnt++;
748 if (ratcnt > 10) {
749 deletesprite(i);
750 }
751 }
752
753 if (sprite[i].picnum == SPAWN) {
754 deletesprite(i);
755 }
756
757 if (sprite[i].picnum == TORCH) {
758 sprite[i].cstat &= ~3;
759 changespritestat(i, TORCHLIGHT);
760 }
761
762 if (sprite[i].picnum == STANDINTORCH ||
763 sprite[i].picnum == BOWLOFFIRE) {
764 changespritestat(i, TORCHLIGHT);
765 }
766
767 if (sprite[i].picnum == GLOW) {
768 changespritestat(i, GLOWLIGHT);
769 }
770
771 if (sprite[i].picnum == SNDEFFECT) {
772 sector[sprite[i].sectnum].extra = sprite[i].lotag;
773 deletesprite(i);
774 }
775
776 if (sprite[i].picnum == SNDLOOP) { //loop on
777 sector[sprite[i].sectnum].extra = (32768 | (sprite[i].lotag << 1) | 1);
778 deletesprite(i);
779 }
780
781 if (sprite[i].picnum == SNDLOOPOFF) { //loop off
782 sector[sprite[i].sectnum].extra = (32768 | (sprite[i].lotag << 1));
783 deletesprite(i);
784 }
785
786 if (sprite[i].lotag == 80)
787 {
788 ironbarsector[ironbarscnt] = sprite[i].sectnum;
789 ironbarsdone[ironbarscnt] = 0;
790 ironbarsanim[ironbarscnt] = i;
791 ironbarsgoal[ironbarscnt] = 0;
792 ironbarscnt++;
793 }
794
795 if (sprite[i].statnum < MAXSTATUS)
796 {
797 switch (sprite[i].picnum)
798 {
799 case GRONHAL:
800 sprite[i].xrepeat = 30;
801 sprite[i].yrepeat = 30;
802 sprite[i].clipdist = 64;
803 changespritestat(i, FACE);
804 sprite[i].hitag = adjusthp(300);
805 sprite[i].lotag = 100;
806 sprite[i].cstat |= 0x101;
807 sprite[i].extra = 4;
808 break;
809 case GRONMU:
810 sprite[i].xrepeat = 30;
811 sprite[i].yrepeat = 30;
812 sprite[i].clipdist = 64;
813 changespritestat(i, FACE);
814 sprite[i].hitag = adjusthp(300);
815 sprite[i].lotag = 100;
816 sprite[i].cstat |= 0x101;
817 sprite[i].extra = 2;
818 break;
819 case GRONSW:
820 sprite[i].xrepeat = 30;
821 sprite[i].yrepeat = 30;
822 sprite[i].clipdist = 64;
823 changespritestat(i, FACE);
824 sprite[i].hitag = adjusthp(300);
825 sprite[i].lotag = 100;
826 sprite[i].cstat |= 0x101;
827 sprite[i].extra = 0;
828 break;
829 case RAT:
830 sprite[i].xrepeat = 32;
831 sprite[i].yrepeat = 32;
832 sprite[i].shade = 12;
833 sprite[i].pal = 5;
834 changespritestat(i, FACE);
835 sprite[i].hitag = 10;
836 sprite[i].lotag = 100;
837 sprite[i].cstat = 0x101;
838 break;
839 case FISH:
840 sprite[i].clipdist = 32;
841 changespritestat(i, FACE);
842 sprite[i].hitag = 10;
843 sprite[i].lotag = 100;
844 sprite[i].cstat |= 0x101;
845 break;
846 case WILLOW:
847 sprite[i].xrepeat = 32;
848 sprite[i].yrepeat = 32;
849 sprite[i].clipdist = 64;
850 changespritestat(i, FACE);
851 sprite[i].hitag = adjusthp(400);
852 sprite[i].lotag = 100;
853 sprite[i].cstat |= 0x101;
854 break;
855 case DRAGON:
856 sprite[i].xrepeat = 54;
857 sprite[i].yrepeat = 54;
858 sprite[i].clipdist = 128;
859 changespritestat(i, FACE);
860 sprite[i].hitag = adjusthp(900);
861 sprite[i].lotag = 100;
862 sprite[i].cstat |= 0x101;
863 break;
864 case DEVIL:
865 case DEVILSTAND:
866 sprite[i].xrepeat = 36;
867 sprite[i].yrepeat = 36;
868 sprite[i].clipdist = 64;
869 changespritestat(i, FACE);
870 if (sprite[i].pal == 2)
871 sprite[i].hitag = adjusthp(60);
872 else
873 sprite[i].hitag = adjusthp(50);
874 sprite[i].lotag = 100;
875 sprite[i].cstat |= 0x101;
876 break;
877 case HANGMAN + 1:
878 sprite[i].xrepeat = 28;
879 sprite[i].yrepeat = 28;
880 break;
881 case HANGMAN:
882 sprite[i].xrepeat = 28;
883 sprite[i].yrepeat = 28;
884 sprite[i].clipdist = 64;
885 changespritestat(i, STAND);
886 sprite[i].hitag = adjusthp(30);
887 sprite[i].lotag = 100;
888 sprite[i].cstat |= 0x101;
889 break;
890 case SKELETON:
891 sprite[i].xrepeat = 24;
892 sprite[i].yrepeat = 24;
893 sprite[i].clipdist = 64;
894 changespritestat(i, FACE);
895 sprite[i].hitag = adjusthp(30);
896 sprite[i].lotag = 100;
897 sprite[i].cstat |= 0x101;
898 break;
899 case GOBLINDEAD:
900 sprite[i].xrepeat = 36;
901 sprite[i].yrepeat = 36;
902 break;
903 case GOBLIN:
904 case GOBLINSTAND:
905 if (sprite[i].hitag >= 90 && sprite[i].hitag <= 99)
906 {
907 if (sprite[i].pal == 0) {
908 sprite[i].xrepeat = 36;
909 sprite[i].yrepeat = 36;
910 }
911 else {
912 sprite[i].xrepeat = 30;
913 sprite[i].yrepeat = 36;
914 }
915 sprite[i].extra = 0;
916 sprite[i].owner = 0;
917 sprite[i].lotag = 100;
918 sprite[i].cstat |= 0x101;
919 sprite[i].clipdist = 64;
920 goblinspritelist[goblinwarcnt] = i;
921 goblinwarcnt++;
922 }
923 else
924 {
925 sprite[i].xrepeat = 36;
926 sprite[i].yrepeat = 36;
927 changespritestat(i, FACE);
928 if (sprite[i].pal == 5)
929 sprite[i].hitag = adjusthp(35);
930 else if (sprite[i].pal == 4)
931 sprite[i].hitag = adjusthp(25);
932 else
933 sprite[i].hitag = adjusthp(15);
934 sprite[i].lotag = 100;
935 sprite[i].cstat |= 0x101;
936 if (rand() % 100 > 50)
937 sprite[i].extra = 1;
938 sprite[i].clipdist = 64;
939 }
940 break;
941 case GOBLINCHILL:
942 sprite[i].xrepeat = 36;
943 sprite[i].yrepeat = 36;
944 changespritestat(i, STAND);
945 sprite[i].hitag = adjusthp(15);
946 sprite[i].lotag = 30;
947 sprite[i].cstat |= 0x101;
948 if (rand() % 100 > 50)
949 sprite[i].extra = 1;
950 sprite[i].clipdist = 64;
951 break;
952 case FATWITCH:
953 sprite[i].clipdist = 64;
954 sprite[i].xrepeat = 32;
955 sprite[i].yrepeat = 32;
956 changespritestat(i, FACE);
957 if (sprite[i].pal == 7)
958 sprite[i].hitag = adjusthp(290);
959 else
960 sprite[i].hitag = adjusthp(280);
961 sprite[i].lotag = 100;
962 sprite[i].cstat |= 0x101;
963 if (rand() % 100 > 50)
964 sprite[i].extra = 1;
965 break;
966 case SKULLY:
967 sprite[i].clipdist = 64;
968 sprite[i].xrepeat = 32;
969 sprite[i].yrepeat = 32;
970 changespritestat(i, FACE);
971 sprite[i].hitag = adjusthp(300);
972 sprite[i].lotag = 100;
973 sprite[i].cstat |= 0x101;
974 if (rand() % 100 > 50)
975 sprite[i].extra = 1;
976 break;
977 case MINOTAUR:
978 sprite[i].clipdist = 64;
979 changespritestat(i, FACE);
980 sprite[i].hitag = adjusthp(100);
981 sprite[i].lotag = 100;
982 sprite[i].cstat |= 0x101;
983 if (rand() % 100 > 50)
984 sprite[i].extra = 1;
985 break;
986 case FRED:
987 case FREDSTAND:
988 if (sprite[i].pal == 1)
989 break;
990 sprite[i].xrepeat = 48;
991 sprite[i].yrepeat = 48;
992 changespritestat(i, FACE);
993 sprite[i].hitag = adjusthp(40);
994 sprite[i].lotag = 100;
995 sprite[i].cstat |= 0x101;
996 sprite[i].clipdist = 64;
997 if (rand() % 100 > 50)
998 sprite[i].extra = 1;
999 break;
1000 case KOBOLD:
1001 // gave kobold x2 hp
1002 sprite[i].clipdist = 64;
1003 changespritestat(i, FACE);
1004 if (sprite[i].pal == 8)
1005 sprite[i].hitag = adjusthp(40);
1006 else if (sprite[i].pal == 7)
1007 sprite[i].hitag = adjusthp(60);
1008 else
1009 sprite[i].hitag = adjusthp(20);
1010 sprite[i].lotag = 100;
1011 sprite[i].xrepeat = sprite[i].yrepeat = 54;
1012 sprite[i].cstat |= 0x101;
1013 break;
1014 case SPIDER:
1015 sprite[i].xrepeat = 24;
1016 sprite[i].yrepeat = 18;
1017 sprite[i].clipdist = 64;
1018 changespritestat(i, FACE);
1019 sprite[i].hitag = adjusthp(5);
1020 sprite[i].lotag = 100;
1021 sprite[i].cstat |= 0x101;
1022 break;
1023 case GUARDIAN:
1024 sprite[i].clipdist = 64;
1025 changespritestat(i, FACE);
1026 sprite[i].hitag = adjusthp(200);
1027 sprite[i].lotag = 100;
1028 sprite[i].xrepeat = sprite[i].yrepeat = 32;
1029 sprite[i].cstat |= 0x101;
1030 break;
1031 case JUDYSIT:
1032 changespritestat(i, WITCHSIT);
1033 if (mapon > 24)
1034 sprite[i].hitag = adjusthp(700);
1035 else
1036 sprite[i].hitag = adjusthp(500);
1037 sprite[i].lotag = 100;
1038 sprite[i].xrepeat = sprite[i].yrepeat = 32;
1039 sprite[i].cstat |= 0x101;
1040 sprite[i].extra = 1200;
1041 break;
1042 case JUDY:
1043 changespritestat(i, FACE);
1044 if (mapon > 24)
1045 sprite[i].hitag = adjusthp(700);
1046 else
1047 sprite[i].hitag = adjusthp(500);
1048 sprite[i].lotag = 100;
1049 sprite[i].xrepeat = sprite[i].yrepeat = 32;
1050 sprite[i].cstat |= 0x101;
1051 break;
1052 case GOBWEAPON:
1053 case WEAPON1:
1054 sprite[i].xrepeat = 34;
1055 sprite[i].yrepeat = 21;
1056 break;
1057 case WEAPON2:
1058 sprite[i].xrepeat = 26;
1059 sprite[i].yrepeat = 26;
1060 break;
1061 case WEAPON3:
1062 sprite[i].xrepeat = 44;
1063 sprite[i].yrepeat = 39;
1064 break;
1065 case WEAPON4:
1066 sprite[i].xrepeat = 25;
1067 sprite[i].yrepeat = 20;
1068 break;
1069 case WEAPON6:
1070 sprite[i].xrepeat = 20;
1071 sprite[i].yrepeat = 15;
1072 sprite[i].cstat &= ~3;
1073 break;
1074 case WEAPON7:
1075 sprite[i].xrepeat = 41;
1076 sprite[i].yrepeat = 36;
1077 sprite[i].cstat &= ~3;
1078 break;
1079 case QUIVER:
1080 sprite[i].xrepeat = 27;
1081 sprite[i].yrepeat = 27;
1082 break;
1083 case LEATHERARMOR:
1084 sprite[i].xrepeat = 47;
1085 sprite[i].yrepeat = 50;
1086 break;
1087 case CHAINMAIL:
1088 case PLATEARMOR:
1089 case SHIELD:
1090 sprite[i].xrepeat = sprite[i].yrepeat = 26;
1091 break;
1092 case HELMET:
1093 sprite[i].xrepeat = 27;
1094 sprite[i].yrepeat = 28;
1095 break;
1096 case SCROLLSCARE:
1097 case SCROLLNUKE:
1098 case SCROLLFLY:
1099 case SCROLLFIREBALL:
1100 case SCROLLFREEZE:
1101 case SCROLLNIGHT:
1102 case SCROLLMAGIC:
1103 sprite[i].xrepeat = 35;
1104 sprite[i].yrepeat = 36;
1105 sprite[i].cstat &= ~3;
1106 break;
1107 case DIAMONDRING:
1108 case ADAMANTINERING:
1109 sprite[i].xrepeat = 14;
1110 sprite[i].yrepeat = 14;
1111 break;
1112 case SHADOWAMULET:
1113 sprite[i].xrepeat = 30;
1114 sprite[i].yrepeat = 23;
1115 break;
1116 case GLASSSKULL:
1117 sprite[i].xrepeat = 22;
1118 sprite[i].yrepeat = 22;
1119 break;
1120 case AHNK:
1121 sprite[i].xrepeat = 51;
1122 sprite[i].yrepeat = 54;
1123 break;
1124 case BLUESCEPTER:
1125 case YELLOWSCEPTER:
1126 sprite[i].xrepeat = 32;
1127 sprite[i].yrepeat = 32;
1128 break;
1129 case ONYXRING:
1130 sprite[i].xrepeat = 42;
1131 sprite[i].yrepeat = 28;
1132 break;
1133 case HORNEDSKULL:
1134 case CRYSTALSTAFF:
1135 sprite[i].xrepeat = 64;
1136 sprite[i].yrepeat = 64;
1137 break;
1138 case AMULETOFTHEMIST:
1139 sprite[i].xrepeat = 26;
1140 sprite[i].yrepeat = 28;
1141 break;
1142 case SAPHIRERING:
1143 sprite[i].xrepeat = 30;
1144 sprite[i].yrepeat = 20;
1145 break;
1146 case PINE:
1147 sprite[i].xrepeat = treesize = ((krand() % 5) + 3) << 4;
1148 sprite[i].yrepeat = treesize;
1149 break;
1150 case GIFTBOX:
1151 sprite[i].xrepeat = 56;
1152 sprite[i].yrepeat = 49;
1153 break;
1154 case GYSER:
1155 sprite[i].xrepeat = 32;
1156 sprite[i].yrepeat = 18;
1157 sprite[i].shade = -17;
1158 sprite[i].pal = 0;
1159 //changespritestat(i,DORMANT);
1160 break;
1161 case BARREL:
1162 case VASEA:
1163 case VASEB:
1164 case VASEC:
1165 sprite[i].cstat |= 0x101;
1166 sprite[i].clipdist = 64;
1167 break;
1168 case BRASSKEY:
1169 sprite[i].xrepeat = sprite[i].yrepeat = 24;
1170 break;
1171 case BLACKKEY:
1172 sprite[i].xrepeat = sprite[i].yrepeat = 24;
1173 break;
1174 case GLASSKEY:
1175 sprite[i].xrepeat = sprite[i].yrepeat = 24;
1176 break;
1177 case IVORYKEY:
1178 sprite[i].xrepeat = sprite[i].yrepeat = 24;
1179 break;
1180 case THEHORN:
1181 sprite[i].xrepeat = sprite[i].yrepeat = 32;
1182 break;
1183 case 2233: // team flags
1184 // TODO netmarkflag(i);
1185 break;
1186 }
1187 }
1188 }
1189
1190 for (i = 0; i < numsectors; i++)
1191 {
1192 if (sector[i].lotag == 100) {
1193 spikesector[spikecnt++] = i;
1194 }
1195
1196 if (sector[i].lotag == 70) {
1197 skypanlist[skypancnt++] = i;
1198 }
1199
1200 if (sector[i].lotag >= 80 && sector[i].lotag <= 89)
1201 {
1202 floorpanninglist[floorpanningcnt++] = i;
1203 }
1204
1205 if (sector[i].lotag >= 900 && sector[i].lotag <= 999)
1206 {
1207 lavadrylandsector[lavadrylandcnt] = i;
1208 lavadrylandcnt++;
1209 }
1210
1211 if (sector[i].lotag >= 2100 && sector[i].lotag <= 2199)
1212 {
1213 startwall = sector[i].wallptr;
1214 endwall = startwall + sector[i].wallnum - 1;
1215 dax = 0;
1216 day = 0;
1217 for (j = startwall; j <= endwall; j++) {
1218 dax += wall[j].x;
1219 day += wall[j].y;
1220 }
1221 revolvepivotx[revolvecnt] = dax / (endwall - startwall + 1);
1222 revolvepivoty[revolvecnt] = day / (endwall - startwall + 1);
1223
1224 k = 0;
1225 for (j = startwall; j <= endwall; j++) {
1226 revolvex[revolvecnt][k] = wall[j].x;
1227 revolvey[revolvecnt][k] = wall[j].y;
1228 k++;
1229 }
1230 revolvesector[revolvecnt] = i;
1231 revolveang[revolvecnt] = 0;
1232
1233 revolveclip[revolvecnt] = 1;
1234 if (sector[i].ceilingz == sector[wall[startwall].nextsector].ceilingz) {
1235 revolveclip[revolvecnt] = 0;
1236 }
1237 revolvecnt++;
1238 }
1239
1240 switch (sector[i].lotag)
1241 {
1242 case DOORSWINGTAG:
1243 startwall = sector[i].wallptr;
1244 endwall = startwall + sector[i].wallnum - 1;
1245 for (j = startwall; j <= endwall; j++)
1246 {
1247 if (wall[j].lotag == 4)
1248 {
1249 k = wall[wall[wall[wall[j].point2].point2].point2].point2;
1250 if ((wall[j].x == wall[k].x) && (wall[j].y == wall[k].y)) {
1251 swingdoor[swingcnt].wall[0] = j;
1252 swingdoor[swingcnt].wall[1] = wall[j].point2;
1253 swingdoor[swingcnt].wall[2] = wall[wall[j].point2].point2;
1254 swingdoor[swingcnt].wall[3] = wall[wall[wall[j].point2].point2].point2;
1255 swingdoor[swingcnt].angopen = 1536;
1256 swingdoor[swingcnt].angclosed = 0;
1257 swingdoor[swingcnt].angopendir = -1;
1258 }
1259 else {
1260 swingdoor[swingcnt].wall[0] = wall[j].point2;
1261 swingdoor[swingcnt].wall[1] = j;
1262 swingdoor[swingcnt].wall[2] = lastwall(j);
1263 swingdoor[swingcnt].wall[3] = lastwall(swingdoor[swingcnt].wall[2]);
1264 swingdoor[swingcnt].angopen = 512;
1265 swingdoor[swingcnt].angclosed = 0;
1266 swingdoor[swingcnt].angopendir = 1;
1267 }
1268 for (k = 0; k < 4; k++) {
1269 swingdoor[swingcnt].x[k] = wall[swingdoor[swingcnt].wall[k]].x;
1270 swingdoor[swingcnt].y[k] = wall[swingdoor[swingcnt].wall[k]].y;
1271 }
1272 swingdoor[swingcnt].sector = i;
1273 swingdoor[swingcnt].ang = swingdoor[swingcnt].angclosed;
1274 swingdoor[swingcnt].anginc = 0;
1275 swingcnt++;
1276 }
1277 }
1278 break;
1279 case 11:
1280 xpanningsectorlist[xpanningsectorcnt++] = i;
1281 break;
1282 case 12:
1283 dasector = i;
1284 dax = 0x7fffffff;
1285 day = 0x7fffffff;
1286 dax2 = 0x80000000;
1287 day2 = 0x80000000;
1288 startwall = sector[i].wallptr;
1289 endwall = startwall + sector[i].wallnum - 1;
1290
1291 for (j = startwall; j <= endwall; j++)
1292 {
1293 if (wall[j].x < dax)
1294 dax = wall[j].x;
1295 if (wall[j].y < day)
1296 day = wall[j].y;
1297 if (wall[j].x > dax2)
1298 dax2 = wall[j].x;
1299 if (wall[j].y > day2)
1300 day2 = wall[j].y;
1301 if (wall[j].lotag == 3)
1302 k = j;
1303 }
1304 if (wall[k].x == dax)
1305 dragxdir[dragsectorcnt] = -16;
1306 if (wall[k].y == day)
1307 dragydir[dragsectorcnt] = -16;
1308 if (wall[k].x == dax2)
1309 dragxdir[dragsectorcnt] = 16;
1310 if (wall[k].y == day2)
1311 dragydir[dragsectorcnt] = 16;
1312
1313 dasector = wall[startwall].nextsector;
1314 dragx1[dragsectorcnt] = 0x7fffffff;
1315 dragy1[dragsectorcnt] = 0x7fffffff;
1316 dragx2[dragsectorcnt] = 0x80000000;
1317 dragy2[dragsectorcnt] = 0x80000000;
1318 startwall = sector[dasector].wallptr;
1319 endwall = startwall + sector[dasector].wallnum - 1;
1320
1321 for (j = startwall; j <= endwall; j++)
1322 {
1323 if (wall[j].x < dragx1[dragsectorcnt])
1324 dragx1[dragsectorcnt] = wall[j].x;
1325 if (wall[j].y < dragy1[dragsectorcnt])
1326 dragy1[dragsectorcnt] = wall[j].y;
1327 if (wall[j].x > dragx2[dragsectorcnt])
1328 dragx2[dragsectorcnt] = wall[j].x;
1329 if (wall[j].y > dragy2[dragsectorcnt])
1330 dragy2[dragsectorcnt] = wall[j].y;
1331 }
1332
1333 dragx1[dragsectorcnt] += (wall[sector[i].wallptr].x - dax);
1334 dragy1[dragsectorcnt] += (wall[sector[i].wallptr].y - day);
1335 dragx2[dragsectorcnt] -= (dax2 - wall[sector[i].wallptr].x);
1336 dragy2[dragsectorcnt] -= (day2 - wall[sector[i].wallptr].y);
1337
1338 dragfloorz[dragsectorcnt] = sector[i].floorz;
1339
1340 dragsectorlist[dragsectorcnt++] = i;
1341 break;
1342 case 10:
1343 case 14:
1344 case 4002:
1345 warpsectorlist[warpsectorcnt++] = i;
1346 break;
1347 case 10000:
1348 bobbingsectorlist[bobbingsectorcnt++] = i;
1349 }
1350 if (sector[i].floorpicnum == TELEPAD && sector[i].lotag == 0) {
1351 warpsectorlist[warpsectorcnt++] = i;
1352 }
1353 }
1354
1355 ypanningwallcnt = 0;
1356 for (i = 0; i < numwalls; i++)
1357 {
1358 if (wall[i].lotag == 1) {
1359 ypanningwalllist[ypanningwallcnt++] = i;
1360 }
1361 }
1362
1363 automapping = 1;
1364
1365 if (justteleported == 1 || loadedgame == 1)
1366 {
1367 plr->hvel = 0;
1368 angvel = 0;
1369 svel = 0;
1370 vel = 0;
1371
1372 plr->spritenum = insertsprite(plr->sector, 0);
1373 plr->oldsector = plr->sector;
1374
1375 sprite[plr->spritenum].x = plr->x;
1376 sprite[plr->spritenum].y = plr->y;
1377 sprite[plr->spritenum].z = sector[plr->sector].floorz;
1378 sprite[plr->spritenum].cstat = 1 + 256;
1379 sprite[plr->spritenum].picnum = FRED;
1380 sprite[plr->spritenum].shade = 0;
1381 sprite[plr->spritenum].xrepeat = 36;
1382 sprite[plr->spritenum].yrepeat = 36;
1383 sprite[plr->spritenum].ang = plr->ang;
1384 sprite[plr->spritenum].xvel = 0;
1385 sprite[plr->spritenum].yvel = 0;
1386 sprite[plr->spritenum].zvel = 0;
1387 sprite[plr->spritenum].owner = 4096;
1388 sprite[plr->spritenum].lotag = 0;
1389 sprite[plr->spritenum].hitag = 0;
1390 sprite[plr->spritenum].pal = 1;
1391
1392 vec3_t pos;
1393 pos.x = plr->x;
1394 pos.y = plr->y;
1395 pos.z = plr->z + (PLAYERHEIGHT << 8);
1396
1397 setsprite(plr->spritenum, &pos);
1398
1399 justteleported = 0;
1400 loadedgame = 0;
1401 }
1402 }
1403
DrawHUD()1404 void DrawHUD()
1405 {
1406 overwritesprite(0, 200 - 46, NEWSTATUSBAR, 0, 0x2, 0);
1407
1408 healthpic();
1409 drawarmor();
1410 drawpotionpic();
1411 levelpic();
1412 drawscore();
1413 draworbpic();
1414 }
1415
drawscreen(Player * plr)1416 void drawscreen(Player* plr)
1417 {
1418 if (plr->dimension == 3 || plr->dimension == 2)
1419 {
1420 drawrooms(plr->x, plr->y, plr->z, plr->ang, plr->horiz, plr->sector);
1421 transformactors(plr);
1422
1423 renderDrawMasks();
1424
1425 if (!plr->playerdie) {
1426 drawweapons(plr);
1427 }
1428
1429 if (plr->spiked) {
1430 spikeheart(plr);
1431 }
1432
1433 dofx();
1434 }
1435
1436 if (plr->dimension == 2) {
1437 drawoverheadmap(plr);
1438 }
1439
1440 monitor();
1441 screenfx();
1442
1443 plr->oldsector = plr->sector;
1444
1445 if (netgame) {
1446 whnetmon();
1447 }
1448
1449 DrawHUD();
1450
1451 //updatepics();
1452
1453 G_PrintFPS();
1454
1455 videoNextPage();
1456 }
1457
timerhandler()1458 void timerhandler()
1459 {
1460 // TODO totalclock++;
1461
1462 OSD_DispatchQueued();
1463 }
1464
InitTimer()1465 void InitTimer()
1466 {
1467 timerInit(kTimerTicks);
1468 timerSetCallback(timerhandler);
1469 }
1470
app_main(int argc,char const * const * argv)1471 int app_main(int argc, char const* const* argv)
1472 {
1473 char temp1[10] = { "DEMO" };
1474
1475 Player* plr = &player[pyrn];
1476
1477 char tempbuf[256];
1478
1479 #ifdef _WIN32
1480 #ifndef DEBUGGINGAIDS
1481 if (!G_CheckCmdSwitch(argc, argv, "-noinstancechecking") && !windowsCheckAlreadyRunning())
1482 {
1483 #ifdef EDUKE32_STANDALONE
1484 if (!wm_ynbox(APPNAME, "It looks like " APPNAME " is already running.\n\n"
1485 #else
1486 if (!wm_ynbox(APPNAME, "It looks like the game is already running.\n\n"
1487 #endif
1488 "Are you sure you want to start another copy?"))
1489 return 3;
1490 }
1491 #endif
1492 #endif
1493
1494 G_ExtPreInit(argc, argv);
1495
1496 OSD_SetLogFile(APPBASENAME ".log");
1497
1498 OSD_SetFunctions(NULL,
1499 NULL,
1500 NULL,
1501 NULL,
1502 NULL,
1503 GAME_clearbackground,
1504 BGetTime,
1505 GAME_onshowosd);
1506
1507 wm_setapptitle(APPNAME);
1508
1509 initprintf("Witchaven %s\n", s_buildRev);
1510 PrintBuildInfo();
1511
1512 // This needs to happen afterwards, as G_CheckCommandLine() is where we set
1513 // up the command-line-provided search paths (duh).
1514 G_ExtInit();
1515
1516 if (!g_useCwd)
1517 G_AddSearchPaths();
1518
1519 #if defined(RENDERTYPEWIN) && defined(USE_OPENGL)
1520 if (forcegl) initprintf("GL driver blacklist disabled.\n");
1521 #endif
1522
1523 // used with binds for fast function lookup
1524 hash_init(&h_gamefuncs);
1525 for (bssize_t i = kMaxGameFunctions - 1; i >= 0; i--)
1526 {
1527 if (gamefunctions[i][0] == '\0')
1528 continue;
1529
1530 hash_add(&h_gamefuncs, gamefunctions[i], i, 0);
1531 }
1532
1533 #ifdef STARTUP_SETUP_WINDOW
1534 int const readSetup =
1535 #endif
1536 CONFIG_ReadSetup();
1537
1538 if (enginePreInit())
1539 {
1540 wm_msgbox("Build Engine Initialization Error",
1541 "There was a problem initializing the Build engine: %s", engineerrstr);
1542 ERRprintf("app_main: There was a problem initializing the Build engine: %s\n", engineerrstr);
1543 Bexit(2);
1544 }
1545
1546 if (Bstrcmp(setupfilename, kSetupFilename))
1547 initprintf("Using config file \"%s\".\n", setupfilename);
1548
1549 G_ScanGroups();
1550
1551 wm_msgbox("Pre-Release Software Warning", "%s is not ready for public use. Proceed with caution!", AppProperName);
1552
1553 #ifdef STARTUP_SETUP_WINDOW
1554 if (readSetup < 0 || (!g_noSetup && gSetup.forcesetup) || g_commandSetup)
1555 {
1556 if (quitevent || !startwin_run())
1557 {
1558 engineUnInit();
1559 Bexit(0);
1560 }
1561 }
1562 #endif
1563
1564 G_LoadGroups(!g_noAutoLoad && !gSetup.noautoload);
1565
1566 CONFIG_WriteSetup(1);
1567 CONFIG_ReadSetup();
1568
1569 initprintf("Initializing OSD...\n");
1570
1571 Bsprintf(tempbuf, "Witchaven %s", s_buildRev);
1572 OSD_SetVersion(tempbuf, 10, 0);
1573 OSD_SetParameters(0, 0, 0, 0, 0, 0, OSD_ERROR, OSDTEXT_RED, gamefunctions[gamefunc_Show_Console][0] == '\0' ? OSD_PROTECTED : 0);
1574 registerosdcommands();
1575
1576 SetupInput();
1577
1578 /*
1579 char* const setupFileName = Xstrdup(setupfilename);
1580 char* const p = strtok(setupFileName, ".");
1581
1582 if (!p || !Bstrcmp(setupfilename, kSetupFilename))
1583 Bsprintf(tempbuf, "settings.cfg");
1584 else
1585 Bsprintf(tempbuf, "%s_settings.cfg", p);
1586
1587 Xfree(setupFileName);
1588 */
1589 OSD_Exec("ewitchaven_cvars.cfg");
1590 OSD_Exec("ewitchaven_autoexec.cfg");
1591
1592 CONFIG_SetDefaultKeys(keydefaults, true);
1593
1594 system_getcvars();
1595
1596 InstallEngine();
1597
1598 const char* defsfile = G_DefFile();
1599 uint32_t stime = timerGetTicks();
1600 if (!loaddefinitionsfile(defsfile))
1601 {
1602 uint32_t etime = timerGetTicks();
1603 initprintf("Definitions file \"%s\" loaded in %d ms.\n", defsfile, etime - stime);
1604 }
1605 loaddefinitions_game(defsfile, FALSE);
1606
1607 if (enginePostInit())
1608 shutdown();
1609
1610 g_frameDelay = calcFrameDelay(r_maxfps, r_maxfpsoffset);
1611
1612 KB_Startup();
1613 InitTimer();
1614
1615 //TODO netcheckargs(argc,argv);
1616
1617 tprintf(-1, 0, "WITCHAVEN Copyright (C) 1995 IntraCorp, Inc. ver 1.1", temp1);
1618 tprintf(2, 2, " map name: level%d", mapon);
1619 tprintf(2, 3, " initengine()");
1620
1621 #if 0
1622 int fil;
1623 if ((fil = open("setup.dat", O_BINARY | O_RDWR, S_IREAD)) != -1) {
1624 read(fil, &option, NUMOPTIONS);
1625 read(fil, keys, WHNUMKEYS);
1626 read(fil, option2, 7);
1627 close(fil);
1628 }
1629
1630 if (access("pref.dat", F_OK) != 0) {
1631 goreon = 1;
1632 brightness = gbrightness = 0;
1633 digilevel = 11;
1634 musiclevel = 11;
1635 fil = open("pref.dat", O_BINARY | O_TRUNC | O_CREAT | O_WRONLY, S_IREAD | S_IWRITE);
1636 if (fil != NULL) {
1637 write(fil, &goreon, 2);
1638 write(fil, &brightness, 2);
1639 write(fil, &gbrightness, 2);
1640 write(fil, &digilevel, 2);
1641 write(fil, &musiclevel, 2);
1642 write(fil, &difficulty, 2);
1643 close(fil);
1644 }
1645 }
1646 else {
1647 fil = open("pref.dat", O_RDONLY | O_BINARY);
1648 if (fil != NULL) {
1649 read(fil, &goreon, 2);
1650 read(fil, &brightness, 2);
1651 read(fil, &gbrightness, 2);
1652 read(fil, &digilevel, 2);
1653 read(fil, &musiclevel, 2);
1654 read(fil, &difficulty, 2);
1655 close(fil);
1656 }
1657 }
1658 #endif
1659
1660 if (option[8] == 1 || option[9] == 1)
1661 MusicMode = 1;
1662 else
1663 MusicMode = 0;
1664
1665 if (option[10] == 1 || option[11] == 1)
1666 SoundMode = 1;
1667 else
1668 SoundMode = 0;
1669
1670 // TEMP
1671 MusicMode = 1;
1672 SoundMode = 1;
1673 musiclevel = 15;
1674
1675 //JSA_SPOOGE
1676 if (SoundMode) {
1677 //TODO SND_DoBuffers();
1678 }
1679
1680 #if 0 // TODO
1681 if (option[3] != 0) {
1682 initmouse();
1683 mousekeys[0] = option2[0];
1684 mousekeys[1] = option2[1];
1685 }
1686
1687 if (option2[2] != 0) {
1688 initjstick();
1689 }
1690 #endif
1691 /*
1692 switch (option[0])
1693 {
1694 case 1:
1695 {
1696 initengine(1, vesares[option[6] & 15][0], vesares[option[6] & 15][1]);
1697 if (vesares[option[6] & 15][0] == 640)
1698 svga = 1;
1699 }
1700 break;
1701 default:
1702 initengine(1,320,200);
1703 break;
1704 }
1705 */
1706
1707 /* TODO
1708 pskyoff[0] = 0;
1709 pskyoff[1] = 0;
1710 pskybits = 1;
1711 */
1712
1713 SND_Startup();
1714
1715 // tprintf(2, 4, " loadpics()");
1716 // tprintf(2, 5, " tiles000.art");
1717
1718 //** Les END - 09/06/95
1719 #if 0
1720 if (vixen = ismscdex()) {
1721 sprintf(tempbuf, "%c:\\whaven\\intro.smk", vixen);
1722 if (access(tempbuf, F_OK) != 0) {
1723 crash("\nCD-ROM NOT DETECTED \n");
1724 }
1725 }
1726 #endif
1727
1728 initlava();
1729 initwater();
1730
1731 tprintf(2, 6, " setupboard()");
1732
1733 pyrn = 0;
1734 tprintf(2, 7, " initplayersprite(%d)", pyrn);
1735 tprintf(2, 8, " resettiming()");
1736 totalclock = 0;
1737
1738 //JSA_DEMO start menu song here use
1739 //flc_init();
1740 //flc_playseq(plr,0,FT_FULLSCREEN);
1741
1742 SND_MenuMusic(MENUSONG);
1743
1744 //precache();
1745
1746 plr->playerdie = false;
1747 plr->oldsector = plr->sector;
1748 plr->horiz = 100;
1749 plr->zoom = 256;
1750 if (svga == 1) {
1751 plr->screensize = 328;
1752 }
1753 else {
1754 plr->screensize = 320;
1755 }
1756
1757 plr->dimension = 3;
1758 plr->height = PLAYERHEIGHT;
1759 plr->z = sector[plr->sector].floorz - (plr->height << 8);
1760
1761 //TODO visibility = 1024;
1762
1763 parallaxtype = 1;
1764
1765 setup3dscreen();
1766
1767 // intro();
1768
1769 /*
1770 initpaletteshifts();
1771 readpalettetable();
1772
1773 gameactivated=0;
1774 escapetomenu=0;
1775 */
1776
1777
1778 /*
1779 if (option[MULTIOPT] != 0) {
1780 initmultiplayers(MAXPLAYERS);
1781 }
1782 */
1783
1784 playloop();
1785
1786 return 0;
1787 }
1788
intro()1789 void intro()
1790 {
1791 //loadtile(CAPSTONE);
1792
1793 //for(i=0;i<32;i++) {
1794 // overwritesprite(80,40,CAPSTONE,0,0,0);
1795 // videoNextPage();
1796 //}
1797
1798 tileLoad(TITLEPIC);
1799
1800 for (int i = 0; i < 32; i++)
1801 {
1802 overwritesprite(0,0,TITLEPIC,32-i,2,0);
1803 videoNextPage();
1804 }
1805
1806 rp_delay(120);
1807
1808 for (int i = 0; i < 32; i++)
1809 {
1810 overwritesprite(0,0,TITLEPIC,i,2,0);
1811 videoNextPage();
1812 }
1813 }
1814
1815 ClockTicks ototalclock;
1816
playloop()1817 void playloop()
1818 {
1819 Player *plr = &player[pyrn];
1820
1821 if (netgame) {
1822 // TODO initmulti(MAXPLAYERS);
1823 }
1824
1825 int exit = 0;
1826
1827 CONTROL_BindsEnabled = 1;
1828
1829 ototalclock = totalclock;
1830
1831 while (!exit)
1832 {
1833 static bool frameJustDrawn;
1834 bool gameUpdate = false;
1835 double gameUpdateStartTime = timerGetHiTicks();
1836
1837 if (gameactivated == 0 || escapetomenu == 1)
1838 {
1839 exit = menuscreen();
1840 }
1841
1842 if (totalclock >= (ototalclock + kTicksPerFrame))
1843 {
1844 do // while(0)
1845 {
1846 if (!frameJustDrawn)
1847 break;
1848
1849 frameJustDrawn = false;
1850
1851 int32_t oldsynctics = synctics;
1852 synctics = 4;
1853 processinput(plr);
1854 synctics = oldsynctics;
1855
1856 do
1857 {
1858 ototalclock += kTicksPerFrame;
1859 auto const moveClock = totalclock;
1860 /*
1861 if (gameactivated == 0 || escapetomenu == 1)
1862 {
1863 exit = menuscreen(plr);
1864 }
1865 else
1866 */
1867 {
1868 int32_t oldsynctics = synctics;
1869 // temp
1870 synctics = kTicksPerFrame;
1871 processobjs(plr);
1872 animateobjs(plr);
1873 animatetags(plr);
1874 doanimations(kTicksPerFrame);
1875 dodelayitems(kTicksPerFrame);
1876
1877 synctics = oldsynctics;
1878 }
1879
1880 if ((int)(totalclock - moveClock) >= (kTicksPerFrame >> 1))
1881 break;
1882 }
1883 while ((totalclock - ototalclock) >= kTicksPerFrame);
1884
1885 gameUpdate = true;
1886
1887 } while (0);
1888 }
1889
1890 keytimerstuff();
1891
1892 handleevents();
1893
1894 drawscreen(plr);
1895
1896 frameJustDrawn = true;
1897
1898 #if 0
1899
1900 handleevents();
1901
1902 if (gameactivated == 0 || escapetomenu == 1)
1903 {
1904 exit = menuscreen(plr);
1905 #if 0
1906 if (svga == 0)
1907 {
1908 permanentwritesprite(0, 0, BACKGROUND, 0, 0, 0, 319, 199, 0);
1909 permanentwritesprite(0, 200 - 46, STATUSBAR, 0, 0, 0, 319, 199, 0);
1910 //updatepics();
1911 }
1912
1913 if (svga == 1)
1914 {
1915 if (plr->screensize == 320) {
1916 overwritesprite(0, 372, SSTATUSBAR, 0, 0, 0);
1917 //updatepics();
1918 }
1919 }
1920 #endif
1921
1922 plr->z = sector[plr->sector].floorz - (PLAYERHEIGHT << 8);
1923 }
1924
1925 // drawscreen(plr);
1926 processinput(plr);
1927
1928 if (netgame)
1929 {
1930 netgetmove();
1931 netsendmove();
1932 }
1933
1934 processobjs(plr);
1935 animateobjs(plr);
1936 animatetags(plr);
1937 doanimations(synctics);
1938 dodelayitems(synctics);
1939
1940 //if (engineFPSLimit()) {
1941 drawscreen(plr);
1942 //}
1943 #endif
1944 }
1945 }
1946
drawoverheadmap(Player * plr)1947 void drawoverheadmap(Player *plr)
1948 {
1949 #if 0 // TODO
1950 int i, j, k, l, x1, y1, x2, y2, x3, y3, x4, y4, ox, oy, xoff, yoff;
1951 int dax, day, cosang, sinang, xspan, yspan, sprx, spry;
1952 int xrepeat, yrepeat, z1, z2, startwall, endwall, tilenum, daang;
1953 int xvect, yvect, xvect2, yvect2;
1954 char col;
1955 walltype *wal, *wal2;
1956 spritetype *spr;
1957 short cang;
1958 int czoom;
1959
1960 cang=(short)plr->ang;
1961 czoom=plr->zoom;
1962
1963 xvect = sintable[(2048-cang)& kAngleMask] * czoom;
1964 yvect = sintable[(1536-cang)& kAngleMask] * czoom;
1965 xvect2 = mulscale(xvect,yxaspect,16);
1966 yvect2 = mulscale(yvect,yxaspect,16);
1967
1968 //Draw red lines
1969 for (i=0;i<numsectors;i++)
1970 {
1971 startwall = sector[i].wallptr;
1972 endwall = sector[i].wallptr + sector[i].wallnum - 1;
1973
1974 z1 = sector[i].ceilingz;
1975 z2 = sector[i].floorz;
1976
1977 for(j=startwall,wal=&wall[startwall];j<=endwall;j++,wal++)
1978 {
1979 k = wal->nextwall;
1980 if (k < 0)
1981 continue;
1982
1983 if ((show2dwall[j>>3]&(1<<(j&7))) == 0) {
1984 continue;
1985 }
1986 if ((k > j) && ((show2dwall[k>>3]&(1<<(k&7))) > 0))
1987 continue;
1988
1989 if (sector[wal->nextsector].ceilingz == z1)
1990 if (sector[wal->nextsector].floorz == z2)
1991 if (((wal->cstat|wall[wal->nextwall].cstat)&(16+32)) == 0)
1992 continue;
1993
1994 col = 152;
1995
1996 if (plr->dimension == 2)
1997 {
1998 if (sector[i].floorz != sector[i].ceilingz)
1999 if (sector[wal->nextsector].floorz != sector[wal->nextsector].ceilingz)
2000 if (((wal->cstat|wall[wal->nextwall].cstat)&(16+32)) == 0)
2001 if (sector[i].floorz == sector[wal->nextsector].floorz)
2002 continue;
2003 if (sector[i].floorpicnum != sector[wal->nextsector].floorpicnum)
2004 continue;
2005 if (sector[i].floorshade != sector[wal->nextsector].floorshade)
2006 continue;
2007 col = 12;
2008 }
2009
2010 ox = wal->x-plr->x; oy = wal->y-plr->y;
2011 x1 = mulscale(ox,xvect,16) - mulscale(oy,yvect,16);
2012 y1 = mulscale(oy,xvect2,16) + mulscale(ox,yvect2,16);
2013
2014 wal2 = &wall[wal->point2];
2015 ox = wal2->x-plr->x; oy = wal2->y-plr->y;
2016 x2 = mulscale(ox,xvect,16) - mulscale(oy,yvect,16);
2017 y2 = mulscale(oy,xvect2,16) + mulscale(ox,yvect2,16);
2018
2019 drawline256(x1+(xdim<<11),y1+(ydim<<11),x2+(xdim<<11),y2+(ydim<<11),col);
2020 }
2021 }
2022
2023 //Draw sprites
2024 k = plr->spritenum;
2025 for(i=0;i<numsectors;i++)
2026 for(j=headspritesect[i];j>=0;j=nextspritesect[j])
2027 if ((show2dsprite[j>>3]&(1<<(j&7))) > 0)
2028 {
2029 spr = &sprite[j];
2030 col = 56;
2031 if ((spr->cstat&1) > 0)
2032 col = 248;
2033 if (j == k)
2034 col = 31;
2035
2036 sprx = spr->x;
2037 spry = spr->y;
2038
2039 k = spr->statnum;
2040 if ((k >= 1) && (k <= 8) && (k != 2)) //Interpolate moving sprite
2041 {
2042 sprx = osprite[j].x+mulscale(sprx-osprite[j].x,smoothratio,16);
2043 spry = osprite[j].y+mulscale(spry-osprite[j].y,smoothratio,16);
2044 }
2045
2046 switch (spr->cstat&48)
2047 {
2048 case 0:
2049 ox = sprx-plr->x; oy = spry-plr->y;
2050 x1 = mulscale(ox,xvect,16) - mulscale(oy,yvect,16);
2051 y1 = mulscale(oy,xvect2,16) + mulscale(ox,yvect2,16);
2052
2053 if (plr->dimension == 1)
2054 {
2055 ox = (sintable[(spr->ang+512)& kAngleMask]>>7);
2056 oy = (sintable[(spr->ang)& kAngleMask]>>7);
2057 x2 = mulscale(ox,xvect,16) - mulscale(oy,yvect,16);
2058 y2 = mulscale(oy,xvect,16) + mulscale(ox,yvect,16);
2059
2060 if (j == plr->spritenum)
2061 {
2062 x2 = 0L;
2063 y2 = -(czoom<<5);
2064 }
2065
2066 x3 = mulscale(x2,yxaspect,16);
2067 y3 = mulscale(y2,yxaspect,16);
2068
2069 drawline256(x1-x2+(xdim<<11),y1-y3+(ydim<<11),
2070 x1+x2+(xdim<<11),y1+y3+(ydim<<11),col);
2071 drawline256(x1-y2+(xdim<<11),y1+x3+(ydim<<11),
2072 x1+x2+(xdim<<11),y1+y3+(ydim<<11),col);
2073 drawline256(x1+y2+(xdim<<11),y1-x3+(ydim<<11),
2074 x1+x2+(xdim<<11),y1+y3+(ydim<<11),col);
2075 }
2076 else
2077 {
2078 if (((gotsector[i>>3]&(1<<(i&7))) > 0) && (czoom > 192))
2079 {
2080 daang = (spr->ang-cang)& kAngleMask;
2081 if (j == plr->spritenum )
2082 { x1 = 0; y1 = (yxaspect<<2); daang = 0; }
2083 rotatesprite((x1<<4)+(xdim<<15),(y1<<4)+(ydim<<15),mulscale(czoom*spr->yrepeat,yxaspect,16),daang,spr->picnum,spr->shade,spr->pal,(spr->cstat&2)>>1);
2084 }
2085 }
2086 break;
2087 case 16:
2088 x1 = sprx;
2089 y1 = spry;
2090 tilenum = spr->picnum;
2091 xoff = (int)((signed char)((picanm[tilenum]>>8)&255))+((int)spr->xoffset);
2092 if ((spr->cstat&4) > 0)
2093 xoff = -xoff;
2094 k = spr->ang;
2095 l = spr->xrepeat;
2096 dax = sintable[k& kAngleMask]*l;
2097 day = sintable[(k+1536)& kAngleMask]*l;
2098 l = tilesizx[tilenum];
2099 k = (l>>1)+xoff;
2100 x1 -= mulscale(dax,k,16);
2101 x2 = x1+mulscale(dax,l,16);
2102 y1 -= mulscale(day,k,16);
2103 y2 = y1+mulscale(day,l,16);
2104
2105 ox = x1-plr->x;
2106 oy = y1-plr->y;
2107 x1 = mulscale(ox,xvect,16) - mulscale(oy,yvect,16);
2108 y1 = mulscale(oy,xvect2,16) + mulscale(ox,yvect2,16);
2109
2110 ox = x2-plr->x;
2111 oy = y2-plr->y;
2112 x2 = mulscale(ox,xvect,16) - mulscale(oy,yvect,16);
2113 y2 = mulscale(oy,xvect2,16) + mulscale(ox,yvect2,16);
2114
2115 drawline256(x1+(xdim<<11),y1+(ydim<<11),
2116 x2+(xdim<<11),y2+(ydim<<11),col);
2117
2118 break;
2119 case 32:
2120 if (plr->dimension == 1)
2121 {
2122 tilenum = spr->picnum;
2123 xoff = (int)((signed char)((picanm[tilenum]>>8)&255))+((int)spr->xoffset);
2124 yoff = (int)((signed char)((picanm[tilenum]>>16)&255))+((int)spr->yoffset);
2125 if ((spr->cstat&4) > 0)
2126 xoff = -xoff;
2127 if ((spr->cstat&8) > 0)
2128 yoff = -yoff;
2129
2130 k = spr->ang;
2131 cosang = sintable[(k+512)& kAngleMask];
2132 sinang = sintable[k];
2133 xspan = tilesizx[tilenum];
2134 xrepeat = spr->xrepeat;
2135 yspan = tilesizy[tilenum];
2136 yrepeat = spr->yrepeat;
2137
2138 dax = ((xspan>>1)+xoff)*xrepeat;
2139 day = ((yspan>>1)+yoff)*yrepeat;
2140 x1 = sprx + mulscale(sinang,dax,16) + mulscale(cosang,day,16);
2141 y1 = spry + mulscale(sinang,day,16) - mulscale(cosang,dax,16);
2142 l = xspan*xrepeat;
2143 x2 = x1 - mulscale(sinang,l,16);
2144 y2 = y1 + mulscale(cosang,l,16);
2145 l = yspan*yrepeat;
2146 k = -mulscale(cosang,l,16);
2147 x3 = x2+k;
2148 x4 = x1+k;
2149 k = -mulscale(sinang,l,16);
2150 y3 = y2+k;
2151 y4 = y1+k;
2152
2153 ox = x1-plr->x;
2154 oy = y1-plr->y;
2155 x1 = mulscale(ox,xvect,16) - mulscale(oy,yvect,16);
2156 y1 = mulscale(oy,xvect2,16) + mulscale(ox,yvect2,16);
2157
2158 ox = x2-plr->x;
2159 oy = y2-plr->y;
2160 x2 = mulscale(ox,xvect,16) - mulscale(oy,yvect,16);
2161 y2 = mulscale(oy,xvect2,16) + mulscale(ox,yvect2,16);
2162
2163 ox = x3-plr->x;
2164 oy = y3-plr->y;
2165 x3 = mulscale(ox,xvect,16) - mulscale(oy,yvect,16);
2166 y3 = mulscale(oy,xvect2,16) + mulscale(ox,yvect2,16);
2167
2168 ox = x4-plr->x;
2169 oy = y4-plr->y;
2170 x4 = mulscale(ox,xvect,16) - mulscale(oy,yvect,16);
2171 y4 = mulscale(oy,xvect2,16) + mulscale(ox,yvect2,16);
2172
2173 drawline256(x1+(xdim<<11),y1+(ydim<<11),
2174 x2+(xdim<<11),y2+(ydim<<11),col);
2175
2176 drawline256(x2+(xdim<<11),y2+(ydim<<11),
2177 x3+(xdim<<11),y3+(ydim<<11),col);
2178
2179 drawline256(x3+(xdim<<11),y3+(ydim<<11),
2180 x4+(xdim<<11),y4+(ydim<<11),col);
2181
2182 drawline256(x4+(xdim<<11),y4+(ydim<<11),
2183 x1+(xdim<<11),y1+(ydim<<11),col);
2184
2185 }
2186 break;
2187 }
2188 }
2189
2190 //Draw white lines
2191 for(i=0;i<numsectors;i++)
2192 {
2193 startwall = sector[i].wallptr;
2194 endwall = sector[i].wallptr + sector[i].wallnum - 1;
2195
2196 for(j=startwall,wal=&wall[startwall];j<=endwall;j++,wal++)
2197 {
2198 if (wal->nextwall >= 0)
2199 continue;
2200
2201 if ((show2dwall[j>>3]&(1<<(j&7))) == 0) {
2202 continue;
2203 }
2204
2205 if (tilesizx[wal->picnum] == 0)
2206 continue;
2207 if (tilesizy[wal->picnum] == 0)
2208 continue;
2209
2210 ox = wal->x-plr->x;
2211 oy = wal->y-plr->y;
2212 x1 = mulscale(ox,xvect,16) - mulscale(oy,yvect,16);
2213 y1 = mulscale(oy,xvect2,16) + mulscale(ox,yvect2,16);
2214
2215 wal2 = &wall[wal->point2];
2216 ox = wal2->x-plr->x;
2217 oy = wal2->y-plr->y;
2218 x2 = mulscale(ox,xvect,16) - mulscale(oy,yvect,16);
2219 y2 = mulscale(oy,xvect2,16) + mulscale(ox,yvect2,16);
2220
2221 drawline256(x1+(xdim<<11),y1+(ydim<<11),x2+(xdim<<11),y2+(ydim<<11),24);
2222 }
2223 }
2224 #endif
2225 }
2226
readpalettetable()2227 void readpalettetable()
2228 {
2229 uint8_t palbuf[256];
2230
2231 int hFile = kopen4loadfrommod("lookup.dat", 0);
2232 if (hFile == -1)
2233 {
2234 // TODO - error
2235 return;
2236 }
2237
2238 uint8_t num_tables = 0;
2239 kread(hFile, &num_tables, 1);
2240
2241 for (int j = 0; j < num_tables; j++)
2242 {
2243 char lookup_num;
2244 kread(hFile, &lookup_num, 1);
2245 kread(hFile, palbuf, 256);
2246
2247 paletteMakeLookupTable(lookup_num, (const char*)palbuf, 0, 0, 0, 1);
2248 }
2249
2250 kclose(hFile);
2251 }
2252
adjusthp(int hp)2253 int adjusthp(int hp)
2254 {
2255 float factor = (krand() % 20) / 100;
2256 int howhard = difficulty;
2257
2258 if (krand() % 100 > 50) {
2259 return((hp * (factor + 1)) * howhard);
2260 }
2261 else {
2262 return((hp - (hp * (factor))) * howhard);
2263 }
2264 }
2265
InstallEngine()2266 void InstallEngine()
2267 {
2268 // initgroupfile("stuff.dat");
2269
2270 char* cwd;
2271
2272 if (g_modDir[0] != '/' && (cwd = buildvfs_getcwd(NULL, 0)))
2273 {
2274 buildvfs_chdir(g_modDir);
2275 if (artLoadFiles("tiles%03i.art", MAXCACHE1DSIZE) < 0)
2276 {
2277 buildvfs_chdir(cwd);
2278 if (artLoadFiles("tiles%03i.art", MAXCACHE1DSIZE) < 0)
2279 crash("Failed loading art.");
2280 }
2281 buildvfs_chdir(cwd);
2282 #ifndef __ANDROID__ //This crashes on *some* Android devices. Small onetime memory leak. TODO fix above function
2283 Xfree(cwd);
2284 #endif
2285 }
2286 else if (artLoadFiles("tiles%03i.art", MAXCACHE1DSIZE) < 0)
2287 crash("Failed loading art.");
2288
2289 if (engineInit())
2290 {
2291 wm_msgbox("Fatal Engine Initialization Error",
2292 "There was a problem initializing the engine: %s\n\nThe application will now close.", engineerrstr);
2293 //TODO:
2294 //G_Cleanup();
2295 ERRprintf("G_Startup: There was a problem initializing the engine: %s\n", engineerrstr);
2296 exit(6);
2297 }
2298 if (videoSetGameMode(gSetup.fullscreen, gSetup.xdim, gSetup.ydim, gSetup.bpp, 0) < 0)
2299 {
2300 initprintf("Failure setting video mode %dx%dx%d %s! Trying next mode...\n", gSetup.xdim, gSetup.ydim,
2301 gSetup.bpp, gSetup.fullscreen ? "fullscreen" : "windowed");
2302
2303 int resIdx = 0;
2304
2305 for (int i = 0; i < validmodecnt; i++)
2306 {
2307 if (validmode[i].xdim == gSetup.xdim && validmode[i].ydim == gSetup.ydim)
2308 {
2309 resIdx = i;
2310 break;
2311 }
2312 }
2313
2314 int const savedIdx = resIdx;
2315 int bpp = gSetup.bpp;
2316
2317 while (videoSetGameMode(0, validmode[resIdx].xdim, validmode[resIdx].ydim, bpp, 0) < 0)
2318 {
2319 initprintf("Failure setting video mode %dx%dx%d windowed! Trying next mode...\n",
2320 validmode[resIdx].xdim, validmode[resIdx].ydim, bpp);
2321
2322 if (++resIdx == validmodecnt)
2323 {
2324 if (bpp == 8)
2325 crash("Fatal error: unable to set any video mode!");
2326
2327 resIdx = savedIdx;
2328 bpp = 8;
2329 }
2330 }
2331
2332 gSetup.xdim = validmode[resIdx].xdim;
2333 gSetup.ydim = validmode[resIdx].ydim;
2334 gSetup.bpp = bpp;
2335 }
2336
2337 initpaletteshifts();
2338 readpalettetable();
2339
2340 // build.obj is dated 9th July 1995
2341 enginecompatibilitymode = ENGINE_19950829;
2342
2343 engineinitflag = 1;
2344 }
2345
RemoveEngine()2346 void RemoveEngine()
2347 {
2348 engineUnInit();
2349 uninitgroupfile();
2350 }
2351