MAIN.C 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. #include "horror.h"
  2. #include "fire.h"
  3. /****************************************************************************
  4. ** Jump parametrics
  5. ****************************************************************************/
  6. #define kCrouchTime 45 // ticks to attain highest jump
  7. #define kTimeToApex 90 // ticks to attain apex
  8. #define kCrouchDist (12 << 8) // how far to crouch before jumping
  9. #define kMaxJumpVel (kTimeToApex * kNormalGravity / 100)
  10. #define kJumpAccel (kMaxJumpVel / kCrouchTime)
  11. #define kDuckVel (kCrouchDist / kCrouchTime)
  12. /****************************************************************************
  13. ** Player status
  14. ****************************************************************************/
  15. short gHealth = 100;
  16. short gDead = FALSE;
  17. short gJumping = FALSE;
  18. short gCrouching = FALSE;
  19. /****************************************************************************
  20. ** Interface status
  21. ****************************************************************************/
  22. short gViewStyle = kViewNormal;
  23. short gHasCompass = TRUE;
  24. short gCompassUp = FALSE;
  25. short gPaused = FALSE;
  26. short gExit = FALSE;
  27. short gMenuMode = !0;
  28. int gRandom; // reset every frame
  29. char gStatusShade = 0;
  30. short startstate[] = {0,0,5,0,0,0};
  31. short firearm=0, firestate=0, firetimer=0;
  32. /****************************************************************************
  33. ** TEMPORARY GLOBALS
  34. ****************************************************************************/
  35. char boardfilename[20];
  36. short lastsectnum;
  37. /****************************************************************************
  38. ** ProcessIO - process keyboard i/o
  39. **
  40. ** ARGUMENTS:
  41. ** none
  42. **
  43. ** RETURNS:
  44. ** none
  45. ****************************************************************************/
  46. void ProcessIO(void)
  47. {
  48. static short doubvel;
  49. static long springVelocity = 0;
  50. // temp handling for escape key
  51. if (keystatus[kKeyEscape] > 0) {
  52. gExit = TRUE;
  53. return;
  54. }
  55. // PLAYER IS DEAD?
  56. if (gDead) {
  57. if (keystatus[kKeySpace] > 0) {
  58. gDead = FALSE;
  59. gHealth = 100;
  60. keystatus[kKeySpace] = 0;
  61. }
  62. return;
  63. }
  64. #if 0
  65. // COMPASS TOGGLE
  66. if (keystatus[ kKeyC ] > 0) {
  67. if (gHasCompass) {
  68. gCompassUp = BOOL(!gCompassUp);
  69. }
  70. keystatus[ kKeyC ] = 0;
  71. }
  72. #endif
  73. // FIRING & WEAPON SELECTION
  74. if (firestate == startstate[firearm]) {
  75. if (keystatus[kKeyLCtrl] > 0) {
  76. firestate++;
  77. }
  78. else if (keystatus[kKey1] > 0) {
  79. firearm = 0;
  80. firestate = startstate[firearm];
  81. }
  82. else if (keystatus[kKey2] > 0) {
  83. firearm = 1;
  84. firestate = startstate[firearm];
  85. }
  86. else if (keystatus[kKey3] > 0) {
  87. firearm = 2;
  88. firestate = startstate[firearm];
  89. }
  90. else if (keystatus[kKey4] > 0) {
  91. firearm = 3;
  92. firestate = startstate[firearm];
  93. }
  94. else if (keystatus[kKey5] > 0) {
  95. firearm = 4;
  96. firestate = startstate[firearm];
  97. }
  98. else if (keystatus[kKey6] > 0) {
  99. firearm = 5;
  100. firestate = startstate[firearm];
  101. }
  102. }
  103. // PLAYER PUSHED SOMETHING
  104. if (keystatus[kKeySpace] > 0) {
  105. P_Push();
  106. keystatus[kKeySpace] = 0;
  107. }
  108. // CHANGE HORIZON
  109. if ((keystatus[0x4a] > 0) && (horiz >= 8)) horiz -= 8; //-
  110. if ((keystatus[0x4e] > 0) && (horiz <= 180)) horiz += 8; //+
  111. if (keystatus[0x4C] > 0) {
  112. horiz = 100;
  113. keystatus[0x4C] = 0;
  114. }
  115. // CHANGE PARALLAX SKY TYPE
  116. if (keystatus[0x19] > 0) //P
  117. {
  118. keystatus[0x19] = 0;
  119. parallaxtype++;
  120. if (parallaxtype > 2) parallaxtype = 0;
  121. }
  122. // CHANGE VISIBILITY
  123. if (keystatus[0x2f] > 0) {
  124. keystatus[0x2f] = 0;
  125. visibility++;
  126. if (visibility == 17)
  127. visibility = 5;
  128. }
  129. // PROCESS DIRECTIONAL MOVEMENT
  130. if (angvel != 0) {
  131. //ang += angvel * constant
  132. //ENGINE calculates angvel for you
  133. doubvel = lockspeed;
  134. //Left shift makes turn velocity 50% faster
  135. if (keystatus[kKeyLShift] > 0)
  136. doubvel += (lockspeed>>1);
  137. ang += ((angvel*doubvel)>>5);
  138. ang = (ang+2048)&2047;
  139. }
  140. doubvel = lockspeed;
  141. //Left shift doubles forward velocity
  142. if (keystatus[0x2a] > 0)
  143. doubvel += lockspeed;
  144. //vel = forward velocity
  145. if (vel != 0) {
  146. //Change posx/posy with ang & clip
  147. clipmove( &posx, &posy, &posz, &cursectnum,
  148. (long)(vel * doubvel * sintable[(ang + 2560) & 2047]) >> 4,
  149. (long)(vel * doubvel * sintable[ang & 2047]) >> 4, 128L);
  150. }
  151. //svel = strafing velocity
  152. if (svel != 0) {
  153. //Change posx/posy with ang & clip
  154. clipmove( &posx, &posy, &posz, &cursectnum,
  155. (long)(svel * doubvel * sintable[ang & 2047]) >> 4,
  156. (long)(svel * doubvel * sintable[(ang + 1536) & 2047]) >> 4, 128L);
  157. }
  158. // LeftAlt: PLAYER IS JUMPING
  159. if (keystatus[kKeyLAlt] > 0) {
  160. if (!gJumping) {
  161. springVelocity = 0;
  162. gJumping = TRUE;
  163. }
  164. if (springVelocity < kMaxJumpVel) {
  165. heightofffloor -= lockspeed * kDuckVel;
  166. springVelocity += lockspeed * kJumpAccel;
  167. }
  168. }
  169. else if (gJumping) {
  170. if (posz > sector[cursectnum].floorz - kNormHeightOffFloor) {
  171. if (hvel > 0) hvel = 0;
  172. hvel -= springVelocity;
  173. /* this is a kludge here because Ken's engine doesn't properly use
  174. * the value in hvel when posz is below heightofffloor. */
  175. posz = sector[cursectnum].floorz - heightofffloor - 1;
  176. }
  177. gJumping = FALSE;
  178. }
  179. // 'Z': PLAYER IS DUCKING
  180. if (keystatus[0x2c] > 0) {
  181. heightofffloor -= lockspeed * kDuckVel;
  182. //Either shift key
  183. if ((keystatus[0x2a]|keystatus[0x36]) > 0) {
  184. heightofffloor -= lockspeed * kDuckVel;
  185. }
  186. gJumping = FALSE;
  187. gCrouching = TRUE;
  188. }
  189. else if (gCrouching) {
  190. gCrouching = FALSE;
  191. heightofffloor = kNormHeightOffFloor;
  192. }
  193. if (!gJumping && !gCrouching && hvel > 0) {
  194. heightofffloor = kNormHeightOffFloor;
  195. }
  196. P_TransitSectors(); // entry/exit sector triggers
  197. P_GetItems(); // get items in sector
  198. }
  199. /****************************************************************************
  200. ** Draw3DScreen
  201. **
  202. ** ARGUMENTS:
  203. ** none
  204. **
  205. ** RETURNS:
  206. ** none
  207. ****************************************************************************/
  208. void Draw3DScreen(void)
  209. {
  210. short i, j, isprite, dang;
  211. struct spritetype *pSprite;
  212. drawrooms();
  213. // reset picnum for multi-face sprites
  214. for (i=0; i<spritesortcnt; i++)
  215. {
  216. if ((isprite = thesprite[i]) >= 0) {
  217. pSprite = &sprite[isprite];
  218. switch ( pSprite->tag )
  219. {
  220. case kTagGoldRing:
  221. dang = getangle(pSprite->x-posx,pSprite->y-posy);
  222. j = (((dang + 64) & kAngleMask) << 4) / 1365;
  223. if (j <= 6) {
  224. pSprite->picnum = kAnmGoldRing + j;
  225. pSprite->cstat |= kSpriteFlipX;
  226. } else if (j <= 12) {
  227. pSprite->picnum = kAnmGoldRing + 12 - j;
  228. pSprite->cstat &= ~kSpriteFlipX;
  229. }
  230. break;
  231. case kTagGargoyle:
  232. break;
  233. case kTagPlayer1:
  234. sprite[isprite].picnum = kInvisible;
  235. break;
  236. }
  237. }
  238. }
  239. drawmasks();
  240. }
  241. /****************************************************************************
  242. ** DrawStatus
  243. **
  244. ** ARGUMENTS:
  245. ** none
  246. **
  247. ** RETURNS:
  248. ** none
  249. ****************************************************************************/
  250. void DrawStatus(void)
  251. {
  252. signed char gunshade;
  253. short i, daang, hitsect, hitwall=-1, hitsprite=-1;
  254. long hitx, hity, hitz, daz;
  255. short damage;
  256. // set the weapon shade
  257. gunshade = 0;
  258. #if 0
  259. gunshade = sector[cursectnum].floorshade;
  260. if (gunshade < 0) {
  261. gunshade = 0;
  262. } else {
  263. gunshade &= 31;
  264. }
  265. #endif
  266. switch (firestate) {
  267. // PISTOL
  268. case 0:
  269. overwritesprite(135,134,kAnmPistol,gunshade,0);
  270. break;
  271. case 1:
  272. case 3:
  273. if (firestate == 1) {
  274. if (firetimer == 0) {
  275. visibility++;
  276. } else {
  277. visibility--;
  278. }
  279. }
  280. overwritesprite(105,134-20,kAnmPistol+1,visibility,0);
  281. if ((firestate == 1) && (firetimer==0)) {
  282. PlaySound(kPISTOL,255);
  283. overwritesprite(160,114,kAnmPistolFlash,0,1);
  284. daang = ((ang + (gRandom & 63) + 2048 - 32 ) & 2047);
  285. daz = ((100 - horiz) * 2621);
  286. daz += (((((long)rand()) & 32767L) - 16384L) << 1);
  287. hitscan(posx, posy, posz, cursectnum, //Start position
  288. sintable[(daang + 2560) & 2047], //X vector of 3D ang
  289. sintable[(daang + 2048) & 2047], //Y vector of 3D ang
  290. daz, //Z vector of 3D ang
  291. &hitsect, &hitwall, &hitsprite, &hitx, &hity, &hitz);
  292. //A_NoiseAlert(hitsect);
  293. if (hitsprite > -1) {
  294. damage = ((gRandom % 8) + 1) * 2;
  295. FX_TriggerSprite(hitsprite,kSpriteImpact,&damage);
  296. // P_DamageSprite(hitsprite,(gRandom%8+1)*2);
  297. }
  298. else if (hitwall > -1) {
  299. FX_SpawnImpact(hitsect,hitx,hity,hitz,kTagPuff);
  300. if (wall[hitwall].tag & kWallImpact) {
  301. FX_TriggerWall(hitwall,kWallImpact, NULL);
  302. }
  303. }
  304. else if (sector[hitsect].tag & kSectImpact) {
  305. FX_TriggerSector(hitsect,kSectImpact, NULL);
  306. }
  307. }
  308. break;
  309. case 2:
  310. overwritesprite(105,134-41,kAnmPistol+2,visibility,0);
  311. break;
  312. case 4:
  313. overwritesprite(135,134,kAnmPistol,visibility,0);
  314. firestate = startstate[firearm];
  315. firetimer = 0;
  316. break;
  317. // SHOTGUN
  318. case 5:
  319. overwritesprite(160,165,kAnmShotgun,gunshade,1);
  320. break;
  321. case 6:
  322. if (firetimer==0) {
  323. visibility++;
  324. PlaySound(kSHOTGUN,255);
  325. for (i=0;i<5;i++)
  326. {
  327. daang = ((ang + (rand() & 63) + 2048 - 32 ) & 2047);
  328. daz = ((100 - horiz) * 2621);
  329. daz += (((((long)rand()) & 32767L) - 16384L) << 1);
  330. hitscan(posx, posy, posz, cursectnum, //Start position
  331. sintable[(daang + 2560) & 2047], //X vector of 3D ang
  332. sintable[(daang + 2048) & 2047], //Y vector of 3D ang
  333. daz, //Z vector of 3D ang
  334. &hitsect, &hitwall, &hitsprite, &hitx, &hity, &hitz);
  335. //A_NoiseAlert(hitsect);
  336. if (hitsprite > -1) {
  337. damage = ((gRandom % 8) + 1) * 2;
  338. FX_TriggerSprite(hitsprite,kSpriteImpact,&damage);
  339. // P_DamageSprite(hitsprite,(gRandom%8+1)*2);
  340. }
  341. else if (hitwall > -1) {
  342. FX_SpawnImpact(hitsect,hitx,hity,hitz,kTagPuff);
  343. if (wall[hitwall].tag & kWallImpact) {
  344. // COULD ADD WALL DAMAGE HERE
  345. FX_TriggerWall(hitwall,kWallImpact,NULL);
  346. }
  347. }
  348. else if (sector[hitsect].tag & kSectImpact) {
  349. // COULD ADD SECTOR DAMAGE HERE
  350. FX_TriggerSector(hitsect,kSectImpact, NULL);
  351. }
  352. }
  353. } else {
  354. visibility--;
  355. }
  356. overwritesprite(160,170,kAnmShotgun,visibility,1);
  357. overwritesprite(163,125,kAnmShotgun+4,0,1);
  358. break;
  359. case 7:
  360. overwritesprite(160,170,kAnmShotgun,visibility,1);
  361. overwritesprite(163,125,kAnmShotgun+5,0,1);
  362. break;
  363. case 8:
  364. case 12:
  365. overwritesprite(80-24,100-41,kAnmShotgun+1,visibility,0);
  366. if (firestate == 12) {
  367. firestate = startstate[firearm];
  368. firetimer = 0;
  369. }
  370. break;
  371. case 9:
  372. case 11:
  373. overwritesprite(80-24,100-20,kAnmShotgun+2,visibility,0);
  374. break;
  375. case 10:
  376. if (firetimer==0) PlaySound(kSHOTCOCK,255);
  377. overwritesprite(80,80,kAnmShotgun+3,visibility,0);
  378. break;
  379. }
  380. // advance the firing state, reset firing timer
  381. if (firestate != startstate[firearm]) {
  382. if (++firetimer > 1) {
  383. firestate++;
  384. firetimer=0;
  385. }
  386. }
  387. // draw the compass
  388. #if 0
  389. if (gHasCompass && gCompassUp) {
  390. overwritesprite(160, YDIM-60, kCompass, visibility, 1);
  391. }
  392. if (gViewStyle == kViewFullScreen) {
  393. overwritesprite(0, YDIM-tilesizy[kStatusFace],
  394. kStatusFace, gStatusShade, 0);
  395. overwritesprite(XDIM-tilesizx[kStatusCompass], YDIM-tilesizy[kStatusCompass],
  396. kStatusCompass + (((ang + kAngle90) & kAngleMask) >> 8), gStatusShade, 0);
  397. }
  398. #endif
  399. }
  400. /****************************************************************************
  401. ** main - it all starts here...
  402. ****************************************************************************/
  403. int main(int argc, char *argv[])
  404. {
  405. UBYTE *CLU[4];
  406. InstallBuild();
  407. GetArgs(argc,argv); // also get map from command-line
  408. InstallSound();
  409. CLU[0] = LoadFile( "red.clu" );
  410. CLU[1] = LoadFile( "green.clu" );
  411. CLU[2] = LoadFile( "blue.clu" );
  412. CLU[3] = LoadFile( "grey.clu" );
  413. // add error checks
  414. FireInit( 128 ); // create 128x128 combustion chamber
  415. if (loadboard(boardfilename) == -1) {
  416. Abendf( "Board \"%s\" not found.\n", boardfilename );
  417. }
  418. loadpics("tiles000.art");
  419. FX_InitPanning();
  420. FX_InitLights();
  421. FX_InitSprites();
  422. FX_InitAlways();
  423. scrSetGameMode();
  424. SetViewStyle(kViewFullScreen);
  425. while (gExit == FALSE)
  426. {
  427. gRandom = rand();
  428. FireProcess();
  429. FireUpdateTile( CLU[0], (UBYTE *)waloff[ kAnmRedFire ] );
  430. FireUpdateTile( CLU[1], (UBYTE *)waloff[ kAnmGreenFire ] );
  431. FireUpdateTile( CLU[2], (UBYTE *)waloff[ kAnmBlueFire ] );
  432. FireUpdateTile( CLU[3], (UBYTE *)waloff[ kAnmGreyFire ] );
  433. lastsectnum = cursectnum;
  434. Draw3DScreen();
  435. ProcessIO();
  436. if (gPaused == FALSE) {
  437. FX_DoPanning();
  438. FX_DoLights();
  439. FX_DoAlways();
  440. // other effects here
  441. }
  442. engineinput();
  443. DrawStatus();
  444. FX_MoveSprites();
  445. nextpage();
  446. }
  447. RemoveBuild();
  448. FireDeinit();
  449. #ifdef DEBUG
  450. showengineinfo();
  451. #endif
  452. return 0;
  453. }