C5_PLAY.C 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426
  1. /* Catacomb Armageddon Source Code
  2. * Copyright (C) 1993-2014 Flat Rock Software
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. */
  18. // C3_PLAY.C
  19. #include "DEF.H"
  20. #include "gelib.h"
  21. #pragma hdrstop
  22. /*
  23. =============================================================================
  24. LOCAL CONSTANTS
  25. =============================================================================
  26. */
  27. #define POINTTICS 6
  28. #define PAUSE 300
  29. /*
  30. =============================================================================
  31. GLOBAL VARIABLES
  32. =============================================================================
  33. */
  34. byte bcolor;
  35. short skytimer=-1,skytimer_reset;
  36. short groundtimer=-1,groundtimer_reset;
  37. unsigned scolor,gcolor;
  38. unsigned *skycolor,*groundcolor,debug_sky,debug_gnd;
  39. unsigned nocolorchange=0xFFFF;
  40. byte BGFLAGS, // global that holds all current flags
  41. bgflag; // used by BG changer, this flag is set when done
  42. unsigned sky_daytonight[]={0x0909,0x0101,0x0808,0x0000,0xFFFF};
  43. //unsigned gnd_daytonight[]={0x0202,0xFFFF};
  44. unsigned sky_lightning[]={0x0101,0x0909,0x0f0f,0x0808,0x0000,0xFFFF};
  45. unsigned sky_colors[NUMLEVELS]={0x0000,0x0000,0x0000,0x0000,0x0808,
  46. 0x0404,0x0000,0x0000,0x0000,0x0000,
  47. 0x0000,0x0000,0x0000,0x0000,0x0606,
  48. 0x0000,0x0000,0x0000,0x0000,0x0000,
  49. 0x0000};
  50. unsigned gnd_colors[NUMLEVELS]={0x0202,0x0202,0x0606,0x0202,0x0707,
  51. 0x0505,0x0808,0x0606,0x0101,0x0808,
  52. 0x0606,0x0404,0x0808,0x0c0c,0x0e0e,
  53. 0x0808,0x0808,0x0c0c,0x0000,0x0707,
  54. 0x0808};
  55. ControlInfo control;
  56. boolean running=false; //,slowturn;
  57. int bordertime;
  58. objtype objlist[MAXACTORS],*new,*obj,*player,*lastobj,*objfreelist;
  59. #if USE_INERT_LIST
  60. inertobjtype inertobjlist[MAXINERTOBJ],*inert;
  61. #endif
  62. unsigned farmapylookup[MAPSIZE];
  63. byte *nearmapylookup[MAPSIZE];
  64. boolean singlestep,godmode;
  65. int extravbls;
  66. status_flags status_flag;
  67. int status_delay;
  68. //
  69. // replacing refresh manager
  70. //
  71. unsigned mapwidth,mapheight,tics,realtics;
  72. boolean compatability;
  73. byte *updateptr;
  74. unsigned mapwidthtable[64];
  75. unsigned uwidthtable[UPDATEHIGH];
  76. unsigned blockstarts[UPDATEWIDE*UPDATEHIGH];
  77. #define UPDATESCREENSIZE (UPDATEWIDE*PORTTILESHIGH+2)
  78. #define UPDATESPARESIZE (UPDATEWIDE*2+4)
  79. #define UPDATESIZE (UPDATESCREENSIZE+2*UPDATESPARESIZE)
  80. byte update[UPDATESIZE];
  81. int mousexmove,mouseymove;
  82. int pointcount,pointsleft;
  83. short BeepTime = 0;
  84. /*
  85. =============================================================================
  86. LOCAL VARIABLES
  87. =============================================================================
  88. */
  89. void CalcBounds (objtype *ob);
  90. void DrawPlayScreen (void);
  91. void PreFullDisplay(void);
  92. void PostFullDisplay(boolean draw_view);
  93. //
  94. // near data map array (wall values only, get text number from far data)
  95. //
  96. byte tilemap[MAPSIZE][MAPSIZE];
  97. byte spotvis[MAPSIZE][MAPSIZE];
  98. objtype *actorat[MAPSIZE][MAPSIZE];
  99. objtype dummyobj;
  100. int bordertime;
  101. int objectcount;
  102. void StopMusic(void);
  103. void StartMusic(void);
  104. void CalibrateJoystick(short joynum);
  105. //==========================================================================
  106. ///////////////////////////////////////////////////////////////////////////
  107. //
  108. // CenterWindow() - Generates a window of a given width & height in the
  109. // middle of the screen
  110. //
  111. ///////////////////////////////////////////////////////////////////////////
  112. #define MAXX 320
  113. #define MAXY 120
  114. void CenterWindow(word w,word h)
  115. {
  116. US_DrawWindow(((MAXX / 8) - w) / 2,((MAXY / 8) - h) / 2,w,h);
  117. }
  118. //===========================================================================
  119. /*
  120. =====================
  121. =
  122. = CheckKeys
  123. =
  124. =====================
  125. */
  126. void CheckKeys (void)
  127. {
  128. extern boolean autofire;
  129. if (screenfaded) // don't do anything with a faded screen
  130. return;
  131. #if 0
  132. //
  133. // pause key wierdness can't be checked as a scan code
  134. //
  135. if (Paused)
  136. {
  137. CenterWindow (8,3);
  138. US_PrintCentered ("PAUSED");
  139. VW_UpdateScreen ();
  140. // SD_MusicOff();
  141. IN_Ack();
  142. // SD_MusicOn();
  143. Paused = false;
  144. if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement
  145. }
  146. else
  147. if (Keyboard[sc_Enter]) // P = pause with no screen disruptioon
  148. {
  149. // SD_MusicOff();
  150. DisplaySMsg("PAUSED",NULL);
  151. IN_Ack();
  152. // SD_MusicOn();
  153. if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement
  154. }
  155. else
  156. if (Keyboard[sc_S])
  157. {
  158. char *Text[] = {{"Slow Mode ON"},{"Slow Mode OFF"}};
  159. SlowMode ^= 1;
  160. extravbls = SlowMode << 3;
  161. CenterWindow (8,3);
  162. US_PrintCentered (Text[SlowMode]);
  163. VW_UpdateScreen ();
  164. // SD_MusicOff();
  165. IN_Ack();
  166. // SD_MusicOn();
  167. if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement
  168. }
  169. #endif
  170. // F2 - SOUND OPTIONS
  171. //
  172. if (Keyboard[sc_F2])
  173. {
  174. int height=7;
  175. boolean ChoiceMade = false;
  176. if (AdLibPresent)
  177. height++;
  178. VW_FixRefreshBuffer();
  179. CenterWindow(22,height);
  180. US_Print( "\n 1 ) NO SOUND \n");
  181. US_Print( " 2 ) PC AUDIO \n");
  182. if (AdLibPresent)
  183. US_Print(" 3 ) ADLIB AUDIO\n");
  184. US_Print( "\n ESC) EXIT ");
  185. VW_UpdateScreen();
  186. // Switch audio device ON/OFF & load sounds if there
  187. // was a change in the device.
  188. do {
  189. if (Keyboard[1]) // ESC - Exit
  190. ChoiceMade = true;
  191. else
  192. if (Keyboard[2]) // 1 - No Sound
  193. {
  194. SD_SetSoundMode(sdm_Off);
  195. ChoiceMade = true;
  196. }
  197. else
  198. if (Keyboard[3]) // 2 - PC Audio
  199. {
  200. SD_SetSoundMode(sdm_PC);
  201. // if (oldsoundmode != sdm_PC)
  202. CA_LoadAllSounds();
  203. ChoiceMade = true;
  204. }
  205. else
  206. if ((Keyboard[4]) && AdLibPresent) // 3 - AdLib Audio
  207. {
  208. SD_SetSoundMode(sdm_AdLib);
  209. // if (oldsoundmode != sdm_AdLib)
  210. CA_LoadAllSounds();
  211. ChoiceMade = true;
  212. }
  213. } while (!ChoiceMade);
  214. tics = realtics = 1;
  215. IN_ClearKeysDown();
  216. }
  217. // F5 - CALIBRATE JOYSTICK
  218. //
  219. if (Keyboard[sc_F5])
  220. {
  221. CalibrateJoystick(0);
  222. tics = realtics = 1;
  223. IN_ClearKeysDown();
  224. }
  225. deadloop:;
  226. // ESCAPE - quits game
  227. //
  228. if ((Keyboard[sc_Escape]) || (Flags & FL_DEAD))
  229. {
  230. char ch;
  231. DisplaySMsg("Options", NULL);
  232. status_flag = S_NONE;
  233. if (Flags & FL_DEAD)
  234. {
  235. char choices[] = {sc_Escape,sc_R,sc_N,sc_Q,0};
  236. ch = DisplayMsg("Restore New Quit",choices);
  237. }
  238. else
  239. {
  240. char choices[] = {sc_Escape,sc_S,sc_R,sc_N,sc_Q,0};
  241. ch = DisplayMsg("Save Restore New Quit",choices);
  242. }
  243. DrawText(true);
  244. switch (ch)
  245. {
  246. case sc_S:
  247. if (!(Flags & FL_DEAD))
  248. Keyboard[sc_F3] = true;
  249. break;
  250. case sc_R:
  251. Keyboard[sc_F4] = true;
  252. break;
  253. case sc_N:
  254. DisplaySMsg("Starting anew", NULL);
  255. VW_WaitVBL(60);
  256. playstate = ex_resetgame;
  257. Flags &= ~FL_DEAD;
  258. break;
  259. case sc_Q:
  260. DisplaySMsg("FARE THEE WELL!", NULL);
  261. VW_WaitVBL(120);
  262. if (!Flags & FL_QUICK)
  263. VW_FadeOut();
  264. NormalScreen();
  265. FreeUpMemory();
  266. Quit(NULL);
  267. break;
  268. }
  269. tics = realtics = 1;
  270. }
  271. // F1 - DISPLAY HELP
  272. //
  273. if (Keyboard[sc_F1])
  274. {
  275. PrintHelp();
  276. #ifdef TEXT_PRESENTER
  277. extern PresenterInfo MainHelpText;
  278. VW_FadeOut();
  279. FreeUpMemory();
  280. if (!LoadPresenterScript("HELP.TXT",&MainHelpText))
  281. {
  282. VW_FadeIn();
  283. CenterWindow(30,5);
  284. US_CPrint("\nError loading HELP file.\n");
  285. US_CPrint("Press any key.");
  286. IN_Ack();
  287. VW_FadeOut();
  288. }
  289. else
  290. {
  291. VW_SetSplitScreen(200);
  292. bufferofs = displayofs = screenloc[0];
  293. VW_Bar(0,0,320,200,0);
  294. Display640();
  295. Presenter(&MainHelpText);
  296. Display320();
  297. }
  298. FreePresenterScript(&MainHelpText);
  299. #endif
  300. VW_SetSplitScreen(120);
  301. VW_SetScreen(screenloc[0],0);
  302. screenpage = 0;
  303. CacheScaleds();
  304. bufferofs = 0;
  305. RedrawStatusWindow();
  306. ThreeDRefresh();
  307. VW_FadeIn();
  308. Keyboard[sc_F1] = false;
  309. tics = realtics = 1;
  310. IN_ClearKeysDown();
  311. }
  312. // F3 - SAVE GAME
  313. //
  314. if ((Keyboard[sc_F3]) && (!(Flags & FL_DEAD)))
  315. {
  316. PreFullDisplay();
  317. GE_SaveGame();
  318. PostFullDisplay(true);
  319. tics = realtics = 1;
  320. IN_ClearKeysDown();
  321. }
  322. // F4 - LOAD GAME
  323. //
  324. if (Keyboard[sc_F4])
  325. {
  326. PreFullDisplay();
  327. if (GE_LoadGame())
  328. {
  329. loadedgame = true;
  330. playstate = ex_loadedgame;
  331. Flags &= ~FL_DEAD;
  332. lasttext = -1;
  333. PostFullDisplay(false);
  334. }
  335. else
  336. if (playstate == ex_victorious)
  337. {
  338. PostFullDisplay(false);
  339. Victory(false);
  340. IN_Ack();
  341. // gamestate.mapon++;
  342. }
  343. else
  344. PostFullDisplay(true);
  345. Keyboard[sc_F5] = false;
  346. tics = realtics = 1;
  347. IN_ClearKeysDown();
  348. }
  349. if (Flags & FL_DEAD)
  350. goto deadloop;
  351. //
  352. // F10-? debug keys
  353. //
  354. if (Keyboard[sc_BackSpace])
  355. {
  356. DebugKeys();
  357. if (MousePresent) Mouse(MDelta); // Clear accumulated mouse movement
  358. lasttimecount = TimeCount;
  359. }
  360. }
  361. //-------------------------------------------------------------------------
  362. // PreFullDisplay()
  363. //-------------------------------------------------------------------------
  364. void PreFullDisplay()
  365. {
  366. VW_FadeOut();
  367. VW_SetSplitScreen(200);
  368. bufferofs = displayofs = screenloc[0];
  369. VW_Bar(0,0,320,200,0);
  370. }
  371. //-------------------------------------------------------------------------
  372. // PostFullDisplay()
  373. //-------------------------------------------------------------------------
  374. void PostFullDisplay(boolean draw_view)
  375. {
  376. VW_SetSplitScreen(120);
  377. bufferofs = 0;
  378. RedrawStatusWindow();
  379. if (draw_view)
  380. {
  381. ThreeDRefresh();
  382. VW_FadeIn();
  383. }
  384. }
  385. //===========================================================================
  386. /*
  387. #############################################################################
  388. The objlist data structure
  389. #############################################################################
  390. objlist containt structures for every actor currently playing. The structure
  391. is accessed as a linked list starting at *player, ending when ob->next ==
  392. NULL. GetNewObj inserts a new object at the end of the list, meaning that
  393. if an actor spawn another actor, the new one WILL get to think and react the
  394. same frame. RemoveObj unlinks the given object and returns it to the free
  395. list, but does not damage the objects ->next pointer, so if the current object
  396. removes itself, a linked list following loop can still safely get to the
  397. next element.
  398. <backwardly linked free list>
  399. #############################################################################
  400. */
  401. /*
  402. =========================
  403. =
  404. = InitObjList
  405. =
  406. = Call to clear out the entire object list, returning them all to the free
  407. = list. Allocates a special spot for the player.
  408. =
  409. =========================
  410. */
  411. void InitObjList (void)
  412. {
  413. int i;
  414. for (i=0;i<MAXACTORS;i++)
  415. {
  416. objlist[i].prev = &objlist[i+1];
  417. objlist[i].next = NULL;
  418. }
  419. objlist[MAXACTORS-1].prev = NULL;
  420. objfreelist = &objlist[0];
  421. lastobj = NULL;
  422. objectcount = 0;
  423. //
  424. // give the player and score the first free spots
  425. //
  426. GetNewObj (false);
  427. player = new;
  428. #if USE_INERT_LIST
  429. inert = inertobjlist;
  430. #endif
  431. }
  432. //===========================================================================
  433. /*
  434. =========================
  435. =
  436. = GetNewObj
  437. =
  438. = Sets the global variable new to point to a free spot in objlist.
  439. = The free spot is inserted at the end of the liked list
  440. =
  441. = When the object list is full, the caller can either have it bomb out ot
  442. = return a dummy object pointer that will never get used
  443. =
  444. =========================
  445. */
  446. void GetNewObj (boolean usedummy)
  447. {
  448. if (!objfreelist)
  449. {
  450. if (usedummy)
  451. {
  452. new = &dummyobj;
  453. return;
  454. }
  455. Quit ("GetNewObj: No free spots in objlist!");
  456. }
  457. new = objfreelist;
  458. objfreelist = new->prev;
  459. memset (new,0,sizeof(*new));
  460. if (lastobj)
  461. lastobj->next = new;
  462. new->prev = lastobj; // new->next is allready NULL from memset
  463. new->active = false;
  464. lastobj = new;
  465. objectcount++;
  466. }
  467. //===========================================================================
  468. /*
  469. =========================
  470. =
  471. = RemoveObj
  472. =
  473. = Add the given object back into the free list, and unlink it from it's
  474. = neighbors
  475. =
  476. =========================
  477. */
  478. void RemoveObj (objtype *gone)
  479. {
  480. objtype **spotat;
  481. if (gone == player)
  482. Quit ("RemoveObj: Tried to remove the player!");
  483. //
  484. // fix the next object's back link
  485. //
  486. if (gone == lastobj)
  487. lastobj = (objtype *)gone->prev;
  488. else
  489. gone->next->prev = gone->prev;
  490. //
  491. // fix the previous object's forward link
  492. //
  493. gone->prev->next = gone->next;
  494. //
  495. // add it back in to the free list
  496. //
  497. gone->prev = objfreelist;
  498. objfreelist = gone;
  499. objectcount--;
  500. }
  501. #if USE_INERT_LIST
  502. //--------------------------------------------------------------------------
  503. // MoveObjToInert()
  504. //--------------------------------------------------------------------------
  505. void MoveObjToInert(objtype *obj)
  506. {
  507. if (inert == &inertobjlist[MAXINERTOBJ])
  508. return;
  509. // Transfer info needed by inert objtype
  510. //
  511. inert->x = obj->x;
  512. inert->y = obj->y;
  513. inert->size = obj->size;
  514. inert->viewx = obj->viewx;
  515. inert->tilex = obj->tilex;
  516. inert->tiley = obj->tiley;
  517. inert->state = obj->state;
  518. inert->ticcount = obj->ticcount;
  519. // Setup links between inert objects
  520. //
  521. if (inert != inertobjlist)
  522. (inert-1)->next = inert;
  523. inert->next = NULL;
  524. inert++;
  525. // Free 'real' object from list.
  526. //
  527. RemoveObj(obj);
  528. }
  529. #endif
  530. //==========================================================================
  531. /*
  532. ===================
  533. =
  534. = PollControls
  535. =
  536. ===================
  537. */
  538. void PollControls (void)
  539. {
  540. unsigned buttons;
  541. IN_ReadControl(0,&control);
  542. if (MousePresent)
  543. {
  544. Mouse(MButtons);
  545. buttons = _BX;
  546. Mouse(MDelta);
  547. mousexmove = _CX;
  548. mouseymove = _DX;
  549. if (buttons&1)
  550. control.button0 = 1;
  551. if (buttons&2)
  552. control.button1 = 1;
  553. }
  554. if (Keyboard[sc_V] || Keyboard[sc_Tab])
  555. running = true;
  556. else
  557. running = false;
  558. }
  559. //==========================================================================
  560. #if 0
  561. /*
  562. =================
  563. =
  564. = StopMusic
  565. =
  566. =================
  567. */
  568. void StopMusic(void)
  569. {
  570. int i;
  571. SD_MusicOff();
  572. for (i = 0;i < LASTMUSIC;i++)
  573. if (audiosegs[STARTMUSIC + i])
  574. {
  575. MM_SetPurge(&((memptr)audiosegs[STARTMUSIC + i]),3);
  576. MM_SetLock(&((memptr)audiosegs[STARTMUSIC + i]),false);
  577. }
  578. }
  579. //==========================================================================
  580. /*
  581. =================
  582. =
  583. = StartMusic
  584. =
  585. =================
  586. */
  587. // JAB - Cache & start the appropriate music for this level
  588. void StartMusic(void)
  589. {
  590. musicnames chunk;
  591. SD_MusicOff();
  592. chunk = TOOHOT_MUS;
  593. // if ((chunk == -1) || (MusicMode != smm_AdLib))
  594. //DEBUG control panel return;
  595. MM_BombOnError (false);
  596. CA_CacheAudioChunk(STARTMUSIC + chunk);
  597. MM_BombOnError (true);
  598. if (mmerror)
  599. mmerror = false;
  600. else
  601. {
  602. MM_SetLock(&((memptr)audiosegs[STARTMUSIC + chunk]),true);
  603. SD_StartMusic((MusicGroup far *)audiosegs[STARTMUSIC + chunk]);
  604. }
  605. }
  606. #endif
  607. //==========================================================================
  608. /*
  609. ===================
  610. =
  611. = PlayLoop
  612. =
  613. ===================
  614. */
  615. void PlayLoop (void)
  616. {
  617. char shot_color[3] = {4,9,14};
  618. int allgems[5]={GEM_DELAY_TIME, // used for Q & D comparison
  619. GEM_DELAY_TIME, // for having all gems...
  620. GEM_DELAY_TIME, // the "allgems" declaration MUST
  621. GEM_DELAY_TIME, // match the "gems" declaration in
  622. GEM_DELAY_TIME // the gametype structure!
  623. };
  624. // int originx=0;
  625. // int i=100;
  626. signed long dx,dy,radius,psin,pcos,newx,newy;
  627. int give;
  628. short objnum;
  629. signed long ox,oy,xl,xh,yl,yh,px,py,norm_dx,norm_dy;
  630. short o_radius;
  631. void (*think)();
  632. ingame = true;
  633. playstate = TimeCount = 0;
  634. gamestate.shotpower = handheight = 0;
  635. pointcount = pointsleft = 0;
  636. status_flag = S_NONE;
  637. #if 0
  638. // setup sky/ground colors and effects (based on level)
  639. //
  640. switch (gamestate.mapon)
  641. {
  642. case 255:
  643. if (!(BGFLAGS & BGF_NIGHT))
  644. {
  645. InitBgChange(3*60,sky_daytonight,-1,NULL,BGF_NIGHT);
  646. groundcolor = &gnd_colors[0];
  647. }
  648. else
  649. {
  650. skycolor = &sky_colors[0];
  651. groundcolor = &gnd_colors[0];
  652. }
  653. break;
  654. default:
  655. skycolor = &sky_colors[gamestate.mapon];
  656. groundcolor = &gnd_colors[gamestate.mapon];
  657. skytimer = groundtimer = -1;
  658. break;
  659. }
  660. #endif
  661. BGFLAGS |= BGF_NOT_LIGHTNING;
  662. skytimer = groundtimer = -1;
  663. debug_gnd = *groundcolor;
  664. debug_sky = *skycolor;
  665. RedrawStatusWindow();
  666. ThreeDRefresh();
  667. if (screenfaded)
  668. VW_FadeIn();
  669. #ifndef PROFILE
  670. fizzlein = true; // fizzle fade in the first refresh
  671. #endif
  672. TimeCount = lasttimecount = lastnuke = 0;
  673. PollControls (); // center mouse
  674. // StartMusic ();
  675. do
  676. {
  677. #ifndef PROFILE
  678. PollControls();
  679. #else
  680. control.xaxis = 1;
  681. if (++TimeCount == 300)
  682. return;
  683. #endif
  684. DisplayStatus(&status_flag);
  685. objnum=0;
  686. for (obj = player;obj;obj = obj->next)
  687. {
  688. if ((obj->active >= yes) && (!(FreezeTime && (obj!=player))))
  689. {
  690. if (obj->ticcount)
  691. {
  692. obj->ticcount-=realtics;
  693. while ( obj->ticcount <= 0)
  694. {
  695. think = obj->state->think;
  696. if (think)
  697. {
  698. statetype *oldstate=obj->state;
  699. think (obj);
  700. if (!obj->state)
  701. {
  702. RemoveObj (obj);
  703. goto nextactor;
  704. }
  705. if (obj->state != oldstate)
  706. break;
  707. }
  708. obj->state = obj->state->next;
  709. if (!obj->state)
  710. {
  711. RemoveObj (obj);
  712. goto nextactor;
  713. }
  714. if (!obj->state->tictime)
  715. {
  716. obj->ticcount = 0;
  717. goto nextactor;
  718. }
  719. if (obj->state->tictime>0)
  720. obj->ticcount += obj->state->tictime;
  721. }
  722. }
  723. think = obj->state->think;
  724. if (think)
  725. {
  726. think (obj);
  727. if (!obj->state)
  728. RemoveObj (obj);
  729. }
  730. nextactor:;
  731. }
  732. // keep a list of objects around the player for radar updates
  733. //
  734. if (obj == player)
  735. {
  736. px = player->x;
  737. py = player->y;
  738. psin = sintable[player->angle];
  739. pcos = costable[player->angle];
  740. xl = px-((long)RADAR_WIDTH<<TILESHIFT)/2;
  741. xh = px+((long)RADAR_WIDTH<<TILESHIFT)/2-1;
  742. yl = py-((long)RADAR_HEIGHT<<TILESHIFT)/2;
  743. yh = py+((long)RADAR_HEIGHT<<TILESHIFT)/2;
  744. }
  745. if (objnum > MAX_RADAR_BLIPS-2)
  746. objnum = MAX_RADAR_BLIPS-2;
  747. ox = obj->x;
  748. oy = obj->y;
  749. if ((ox >= xl) && (ox <= xh) && (oy >= yl) && (oy <= yh))
  750. {
  751. norm_dx = (dx = px-ox)>>TILESHIFT;
  752. norm_dy = (dy = oy-py)>>TILESHIFT;
  753. o_radius = IntSqrt((norm_dx * norm_dx) + (norm_dy * norm_dy));
  754. if (o_radius < RADAR_RADIUS)
  755. {
  756. newx = FixedByFrac(dy,pcos)-FixedByFrac(dx,psin);
  757. newy = FixedByFrac(dy,psin)+FixedByFrac(dx,pcos);
  758. RadarXY[objnum][0]=newx>>TILESHIFT;
  759. RadarXY[objnum][1]=newy>>TILESHIFT;
  760. // Define color to use for this object...
  761. //
  762. switch (obj->obclass)
  763. {
  764. // NO GEM NEEDED
  765. //
  766. // THE WIZARD! (YOU)
  767. //
  768. case playerobj:
  769. RadarXY[objnum++][2]=15;
  770. break;
  771. // WIZARD'S SHOTS
  772. //
  773. case pshotobj:
  774. case bigpshotobj:
  775. RadarXY[objnum++][2]=shot_color[screenpage];
  776. break;
  777. // BATS (DK GRAY)
  778. //
  779. case batobj:
  780. if (obj->active == always)
  781. RadarXY[objnum++][2]=8;
  782. break;
  783. // RABBITS (LT GRAY)
  784. //
  785. case bunnyobj:
  786. if (obj->active == always)
  787. RadarXY[objnum++][2]=7;
  788. break;
  789. // RED GEM
  790. //
  791. // EYE, RED DEMON (DK RED)
  792. //
  793. case eyeobj:
  794. case reddemonobj:
  795. if (gamestate.gems[B_RGEM-B_RGEM])
  796. if (obj->active == always)
  797. RadarXY[objnum++][2]=4;
  798. break;
  799. // RED MAGE (LT RED)
  800. //
  801. case mageobj:
  802. if (gamestate.gems[B_RGEM-B_RGEM])
  803. if (obj->active == always)
  804. RadarXY[objnum++][2]=12;
  805. break;
  806. // BLUE GEM
  807. //
  808. // SUCCUBUS (LT BLUE)
  809. //
  810. case succubusobj:
  811. if (gamestate.gems[B_BGEM-B_RGEM])
  812. if (obj->active == always)
  813. RadarXY[objnum++][2]=9;
  814. break;
  815. // WATER DRAGON (DK BLUE)
  816. //
  817. case wetobj:
  818. if (gamestate.gems[B_GGEM-B_RGEM])
  819. if (obj->active == always)
  820. RadarXY[objnum++][2]=1;
  821. break;
  822. // GREEN GEM
  823. //
  824. // GREEN TROLL (LT GREEN)
  825. //
  826. case fatdemonobj:
  827. if (gamestate.gems[B_GGEM-B_RGEM])
  828. if (obj->active == always)
  829. RadarXY[objnum++][2]=10;
  830. break;
  831. // GODESS (DK GREEN)
  832. //
  833. case godessobj:
  834. if (gamestate.gems[B_GGEM-B_RGEM])
  835. if (obj->active == always)
  836. RadarXY[objnum++][2]=2;
  837. break;
  838. // YELLOW GEM
  839. //
  840. // ANT (BROWN)
  841. //
  842. case antobj:
  843. case treeobj:
  844. if (gamestate.gems[B_YGEM-B_RGEM])
  845. if (obj->active == always)
  846. RadarXY[objnum++][2]=6;
  847. break;
  848. // SKELETON (YELLOW)
  849. //
  850. case skeletonobj:
  851. if (gamestate.gems[B_YGEM-B_RGEM])
  852. if (obj->active == always)
  853. RadarXY[objnum++][2]=14;
  854. break;
  855. // PURPLE GEM
  856. //
  857. // ZOMBIE
  858. //
  859. case zombieobj:
  860. if (gamestate.gems[B_PGEM-B_RGEM])
  861. if (obj->active == always)
  862. RadarXY[objnum++][2]=13;
  863. break;
  864. // ALL GEMS NEEDED
  865. //
  866. // NEMESIS
  867. //
  868. case grelmobj:
  869. if (!memcmp(gamestate.gems,allgems,sizeof(gamestate.gems)))
  870. if (obj->active == always)
  871. RadarXY[objnum++][2]=15;
  872. break;
  873. }
  874. }
  875. }
  876. }
  877. RadarXY[objnum][2]=-1; // Signals end of RadarXY list...
  878. #if USE_INERT_LIST
  879. if (inert != inertobjlist)
  880. for (obj=(objtype *)inertobjlist;obj;obj=obj->next)
  881. if (obj->ticcount)
  882. {
  883. obj->ticcount-=realtics;
  884. while ( obj->ticcount <= 0)
  885. {
  886. obj->state = obj->state->next;
  887. if (!obj->state)
  888. Quit("Removable object in INERT list.");
  889. if (!obj->state->tictime)
  890. {
  891. obj->ticcount = 0;
  892. goto nextactor;
  893. }
  894. if (obj->state->tictime>0)
  895. obj->ticcount += obj->state->tictime;
  896. }
  897. }
  898. #endif
  899. if (bordertime)
  900. {
  901. bordertime -= realtics;
  902. if (bordertime<=0)
  903. {
  904. bordertime = 0;
  905. VW_ColorBorder(0);
  906. }
  907. }
  908. #if 1
  909. // random lightning?
  910. //
  911. if (BGFLAGS & (BGF_NOT_LIGHTNING))
  912. {
  913. if ((scolor & 0xe0) && (!(random(20-realtics))))
  914. {
  915. BGFLAGS &= ~BGF_NOT_LIGHTNING;
  916. InitBgChange(1,sky_lightning,-1,NULL,BGF_NOT_LIGHTNING);
  917. }
  918. }
  919. // handle sky/ground color changes
  920. //
  921. if (skytimer != -1)
  922. {
  923. skytimer -= realtics;
  924. if (skytimer < 0)
  925. {
  926. skycolor++;
  927. if (*skycolor == 0xffff)
  928. {
  929. skytimer = -1;
  930. // skycolor--;
  931. skycolor = &scolor;
  932. if (groundtimer == -1)
  933. BGFLAGS |= bgflag;
  934. }
  935. else
  936. skytimer = skytimer_reset;
  937. }
  938. }
  939. if (groundtimer != -1)
  940. {
  941. groundtimer -= realtics;
  942. if (groundtimer < 0)
  943. {
  944. groundcolor++;
  945. if (*groundcolor == 0xffff)
  946. {
  947. groundtimer = -1;
  948. // groundcolor--;
  949. groundcolor = &gcolor;
  950. if (skytimer == -1)
  951. BGFLAGS |= bgflag;
  952. }
  953. else
  954. groundtimer = groundtimer_reset;
  955. }
  956. }
  957. #endif
  958. //
  959. // Handle FreezeTime counter..
  960. //
  961. if (FreezeTime)
  962. {
  963. if (FreezeTime<20*30)
  964. if ((BeepTime+=realtics)>=60)
  965. {
  966. BeepTime -= 60;
  967. SD_PlaySound(TICKSND);
  968. }
  969. if ((FreezeTime-=realtics)<=0)
  970. {
  971. FreezeTime=0;
  972. SD_PlaySound(TIMERETURNSND);
  973. DisplaySMsg(NULL,NULL);
  974. status_flag = S_NONE;
  975. }
  976. }
  977. // refresh all
  978. //
  979. ThreeDRefresh ();
  980. if (Flags & FL_DEAD)
  981. {
  982. SD_PlaySound (GAMEOVERSND);
  983. DisplaySMsg("DEAD",NULL);
  984. DrawHealth();
  985. if (gamestate.potions)
  986. {
  987. bufferofs = displayofs = screenloc[screenpage];
  988. CenterWindow(35,3);
  989. US_CPrint("\nYou should use your Cure Potions wisely\n");
  990. IN_Ack();
  991. }
  992. }
  993. // check for win
  994. //
  995. if (playstate == ex_victorious)
  996. {
  997. Victory(true);
  998. // Flags |= FL_DEAD;
  999. IN_Ack();
  1000. // gamestate.mapon++;
  1001. }
  1002. CheckKeys();
  1003. }while (!playstate);
  1004. // StopMusic ();
  1005. ingame = false;
  1006. if (bordertime)
  1007. {
  1008. bordertime = 0;
  1009. VW_ColorBorder(0);
  1010. }
  1011. if (abortgame)
  1012. abortgame = false;
  1013. }
  1014. //--------------------------------------------------------------------------
  1015. // IntSqrt() - by Master Programmer, George Leritte!
  1016. //--------------------------------------------------------------------------
  1017. int IntSqrt(long va)
  1018. {
  1019. asm mov AX, word ptr va
  1020. asm mov DX, word ptr va+2
  1021. asm mov bx,dx // {bx = integer square root of dx:ax}
  1022. asm or bx,ax // {if dx:ax=0 then return}
  1023. asm jz isq01
  1024. asm mov bx,dx
  1025. asm shl bx,1
  1026. asm or bl,ah
  1027. asm or bl,al
  1028. asm dec bx
  1029. asm add bx,dx // { initial guess}
  1030. asm jg isq10
  1031. asm inc bx // { don't return zero}
  1032. asm jg isq10
  1033. asm mov bx,7fffh
  1034. isq01:;
  1035. goto exitrout;
  1036. isq10:;
  1037. asm push ax
  1038. asm push dx
  1039. asm div bx
  1040. asm sub ax,bx
  1041. asm cmp ax,1
  1042. asm jbe isq90
  1043. asm cmp ax,-1
  1044. asm jae isq90
  1045. asm sar ax,1
  1046. asm add bx,ax
  1047. asm pop dx
  1048. asm pop ax
  1049. asm jmp isq10
  1050. isq90:;
  1051. asm pop dx
  1052. asm pop ax
  1053. exitrout:;
  1054. asm mov ax,bx
  1055. }
  1056. //-------------------------------------------------------------------------
  1057. // InitBgChange()
  1058. //-------------------------------------------------------------------------
  1059. void InitBgChange(short stimer, unsigned *scolors, short gtimer, unsigned *gcolors, byte flag)
  1060. {
  1061. skytimer_reset = skytimer = stimer;
  1062. if (scolors)
  1063. skycolor = scolors;
  1064. groundtimer_reset = groundtimer = gtimer;
  1065. if (gcolors)
  1066. groundcolor = gcolors;
  1067. bgflag = flag;
  1068. }
  1069. ////////////////////////////////////////////////////////
  1070. //
  1071. // DisplayStatus
  1072. //
  1073. // Stat_Flag - contains the type of status displayed
  1074. // -- also uses status_delay (global variable) will not
  1075. // change display until this variable is zero.
  1076. // -- heirarchy is determined by the series of if statements,
  1077. // to change it, rearrange th if statements.
  1078. //
  1079. ////////////////////////////////////////////////////////
  1080. #define MESSAGEDELAY 25
  1081. void DisplayStatus (status_flags *stat_flag)
  1082. {
  1083. status_flags temp_status;
  1084. if (*stat_flag == S_TIMESTOP)
  1085. return;
  1086. if (status_delay > 0)
  1087. {
  1088. status_delay -= realtics;
  1089. return;
  1090. }
  1091. else
  1092. status_delay = 0;
  1093. // check for a change in status from previous call
  1094. temp_status = S_VIEWING; //precaution
  1095. if (Keyboard[sc_Control] || control.button0)
  1096. temp_status = S_MISSLE;
  1097. if (Keyboard[sc_Z] && !Keyboard[sc_F10])
  1098. temp_status = S_ZAPPER;
  1099. if ((Keyboard[sc_X] && !Keyboard[sc_F10]) || Keyboard[sc_Enter])
  1100. temp_status = S_XTER;
  1101. if (control.x)
  1102. temp_status = S_TURN;
  1103. if ((Keyboard[sc_V] || Keyboard[sc_Tab]) && control.x)
  1104. temp_status = S_QTURN;
  1105. if (Keyboard[sc_Alt] && control.x)
  1106. temp_status = S_SIDESTEP;
  1107. if (control.y < 0)
  1108. temp_status = S_ADVANCE;
  1109. if (control.y > 0)
  1110. temp_status = S_RETREAT;
  1111. if (Keyboard[sc_F5])
  1112. temp_status = S_JOYSTICK;
  1113. if (Keyboard[sc_F4])
  1114. temp_status = S_RESTORING;
  1115. if (Keyboard[sc_F3])
  1116. temp_status = S_SAVING;
  1117. if (Keyboard[sc_F2])
  1118. temp_status = S_SND;
  1119. if (Keyboard[sc_F1])
  1120. temp_status = S_HELP;
  1121. if (temp_status != *stat_flag)
  1122. {
  1123. *stat_flag = temp_status;
  1124. switch (*stat_flag)
  1125. {
  1126. case S_MISSLE:
  1127. DisplaySMsg("Magick Missile", NULL);
  1128. status_delay = MESSAGEDELAY;
  1129. break;
  1130. case S_ZAPPER:
  1131. if (gamestate.bolts)
  1132. {
  1133. DisplaySMsg("Zapper", NULL);
  1134. status_delay = MESSAGEDELAY+10;
  1135. }
  1136. break;
  1137. case S_XTER:
  1138. if (gamestate.nukes)
  1139. {
  1140. DisplaySMsg("Xterminator", NULL);
  1141. status_delay = MESSAGEDELAY+5;
  1142. }
  1143. break;
  1144. case S_TURN:
  1145. DisplaySMsg("Turning", NULL);
  1146. status_delay = MESSAGEDELAY;
  1147. break;
  1148. case S_QTURN:
  1149. DisplaySMsg("Quick Turning", NULL);
  1150. status_delay = MESSAGEDELAY;
  1151. break;
  1152. case S_SIDESTEP:
  1153. DisplaySMsg("Sidestepping", NULL);
  1154. status_delay = MESSAGEDELAY;
  1155. break;
  1156. case S_ADVANCE:
  1157. DisplaySMsg("Advancing", NULL);
  1158. status_delay = MESSAGEDELAY;
  1159. break;
  1160. case S_RETREAT:
  1161. DisplaySMsg("Retreating", NULL);
  1162. status_delay = MESSAGEDELAY;
  1163. break;
  1164. case S_JOYSTICK:
  1165. DisplaySMsg("Adjusting Joystick", NULL);
  1166. break;
  1167. case S_RESTORING:
  1168. DisplaySMsg("Restoring", NULL);
  1169. break;
  1170. case S_SAVING:
  1171. DisplaySMsg("Saving", NULL);
  1172. break;
  1173. case S_SND:
  1174. DisplaySMsg("Select Sound", NULL);
  1175. break;
  1176. case S_HELP:
  1177. DisplaySMsg("Getting Help", NULL);
  1178. break;
  1179. case S_VIEWING:
  1180. DisplaySMsg("Viewing", NULL);
  1181. break;
  1182. }
  1183. bufferofs = displayofs = screenloc[screenpage];
  1184. }
  1185. }