Advertisement
Guest User

Untitled

a guest
Mar 19th, 2012
232
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 29.01 KB | None | 0 0
  1. //NK_PHYS.C
  2.  
  3. #include "NK_DEF.H"
  4.  
  5. //Does all the tileclipping, general movement
  6. // contains some generic sprite collision and draw funcs
  7. // This is reversed directly from Keen5
  8.  
  9. // Tile (T) = 16 Pixels (Px) = 256 Map Units (MU)
  10.  
  11.  
  12. //===========================================================================
  13.  
  14. int SlopeDisp[8][16] =
  15. {
  16. { 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100 },
  17. { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
  18. { 0x0, 0x8, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78 },
  19. { 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, 0xd8, 0xe0, 0xe8, 0xf0, 0xf8 },
  20. { 0x0, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 },
  21. { 0x78, 0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40, 0x38, 0x30, 0x28, 0x20, 0x18, 0x10, 0x08, 0x0 },
  22. { 0xF8, 0xF0, 0xE8, 0xE0, 0xD8, 0xD0, 0xC8, 0xC0, 0xB8, 0xB0, 0xA8, 0xA0, 0x98, 0x90, 0x88, 0x80 },
  23. { 0xF0, 0xE0, 0xD0, 0xC0, 0xB0, 0xA0, 0x90, 0x80, 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x0 }
  24. };
  25.  
  26. Vectrect KeenClip;
  27. int KeenClipXMid;
  28. Rect KeenBox;
  29. unsigned KeenBoxXMid;
  30. Rect KeenBoxT;
  31. unsigned KeenBoxTXMid;
  32. Vector KeenVel;
  33. int KeenPushedHorz;
  34.  
  35. void UpdateYPos(objtype *o, int dy);
  36. void UpdateXPos(objtype *o, int dx);
  37. void MoveDown(objtype *o);
  38. void MoveUp(objtype *o);
  39. void SetOnSlope(objtype *o);
  40. void MoveOutOfTileHorz(objtype *o);
  41. int CheckIfStuck(objtype *o);
  42. void UpdateHitbox(objtype *o);
  43.  
  44. void NormalClip(objtype *o);
  45. void FullClipToWalls(objtype *o);
  46. void SimpleClip(objtype *o);
  47.  
  48. void PushHorz(objtype *o1, objtype *o2);
  49. void PushVert(objtype *o1, objtype *o2);
  50.  
  51. int TimeAction(objtype *o, int time);
  52. void DoAction(objtype *o);
  53. void CheckGround(objtype *o, ACTION *a);
  54. void CheckGround2(objtype *o, ACTION *a);
  55.  
  56. boolean ObjectVisible(objtype *o);
  57. //===========================================================================
  58. /*
  59. ============================
  60. =
  61. = UpdateYPos, UpdateXPos
  62. =
  63. = Move object by dy, dx MU
  64. =
  65. ============================
  66. */
  67.  
  68. // rechecked -- perfect
  69. void UpdateYPos(objtype *o, int dy)
  70. {
  71. o->pos.y += dy;
  72. o->box.ul.y += dy;
  73. o->box.lr.y += dy;
  74. o->boxT.ul.y = MU2TILE(o->box.ul.y);
  75. o->boxT.lr.y = MU2TILE(o->box.lr.y);
  76. }
  77.  
  78. // rechecked -- perfect
  79. void UpdateXPos(objtype *o, int dx)
  80. {
  81. o->pos.x += dx;
  82. o->box.ul.x += dx;
  83. o->box.lr.x += dx;
  84. o->boxT.ul.x = MU2TILE(o->box.ul.x);
  85. o->boxT.lr.x = MU2TILE(o->box.lr.x);
  86. }
  87.  
  88. /*
  89. ============================
  90. =
  91. = MoveDown / MoveUp
  92. =
  93. = Move object down/up and check sloped tile collisions
  94. = We have just moved across tileboundaries (likely)
  95. =
  96. ============================
  97. */
  98.  
  99. // rechecked -- perfect
  100. // Moving across boundaries as per the situation described in "NormalClip"
  101. void MoveDown(objtype *o)
  102. {
  103. int dx, dy, x_px, slope, topflag; // change in MU, tile PX
  104. int far *tile;
  105.  
  106. // Get fgtile one above the new bottom;
  107. // no move if wall left at tile or tile-1
  108. tile = (int far *)MAPSPOT_FP(0,o->boxT.lr.y-1,FGPLANE);
  109.  
  110. // Check if object is running into a wall above the tile we came from
  111. // If so, then don't move it up.
  112. if (o->xmotion == motion_Right)
  113. {
  114. //move right
  115. x_px = 0;
  116. tile += o->boxT.lr.x;
  117. dx = o->box.lr.x - o->boxXmid;
  118. if (TI_FGLeft(*(tile-map_width_T)) || TI_FGLeft(*tile))
  119. return;
  120. }
  121. else
  122. {
  123. //do left
  124. x_px = 15;
  125. tile += o->boxT.ul.x;
  126. dx = o->box.ul.x - o->boxXmid;
  127. if (TI_FGRight(*(tile-map_width_T)) || TI_FGRight(*tile))
  128. return;
  129. }
  130.  
  131. if (TI_FGTop(*tile))
  132. return;
  133.  
  134. topflag = TI_FGTop(*(tile+=map_width_T));
  135.  
  136. // move the object horizontally, and place it above the slope
  137. if (topflag == TF_FLAT)
  138. {
  139. slope = SlopeDisp[(topflag & 7)][x_px];
  140. dy = TILE2MU(o->boxT.lr.y) + slope - 1 - o->box.lr.y;
  141. if (dy <= 0 && -KeenClip.lr.y <= dy)
  142. {
  143. o->topflags = topflag;
  144. UpdateYPos(o, dy);
  145. UpdateXPos(o, dx);
  146. }
  147. }
  148. }
  149.  
  150.  
  151. // rechecked -- perfect
  152. void MoveUp(objtype *o)
  153. {
  154. int dy, x_px, slope, botflag; // change in MU, tile PX
  155. int far *tile;
  156.  
  157. // Get fgtile one below ul; no move if wall left at tile or tile-1
  158. tile = (int far *)MAPSPOT_FP(0,o->boxT.ul.y+1,FGPLANE);
  159.  
  160. if (o->xmotion == motion_Right)
  161. {
  162. //move Right
  163. x_px = 0;
  164. tile += o->boxT.lr.x;
  165. if (TI_FGLeft(*(tile+map_width_T)) || TI_FGLeft(*(tile+2*map_width_T)))
  166. return;
  167. }
  168. else
  169. {
  170. //move Left
  171. x_px = 15;
  172. tile += o->boxT.ul.x;
  173. if (TI_FGRight(*(tile+map_width_T)) || TI_FGRight(*(tile+2*map_width_T)))
  174. return;
  175. }
  176.  
  177. if (TI_FGBot(*tile))
  178. return;
  179.  
  180. botflag = TI_FGBot(*(tile-=map_width_T));
  181. if (botflag)
  182. {
  183. slope = SlopeDisp[botflag & 7][x_px];
  184. dy = TILE2MU(o->boxT.ul.y+1) - slope - o->box.ul.y;
  185. if (dy >= 0 && -KeenClip.ul.y >= dy)
  186. {
  187. o->botflags = botflag;
  188. UpdateYPos(o, dy);
  189. }
  190. }
  191. }
  192.  
  193.  
  194. // move the object VERTICALLY on top of top slope or under bottom slope
  195. // rechecked -- perfect
  196. void SetOnSlope(objtype *o)
  197. {
  198. int dy, varE, slope, flag, i;
  199. unsigned x_px;
  200. int far *t;
  201.  
  202. // x_px = distance in px from left edge of tile of midpoint
  203. x_px = (o->boxXmid & 0xF0) >> 4;
  204.  
  205. /* Set one pixel atop sloped floor */
  206. // varE = horz + vert distance moved this frame plus one pixel
  207. varE = -ABS(KeenClipXMid) - KeenClip.lr.y - 16;
  208. t = (int far *)MAPSPOT_FP(o->boxTXmid, KeenBoxT.lr.y-1, FGPLANE);
  209.  
  210. /* Check the tile above the midpoint and on the new midpoint */
  211. for (i = KeenBoxT.lr.y-1; o->boxT.lr.y >= i; i++, t += map_width_T)
  212. {
  213. flag = TI_FGTop(*t);
  214.  
  215. // ignore empty tiles
  216. if (flag == TF_NOT)
  217. continue;
  218.  
  219. // get the y pixel displacement at the new midopint
  220. slope = SlopeDisp[flag&7][x_px];
  221.  
  222. // dy is distance needed to get out from under slope at new midpoint
  223. dy = TILE2MU(i) + slope - 1 - o->box.lr.y;
  224.  
  225. // if dy is up, AND the x distance covered (PLUS one pixel)
  226. // is greater than y-delta between dest y and hitbox start, then move up
  227. if (dy < 0 && dy >= varE)
  228. {
  229. o->topflags = flag;
  230. UpdateYPos(o, dy);
  231. return;
  232. }
  233. }
  234.  
  235. /* Set under sloped ceiling */
  236. varE = ABS(KeenClipXMid) - KeenClip.ul.y + 16;
  237. t = (int far *)MAPSPOT_FP(o->boxTXmid, KeenBoxT.ul.y+1, FGPLANE);
  238.  
  239. for (i = KeenBoxT.ul.y+1; o->boxT.ul.y <= i; i--, t-= map_width_T)
  240. {
  241. flag = TI_FGBot(*t);
  242. if (flag == BF_NOT)
  243. continue;
  244.  
  245. slope = SlopeDisp[flag&7][x_px];
  246. dy = TILE2MU(i+1) - slope - o->box.ul.y;
  247.  
  248. if (dy > 0 && dy <= varE && (KeenVel.y + dy < 0x100) &&
  249. (KeenVel.y + dy > -0x100))
  250. {
  251. o->botflags = flag;
  252. UpdateYPos(o, dy);
  253. }
  254. }
  255. }
  256.  
  257. // if horz edges of object inside a blocking tile, move outisde
  258. // rechecked -- perfect
  259. void MoveOutOfTileHorz(objtype *o)
  260. {
  261. int far *t;
  262. int y0, y1, ty;
  263.  
  264. y0 = o->boxT.ul.y;
  265. if (o->botflags > BF_FLAT)
  266. y0++;
  267.  
  268. y1 = o->boxT.lr.y;
  269. if (o->topflags > TF_FLAT)
  270. y1--;
  271.  
  272. for (ty = y0; ty <= y1; ty++)
  273. {
  274. t = (int far *)MAPSPOT_FP(o->boxT.ul.x, ty, FGPLANE);
  275. o->rightflags = TI_FGRight(*t);
  276. if (o->rightflags)
  277. {
  278. UpdateXPos(o, TILE2MU(o->boxT.ul.x+1) - o->box.ul.x);
  279. return;
  280. }
  281. }
  282.  
  283. for (ty = y0; ty <= y1; ty++)
  284. {
  285. t = (int far *)MAPSPOT_FP(o->boxT.lr.x, ty, FGPLANE);
  286. o->leftflags = TI_FGLeft(*t);
  287. if (o->leftflags)
  288. {
  289. UpdateXPos(o, TILE2MU(o->boxT.lr.x) - 1 - o->box.lr.x);
  290. return;
  291. }
  292. }
  293. }
  294.  
  295. /* Checks if object is stuck in a wall */
  296. int CheckIfStuck(objtype *o)
  297. {
  298. int nextrowdist, tx, ty;
  299. int far *t;
  300.  
  301. t = (int far *)MAPSPOT_FP(o->boxT.ul.x, o->boxT.ul.y, FGPLANE);
  302.  
  303. nextrowdist = map_width_T - (o->boxT.lr.x - o->boxT.ul.x + 1);
  304.  
  305. for (ty = o->boxT.ul.y; ty <= o->boxT.lr.y; ty++)
  306. {
  307. for(tx = o->boxT.ul.x; tx <= o->boxT.lr.x; tx++)
  308. {
  309. if (TI_FGTop(*t) || TI_FGBot(*t) || TI_FGLeft(*t) || TI_FGRight(*t))
  310. return 0;
  311. t++;
  312. }
  313. t+=nextrowdist;
  314. }
  315.  
  316. return 1;
  317. }
  318.  
  319. // no xrefs here; skipping for nwo
  320. #if 00
  321. sub_196B3(objtype *o, int arg2) {
  322.  
  323. if (o->xmotion > motion_None)
  324. {
  325. ... looks like changing a object chunk?
  326. arg2 is some sort of struct*?
  327. }
  328. #endif
  329.  
  330. void UpdateHitbox(objtype *o)
  331. {
  332. spritetabletype far *sprhead_p;
  333.  
  334. sprhead_p = spritetable + o->chunk-STARTSPRITES;
  335. o->box.ul.x = o->pos.x + sprhead_p->xl;
  336. o->box.lr.x = o->pos.x + sprhead_p->xh;
  337. o->box.ul.y = o->pos.y + sprhead_p->yl;
  338. o->box.lr.y = o->pos.y + sprhead_p->yh;
  339. o->boxXmid = (o->box.lr.x-o->box.ul.x)/2 + o->box.ul.x;
  340. }
  341.  
  342. // rechecked 2x -- good
  343. void NormalClip(objtype *o)
  344. {
  345. unsigned xpos_0, ypos_0;
  346. boolean notonplatform;
  347. spritetabletype far *sprhead_p;
  348.  
  349. xpos_0 = o->pos.x;
  350. ypos_0 = o->pos.y;
  351. notonplatform = false;
  352.  
  353. /* Stick to slopes */
  354. if (o->action->change_v)
  355. {
  356. if (o->topflags == TF_PLATFORM)
  357. {
  358. KeenVel.y = 145;
  359. }
  360. else
  361. {
  362. if (KeenVel.x > 0)
  363. KeenVel.y = KeenVel.x + 16;
  364. else
  365. KeenVel.y = -KeenVel.x + 16;
  366. notonplatform = true;
  367. }
  368. }
  369.  
  370. /* Set Max Vel */
  371. if (KeenVel.x > 239)
  372. KeenVel.x = 239;
  373. else if (KeenVel.x < -239)
  374. KeenVel.x = -239;
  375.  
  376. if (KeenVel.y > 255)
  377. KeenVel.y = 255;
  378. else if (KeenVel.y < -239)
  379. KeenVel.y = -239;
  380.  
  381. o->pos.x += KeenVel.x;
  382. o->pos.y += KeenVel.y;
  383.  
  384. o->draw = true;
  385. if (o->chunk)
  386. {
  387. /* Set the temp box coords */
  388. sprhead_p = spritetable + (o->chunk - STARTSPRITES);
  389. KeenBoxT.ul.x = o->boxT.ul.x;
  390. KeenBoxT.lr.x = o->boxT.lr.x;
  391. KeenBoxT.ul.y = o->boxT.ul.y;
  392. KeenBoxT.lr.y = o->boxT.lr.y;
  393. KeenBoxTXMid = o->boxTXmid;
  394. KeenBox.ul.x = o->box.ul.x;
  395. KeenBox.lr.x = o->box.lr.x;
  396. KeenBox.ul.y = o->box.ul.y;
  397. KeenBox.lr.y = o->box.lr.y;
  398. KeenBoxXMid = o->boxXmid;
  399.  
  400. /* Update object box using spritehead */
  401. o->box.ul.x = o->pos.x + sprhead_p->xl;
  402. o->box.lr.x = o->pos.x + sprhead_p->xh;
  403. o->box.ul.y = o->pos.y + sprhead_p->yl;
  404. o->box.lr.y = o->pos.y + sprhead_p->yh;
  405. o->boxXmid = (o->box.lr.x-o->box.ul.x)/2 + o->box.ul.x;
  406. o->boxT.ul.x = MU2TILE(o->box.ul.x);
  407. o->boxT.lr.x = MU2TILE(o->box.lr.x);
  408. o->boxT.ul.y = MU2TILE(o->box.ul.y);
  409. o->boxT.lr.y = MU2TILE(o->box.lr.y);
  410. o->boxTXmid = MU2TILE(o->boxXmid);
  411.  
  412. /* Do Sloped Tile Checking */
  413. o->leftflags = o->botflags = o->rightflags = o->topflags = 0;
  414. if (o->clipping)
  415. {
  416. // KeenClip is frame delta for object box coordinates
  417. KeenClip.ul.x = o->box.ul.x - KeenBox.ul.x;
  418. KeenClip.lr.x = o->box.lr.x - KeenBox.lr.x;
  419. KeenClip.ul.y = o->box.ul.y - KeenBox.ul.y;
  420. KeenClip.lr.y = o->box.lr.y - KeenBox.lr.y;
  421. KeenClipXMid = o->boxXmid - KeenBoxXMid;
  422.  
  423. // Try to set on or under a slope, but...
  424. SetOnSlope(o);
  425.  
  426. // ... If the necessary delta in y position from start to atop/under slope
  427. // is more than the (x-delta + one pixel), then no movement is made
  428. // and the top/bottom flags are not set
  429.  
  430.  
  431. // This situation could occur when running along a flat surface
  432. // and coming into a discontinuous increase in the top of the surface
  433. // _______
  434. // T0 T1
  435. //
  436. // o--> e.g., approaching slope top,
  437. // _______ object o runs from t0 to t1
  438. // / don't want to "jump up" to the next surface
  439. // /
  440.  
  441. if (o->type == obj_keen && KeenPushedHorz == 0)
  442. {
  443. // So now handle this situation
  444. if (!o->topflags && KeenClip.lr.y > 0)
  445. MoveDown(o);
  446. if (!o->botflags && KeenClip.ul.y < 0)
  447. MoveUp(o);
  448. }
  449.  
  450. MoveOutOfTileHorz(o);
  451. }
  452.  
  453. /* Not On Platform and Falling */
  454. if (notonplatform && !o->topflags)
  455. {
  456. o->pos.y = ypos_0;
  457. o->pos.x = xpos_0 + KeenVel.x;
  458. o->box.ul.x = o->pos.x + sprhead_p->xl;
  459. o->box.lr.x = o->pos.x + sprhead_p->xh;
  460. o->box.ul.y = o->pos.y + sprhead_p->yl;
  461. o->box.lr.y = o->pos.y + sprhead_p->yh;
  462. o->boxXmid = (o->box.lr.x-o->box.ul.x)/2 + o->box.ul.x;
  463. o->boxT.ul.x = MU2TILE(o->box.ul.x);
  464. o->boxT.lr.x = MU2TILE(o->box.lr.x);
  465. o->boxT.ul.y = MU2TILE(o->box.ul.y);
  466. o->boxT.lr.y = MU2TILE(o->box.lr.y);
  467. o->boxTXmid = MU2TILE(o->boxXmid);
  468. }
  469.  
  470. // update offset
  471. o->offs.x += o->pos.x - xpos_0;
  472. o->offs.y += o->pos.y - ypos_0;
  473. }
  474. }
  475.  
  476. // special clipping for sprite types 0xB and 0x16 (slicestar and sphereful)
  477. // TODO: recheck
  478. void FullClipToWalls(objtype *o)
  479. {
  480. unsigned xpos_0, ypos_0;
  481. int del_x, del_y;
  482. spritetabletype far *sprhead_p;
  483.  
  484. /* limit and apply vel */
  485. xpos_0 = o->pos.x;
  486. ypos_0 = o->pos.y;
  487.  
  488. if (KeenVel.x > 239)
  489. KeenVel.x = 239;
  490. else if (KeenVel.x < -239)
  491. KeenVel.y = -239;
  492.  
  493. if (KeenVel.y > 255)
  494. KeenVel.y = 255;
  495. else if (KeenVel.y < -239)
  496. KeenVel.y = -239;
  497.  
  498. o->pos.x += KeenVel.x;
  499. o->pos.y += KeenVel.y;
  500.  
  501. o->draw = true;
  502.  
  503. sprhead_p = spritetable + (o->chunk - STARTSPRITES);
  504.  
  505. if (o->type != 0xB && o->type != 0x16) {
  506. Quit("FullClipToWalls: Bad obclass");
  507. }
  508.  
  509. /* Make Artificial Hitbox */
  510. del_x = del_y = 0x200;
  511. o->box.lr.x = o->pos.x + del_x;
  512. o->box.ul.x = o->pos.x;
  513. o->box.ul.y = o->pos.y;
  514. o->box.lr.y = o->pos.y + del_y;
  515. o->boxT.ul.x = MU2TILE(o->box.ul.x);
  516. o->boxT.lr.x = MU2TILE(o->box.lr.x);
  517. o->boxT.ul.y = MU2TILE(o->box.ul.y);
  518. o->boxT.lr.y = MU2TILE(o->box.lr.y);
  519.  
  520. /* Do Tile Checking */
  521. o->leftflags = o->botflags = o->topflags = o->rightflags = 0;
  522. if (!CheckIfStuck(o))
  523. {
  524. UpdateXPos(o, -KeenVel.x);
  525. if (!CheckIfStuck(o))
  526. {
  527. if (KeenVel.y > 0)
  528. o->topflags = 1;
  529. else
  530. o->botflags = 1;
  531.  
  532. UpdateXPos(o, KeenVel.x);
  533. UpdateYPos(o, KeenVel.y);
  534.  
  535. if (!CheckIfStuck(o))
  536. {
  537.  
  538. UpdateXPos(o, -KeenVel.x);
  539. if (KeenVel.x > 0)
  540. o->leftflags = 1;
  541. else
  542. o->rightflags = 1;
  543. }
  544. }
  545. else
  546. {
  547. if (KeenVel.x > 0)
  548. o->leftflags = 1;
  549. else
  550. o->rightflags = 1;
  551. }
  552. }
  553.  
  554. /* Set box using spriteahd */
  555. o->offs.x += (o->pos.x - xpos_0);
  556. o->offs.y += (o->pos.y - ypos_0);
  557. o->box.ul.x = o->pos.x + sprhead_p->xl;
  558. o->box.lr.x = o->pos.x + sprhead_p->xh;
  559. o->box.ul.y = o->pos.y + sprhead_p->yl;
  560. o->box.lr.y = o->pos.y + sprhead_p->yh;
  561. o->boxXmid = (o->box.lr.x-o->box.ul.x)/2 + o->box.ul.x;
  562. }
  563.  
  564. // rehcek
  565. void SimpleClip(objtype *o)
  566. {
  567. unsigned xpos_0, ypos_0;
  568. spritetabletype far *sprhead_p;
  569.  
  570. /* update object position */
  571. xpos_0 = o->pos.x;
  572. ypos_0 = o->pos.y;
  573. o->pos.x += KeenVel.x;
  574. o->pos.y += KeenVel.y;
  575.  
  576. o->draw = true;
  577.  
  578. if (o->chunk)
  579. {
  580. /* Set Temp Dimensions */
  581. sprhead_p = spritetable + (o->chunk - STARTSPRITES);
  582. KeenBoxT.ul.x = o->boxT.ul.x;
  583. KeenBoxT.lr.x = o->boxT.lr.x;
  584. KeenBoxT.ul.y = o->boxT.ul.y;
  585. KeenBoxT.lr.y = o->boxT.lr.y;
  586. KeenBoxTXMid = o->boxTXmid;
  587. KeenBox.ul.x = o->box.ul.x;
  588. KeenBox.lr.x = o->box.lr.x;
  589. KeenBox.ul.y = o->box.ul.y;
  590. KeenBox.lr.y = o->box.lr.y;
  591. KeenBoxXMid = o->boxXmid;
  592.  
  593. /* Set new box according to sprhead + vel */
  594. o->box.ul.x = o->pos.x + sprhead_p->xl;
  595. o->box.lr.x = o->pos.x + sprhead_p->xh;
  596. o->box.ul.y = o->pos.y + sprhead_p->yl;
  597. o->box.lr.y = o->pos.y + sprhead_p->yh;
  598. o->boxXmid = (o->box.lr.x-o->box.ul.x)/2 + o->box.ul.x;
  599. o->boxT.ul.x = MU2TILE(o->box.ul.x);
  600. o->boxT.lr.x = MU2TILE(o->box.lr.x);
  601. o->boxT.ul.y = MU2TILE(o->box.ul.y);
  602. o->boxT.lr.y = MU2TILE(o->box.lr.y);
  603. o->boxTXmid = MU2TILE(o->boxXmid);
  604.  
  605. /* Do Tile Checking */
  606. o->leftflags = o->botflags = o->rightflags = o->leftflags = 0;
  607. if (o->clipping)
  608. {
  609. KeenClip.ul.x = o->box.ul.x - KeenBox.ul.x;
  610. KeenClip.lr.x = o->box.lr.x - KeenBox.lr.x;
  611. KeenClip.ul.y = o->box.ul.y - KeenBox.ul.y;
  612. KeenClip.lr.y = o->box.lr.y - KeenBox.lr.y;
  613. KeenClipXMid = o->boxXmid - KeenBoxXMid;
  614. SetOnSlope(o);
  615. MoveOutOfTileHorz(o);
  616. }
  617.  
  618. /* calc offset */
  619. o->offs.x += o->pos.x - xpos_0;
  620. o->offs.y += o->pos.y - ypos_0;
  621. }
  622. }
  623.  
  624.  
  625. // recheck
  626. /*
  627. ============================
  628. =
  629. = PushHorz
  630. =
  631. = o2 pushes o1 in x
  632. =
  633. ============================
  634. */
  635. void PushHorz(objtype *o1, objtype *o2)
  636. {
  637. int del_offsX, del_boxXA, del_boxXB;
  638.  
  639. del_offsX = o2->offs.x - o1->offs.x;
  640. del_boxXA = o2->box.lr.x - o1->box.ul.x;
  641. del_boxXB = o1->box.lr.x - o2->box.ul.x;
  642.  
  643. if (del_boxXA > 0 && del_boxXA <= del_offsX)
  644. {
  645. KeenVel.x = del_boxXA;
  646. if (o1->action->change_v)
  647. KeenVel.y = -del_boxXA + 16;
  648. NormalClip(o1);
  649. o1->rightflags = 1;
  650. return;
  651. }
  652.  
  653. if (del_boxXB > 0 && del_boxXB >= -del_offsX)
  654. {
  655. KeenVel.x = -del_boxXB;
  656. if (o1->action->change_v)
  657. KeenVel.y = del_boxXB + 16;
  658. NormalClip(o1);
  659. o1->leftflags = 1;
  660. return;
  661. }
  662. }
  663.  
  664. /*
  665. ============================
  666. =
  667. = PushVert
  668. =
  669. = o2 carries o1
  670. =
  671. ============================
  672. */
  673.  
  674. void PushVert(objtype *o1, objtype *o2)
  675. {
  676. int del_boxY, del_offsY, action_change_v;
  677.  
  678. del_offsY = o1->offs.y - o2->offs.y;
  679. del_boxY = o1->box.lr.y - o2->box.ul.y;
  680.  
  681. if (del_boxY >= 0 && del_boxY <= del_offsY)
  682. {
  683. if (o1->type == obj_keen)
  684. PDat->Platform = o2;
  685.  
  686. /* Move carried sprite around */
  687. KeenVel.y = -del_boxY;
  688. action_change_v = o1->action->change_v;
  689. o1->action->change_v = 0;
  690. NormalClip(o1);
  691. o1->action->change_v = action_change_v;
  692.  
  693. if (o1->botflags == BF_NOT)
  694. o1->topflags = TF_PLATFORM;
  695. }
  696. }
  697.  
  698. void sub_19E88(arg0,arg2,arg4) {
  699. // no xrefs, skipping for now
  700. }
  701.  
  702. // Function that runs the actions
  703. // Rechecked
  704. // MoveParms
  705. // 0
  706. // 1
  707. // 2: Do action once per loop, don't add action delta/v or h, use actiontimer as countdown
  708. // 3
  709. // 4
  710. // o->int13 is some time scaling factor, reset at middle
  711. int TimeAction(objtype *o, int time)
  712. {
  713. actiontype *a;
  714. int newtime, timeleft, newtimeleft;
  715.  
  716. a = o->action;
  717.  
  718. // Move Parm 2 == Use actiontimer as loopcounter
  719. // Only think() once per DoAction call (returns 0)
  720. if (a->moveparm == 2)
  721. {
  722. if (a->think)
  723. {
  724. if (o->actiontimer)
  725. o->actiontimer--;
  726. else
  727. a->think(o);
  728. }
  729. return 0;
  730. }
  731.  
  732. // Increase tics;
  733. newtime = time + o->int13;
  734. if (a->delay > newtime || a->delay == 0)
  735. {
  736. // Haven't yet reached action time limit
  737. o->int13 = newtime;
  738.  
  739. // 1, 4: Use action delta scaled by time for motion
  740. if (a->moveparm == 1 || a->moveparm == 4)
  741. {
  742. if (o->xmotion)
  743. KeenVel.x += a->delta_h * (o->xmotion==motion_Right?time:-time);
  744. if (o->ymotion)
  745. KeenVel.y += a->delta_v * (o->ymotion==motion_Down?time:-time);
  746. }
  747.  
  748. //1a078
  749. // 3, 4 Burn fuse and do think
  750. if (a->moveparm == 4 || a->moveparm == 3)
  751. {
  752. if (a->think)
  753. {
  754. if (o->actiontimer)
  755. o->actiontimer--;
  756. else
  757. a->think(o);
  758. }
  759. }
  760.  
  761. // No leftover tics to do for NEXT action
  762. return 0;
  763. }
  764.  
  765. //1A0A6
  766. // Action time delay reached
  767. // timeleft = the final number of tics to perform for this action
  768. // newtimeleft = the overflow to apply to the next action
  769. timeleft = a->delay - o->int13;
  770. newtimeleft = newtime - a->delay;
  771. o->int13 = 0; // reset tics
  772.  
  773. // 1, 4: Use action delta scaled by remainder of tics for current action
  774. if (a->moveparm == 1 || a->moveparm == 4)
  775. {
  776. //1ac09
  777. if (o->xmotion)
  778. KeenVel.x += a->delta_h * (o->xmotion==motion_Right?timeleft:-timeleft);
  779. if (o->ymotion)
  780. KeenVel.y += a->delta_v * (o->ymotion==motion_Down?timeleft:-timeleft);
  781. }
  782. else // moveparm == 3, 0, Move by unscaled amount at action start
  783. {
  784. if (o->xmotion)
  785. KeenVel.x += (o->xmotion==motion_Right?a->delta_h:-a->delta_h);
  786. if (o->ymotion)
  787. KeenVel.y += (o->ymotion==motion_Down?a->delta_v:-a->delta_v);
  788. }
  789.  
  790. //1a141
  791. // Burn fuse and think()
  792. if (a->think)
  793. {
  794. if (o->actiontimer)
  795. o->actiontimer--;
  796. else
  797. a->think(o);
  798. }
  799.  
  800. // Advance action if haven't done so
  801. if (o->action == a)
  802. o->action = a->next;
  803. else if (!o->action) // if NULL action, then sprite is dead
  804. return 0;
  805.  
  806. // If action advanced, want to process remaining tics on the next action
  807. return newtimeleft;
  808. }
  809.  
  810.  
  811. // Rechecked
  812. void DoAction(objtype *o)
  813. {
  814. int frame_0, time;
  815. actiontype *a;
  816.  
  817. // Set the offset and clipping offset to this frame to zero
  818. o->offs.x = o->offs.y = KeenVel.x = KeenVel.y = 0;
  819. frame_0 = o->chunk;
  820. a = o->action;
  821.  
  822. // Process action once
  823. time = TimeAction(o,SpriteSync);
  824.  
  825. // reset counter if new action
  826. if (o->action != a)
  827. {
  828. o->int13 = 0;
  829. a = o->action;
  830. }
  831.  
  832. // If moved into a new action while performing old action
  833. // then do action(s) for remainder of tics
  834. while (time)
  835. {
  836. if (a->change_h || a->delay > time)
  837. time = TimeAction(o, time);
  838. else
  839. time = TimeAction(o, a->delay - 1);
  840.  
  841. // reset counter if new action
  842. if (o->action != a)
  843. {
  844. o->int13 = 0;
  845. a = o->action;
  846. }
  847. }
  848.  
  849. // NULL action == remove object
  850. if (a == NULL)
  851. {
  852. RemoveObj(o);
  853. return;
  854. }
  855.  
  856. // Set Sprite chunk
  857. if (a->right_chunk)
  858. o->chunk=(o->xmotion>motion_None)? a->right_chunk : a->left_chunk;
  859.  
  860. if (o->chunk == -1)
  861. o->chunk = 0;
  862.  
  863. // If we have moved, frame has changed, or on platform, then do clipping
  864. if (KeenVel.x != 0 || KeenVel.y != 0 ||
  865. o->chunk != frame_0 || o->topflags == TF_PLATFORM)
  866. {
  867. if (o->clipping == 2)
  868. FullClipToWalls(o);
  869. else
  870. NormalClip(o);
  871. }
  872. }
  873.  
  874. //The "check ground" funcs look to be setting an action to a sprite
  875. // rechecked -- perfect
  876. void CheckGround(objtype *o, actiontype *a)
  877. {
  878. int clip_0;
  879.  
  880. o->action = a;
  881.  
  882. if (a->right_chunk)
  883. o->chunk = (o->xmotion > motion_None)? a->right_chunk : a->left_chunk;
  884.  
  885. if (o->chunk == -1)
  886. o->chunk = 0;
  887.  
  888. clip_0 = o->clipping;
  889. o->clipping = 0;
  890. KeenVel.x = KeenVel.y = 0;
  891. NormalClip(o);
  892. o->clipping = clip_0;
  893.  
  894. // Special clipping
  895. if (o->clipping == 2)
  896. {
  897. FullClipToWalls(o);
  898. return;
  899. }
  900.  
  901. if (o->clipping == 1)
  902. NormalClip(o);
  903. }
  904.  
  905. // rechecked -- perfect
  906. void CheckGround2(objtype *o, ACTION *a)
  907. {
  908. o->action = a;
  909. o->int13 = 0;
  910. if (a->right_chunk)
  911. o->chunk = (o->xmotion > motion_None)? a->right_chunk : a->left_chunk;
  912.  
  913. if (o->chunk == -1)
  914. o->chunk = 0;
  915.  
  916. o->draw = true;
  917. KeenVel.x = KeenVel.y = 0;
  918.  
  919. if (o->topflags != TF_PLATFORM)
  920. NormalClip(o);
  921. }
  922.  
  923. /*
  924. ============================
  925. =
  926. = ObjectVisible
  927. =
  928. = Returns true if object on screen
  929. =
  930. ============================
  931. */
  932. boolean ObjectVisible(objtype *o)
  933. {
  934.  
  935. if (o->boxT.lr.x >= ScrollX0_T && o->boxT.lr.x >= ScrollY0_T &&
  936. o->boxT.ul.x <= ScrollX1_T && o->boxT.ul.y <= ScrollY1_T)
  937. return true;
  938.  
  939. return false;
  940. }
  941.  
  942. // ===========================================================================
  943. //
  944. // Generic Object Functions
  945. //
  946. // ===========================================================================
  947.  
  948. /*
  949. ============================
  950. =
  951. = AddGravity / AddGravity2 / AddGravity3
  952. =
  953. = Make objects fall (at various accelerations)
  954. =
  955. ============================
  956. */
  957.  
  958. // rechecked -- perfect
  959. void AddGravity(objtype *o)
  960. {
  961. unsigned long tc;
  962.  
  963. for (tc = gameticks_2 - SpriteSync; tc < gameticks_2; tc++)
  964. {
  965. if (tc & 1)
  966. {
  967. if (o->vel.y < 0 && o->vel.y >= -4)
  968. {
  969. KeenVel.y += o->vel.y;
  970. o->vel.y = 0;
  971. return;
  972. }
  973. o->vel.y += 4; //4 appears to be gravity
  974. if (o->vel.y > 70)
  975. o->vel.y = 70; // 70 is max gravity
  976. }
  977.  
  978. KeenVel.y += o->vel.y;
  979. }
  980. }
  981.  
  982. // rechecked -- perfect
  983. void AddGravity2(objtype *o)
  984. {
  985. unsigned long tc;
  986.  
  987. for (tc = gameticks_2-SpriteSync; tc < gameticks_2; tc++)
  988. {
  989. if (tc & 1)
  990. {
  991. if (o->vel.y < 0 && o->vel.y >= -3)
  992. {
  993. KeenVel.y += o->vel.y;
  994. o->vel.y = 0;
  995. return;
  996. }
  997.  
  998. o->vel.y += 3; // 3 is gravity
  999. if (o->vel.y > 70)
  1000. o->vel.y = 70; // 70 is max gravity
  1001. }
  1002.  
  1003. KeenVel.y += o->vel.y;
  1004. }
  1005. }
  1006.  
  1007. // rechecked -- good
  1008. void AddGravity3(objtype *o)
  1009. {
  1010. unsigned long tc;
  1011.  
  1012. for (tc = gameticks_2-SpriteSync; tc < gameticks_2; tc++)
  1013. {
  1014. if ((tc?0:1) & 3)
  1015. {
  1016. if (++o->vel.y > 70)
  1017. o->vel.y = 70;
  1018. }
  1019.  
  1020. KeenVel.y += o->vel.y;
  1021. }
  1022. }
  1023.  
  1024. // rechecked -- perfect
  1025. void MoveHorz0(objtype *o, int delX, int xlimit)
  1026. {
  1027. unsigned long tc;
  1028. unsigned d;
  1029.  
  1030. // sign byte
  1031. d = (unsigned)o->vel.x & 0x8000;
  1032.  
  1033. for (tc = gameticks_2 - SpriteSync; tc < gameticks_2; tc++)
  1034. {
  1035. if (tc & 1)
  1036. {
  1037. o->vel.x += delX;
  1038. if (((unsigned)o->vel.x & 0x8000) != d)
  1039. {
  1040. d = (unsigned)o->vel.x & 0x8000;
  1041. o->xmotion = d? motion_Left : motion_Right;
  1042. }
  1043.  
  1044. if (o->vel.x > xlimit)
  1045. o->vel.x = xlimit;
  1046. else if (o->vel.x < -xlimit)
  1047. o->vel.x = -xlimit;
  1048. }
  1049. KeenVel.x += o->vel.x;
  1050. }
  1051. }
  1052.  
  1053. // no xrefs in keen5
  1054. void MoveHorz1(objtype *o, Motion xmotion, int xlimit)
  1055. {
  1056. unsigned long tc;
  1057.  
  1058. for (tc = gameticks_2-SpriteSync; tc < gameticks_2; tc++)
  1059. {
  1060. if (tc &1)
  1061. {
  1062. o->vel.x += xmotion;
  1063. if (o->vel.x > xlimit)
  1064. o->vel.x = xlimit;
  1065. else if (o->vel.x < -xlimit)
  1066. o->vel.x = -xlimit;
  1067. }
  1068.  
  1069. KeenVel.x += o->vel.x;
  1070. }
  1071. }
  1072.  
  1073.  
  1074. // no xrefs in keen5
  1075. void MoveVert1(objtype *o, Motion ymotion, int ylimit)
  1076. {
  1077. unsigned long tc;
  1078.  
  1079. for (tc = gameticks_2-SpriteSync; tc < gameticks_2; tc++) {
  1080.  
  1081. if (tc &1)
  1082. {
  1083. o->vel.y += ymotion;
  1084. if (o->vel.y > ylimit)
  1085. o->vel.y = ylimit;
  1086. else if (o->vel.y < -ylimit)
  1087. o->vel.y = -ylimit;
  1088. }
  1089.  
  1090. KeenVel.y += o->vel.y;
  1091. }
  1092. return;
  1093. }
  1094.  
  1095. /*
  1096. ============================
  1097. =
  1098. = MoveHorz2 / MoveVert2
  1099. =
  1100. = Gently slow down in x/y
  1101. =
  1102. ============================
  1103. */
  1104. // rechecked -- perfect
  1105. void MoveHorz2(objtype *o)
  1106. {
  1107. unsigned long tc;
  1108. int d, xadj;
  1109.  
  1110. d = o->vel.x & 0x8000;
  1111.  
  1112. if (o->vel.x > 0)
  1113. xadj = -1;
  1114. else if (o->vel.x < 0)
  1115. xadj = 1;
  1116. else
  1117. xadj = 0;
  1118.  
  1119. for (tc = gameticks_2-SpriteSync; tc < gameticks_2; tc++)
  1120. {
  1121. if (tc & 1)
  1122. {
  1123. o->vel.x += xadj;
  1124. if ((o->vel.x & 0x8000) != d)
  1125. o->vel.x = 0;
  1126. }
  1127. KeenVel.x += o->vel.x;
  1128. }
  1129. }
  1130.  
  1131. // no xrefs
  1132. // note d is used before initialized
  1133. void MoveVert2(objtype *o)
  1134. {
  1135. unsigned long tc;
  1136. int d, yadj;
  1137.  
  1138. d = o->vel.x & 0x8000; // this line not in source, but probably should be?
  1139.  
  1140. if (o->vel.y > 0)
  1141. yadj = -1;
  1142. else if (o->vel.y < 0)
  1143. yadj = 1;
  1144. else
  1145. yadj = 0;
  1146.  
  1147. for (tc = gameticks_2-SpriteSync; tc < gameticks_2; tc++)
  1148. {
  1149. if (tc & 1)
  1150. {
  1151. o->vel.y += yadj;
  1152. if ((o->vel.y & 0x8000) == d)
  1153. o->vel.y = 0;
  1154. }
  1155. KeenVel.y += o->vel.y;
  1156. }
  1157. }
  1158.  
  1159. //something to do with getting shot by keen?
  1160. #if 0
  1161. StunCreature(objtype *o, objtype *stunner, ACTION *a)
  1162. {
  1163.  
  1164. StunnerHits(stunner);
  1165.  
  1166. o->int33 = o->state = o->time = 0;
  1167. o->int34 = o->type;
  1168. CheckGround2(o, a);
  1169. o->type = 7;
  1170. o->vel.y -= 24;
  1171. if (o->vel.y < -48) o->vel.y = -48;
  1172. return;
  1173. }
  1174. #endif
  1175.  
  1176. /*Sprite Bheaviours*/
  1177.  
  1178. //default falling
  1179. // rechecked -- perfect
  1180. void Fall(objtype *o)
  1181. {
  1182. AddGravity(o);
  1183. KeenVel.x = o->vel.x * SpriteSync;
  1184. }
  1185.  
  1186. //used by Master Shot
  1187. // rechecked -- perfect
  1188. void Fall2(objtype *o)
  1189. {
  1190. AddGravity2(o);
  1191. KeenVel.x = o->vel.x * SpriteSync;
  1192. }
  1193.  
  1194. //move without gravity, used by GunShots
  1195. // rechecked -- perfect
  1196. void Glide(objtype *o)
  1197. {
  1198. KeenVel.x = o->vel.x * SpriteSync;
  1199. KeenVel.y = o->vel.y * SpriteSync;
  1200. }
  1201.  
  1202. //no xrefs
  1203. //just draw the sprite
  1204. // rechecked -- perfect
  1205. void Think0(objtype *o)
  1206. {
  1207. o->draw = true;
  1208. }
  1209.  
  1210.  
  1211. // no xrefs
  1212. // cycle through states
  1213. // rechecked -- perfect
  1214. void Think1(objtype *o)
  1215. {
  1216. o->time = 0;
  1217. o->draw = 1;
  1218. if (++(o->state) == 3)
  1219. o->state = 0;
  1220. }
  1221.  
  1222. /*Sprite Collision Functions */
  1223.  
  1224. //usedby ShelleyBits, Polezaps, for killling keen
  1225.  
  1226. void SprCol1(objtype *o1, objtype *o2)
  1227. {
  1228. o1++;
  1229. if (o2->type == obj_keen)
  1230. KeenDie(o2);
  1231. }
  1232.  
  1233.  
  1234.  
  1235. /*Draw Funcs*/
  1236. // note: in keen, there is no active checking
  1237. void DrawFunc1(objtype *o)
  1238. {
  1239. RF_PlaceSprite(&o->spritedraw, o->pos.x, o->pos.y, o->chunk, 0, o->int16);
  1240. }
  1241.  
  1242. //used by scotty
  1243. void DrawFunc2(objtype *o)
  1244. {
  1245. if (o->xmotion == motion_Right && o->leftflags)
  1246. {
  1247. o->pos.x -= o->offs.x;
  1248. o->xmotion = motion_Left;
  1249. o->actiontimer = US_RndT() / 32;
  1250. CheckGround2(o, o->action);
  1251. }
  1252. else if (o->xmotion == motion_Left && o->rightflags)
  1253. {
  1254. o->pos.x -= o->offs.x;
  1255. o->xmotion = motion_Right;
  1256. o->actiontimer = US_RndT()/32;
  1257. CheckGround2(o,o->action);
  1258. }
  1259. else if (!o->topflags)
  1260. {
  1261. o->pos.x -= o->offs.x;
  1262. o->xmotion = -o->xmotion;
  1263. o->actiontimer = US_RndT()/32;
  1264. CheckGround2(o,o->action);
  1265. }
  1266.  
  1267. RF_PlaceSprite(&o->spritedraw, o->pos.x, o->pos.y, o->chunk, 0, o->int16);
  1268. }
  1269.  
  1270. //no xrefs in Keen5, skipping for now
  1271. void DrawFunc3(objtype *o) {
  1272. }
  1273.  
  1274. void ObjBadState(void) {
  1275. Quit("Object with a bad state!");
  1276. return;
  1277. }
  1278.  
  1279.  
  1280. /* Looks like stunner stars */
  1281. #if 0
  1282. void DrawFunc4(objtype *o) {
  1283.  
  1284. int delx, dely;
  1285.  
  1286. if (o->leftflags || o->rightflags)
  1287. o->vel.x = 0;
  1288. if (o->botflags)
  1289. o->vel.y = 0;
  1290. if (o->topflags)
  1291. {
  1292. o->vel.x = o->vel.y = 0;
  1293. if (o->action->next)
  1294. CheckGround2(o, o->action->next);
  1295. }
  1296.  
  1297. RF_PlaceSprite(&o->spritedraw, o->pos.x, o->pos.y, o->chunk, 0, o->int16);
  1298.  
  1299. /* Place The Stunner Stars
  1300. Remember To RF_RemoveSprite in PlayLoop!
  1301. */
  1302. dely = delx = 0;
  1303. if (o->int34 == 9) {
  1304. delx += 64;
  1305. } else if (o->int34 == 15) {
  1306. dely -= 128;
  1307. } else if (o->int34 == 0x17) {
  1308. dely -= 128;
  1309. }
  1310.  
  1311. o->time += SpriteSync;
  1312. if (o->time > 10) {
  1313. o->time -= 10;
  1314. if (++(o->state) == 3)
  1315. o->state = 0;
  1316. }
  1317.  
  1318. RF_PlaceSprite(&(SpriteDraw*)o->int33, o->pos.x+delx, o->pos.y+dely, o->state+143, 0, 3);
  1319. }
  1320. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement