C6_STATE.C 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /* Catacomb Apocalypse 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_STATE.C
  19. #include "DEF.H"
  20. #pragma hdrstop
  21. /*
  22. =============================================================================
  23. LOCAL CONSTANTS
  24. =============================================================================
  25. */
  26. /*
  27. =============================================================================
  28. GLOBAL VARIABLES
  29. =============================================================================
  30. */
  31. /*
  32. =============================================================================
  33. LOCAL VARIABLES
  34. =============================================================================
  35. */
  36. dirtype opposite[9] =
  37. {south,west,north,east,southwest,northwest,northeast,southeast,nodir};
  38. //===========================================================================
  39. /*
  40. ===================
  41. =
  42. = Internal_SpawnNewObj
  43. =
  44. ===================
  45. */
  46. void Internal_SpawnNewObj (unsigned x, unsigned y, statetype *state, unsigned size, boolean UseDummy, boolean PutInActorat)
  47. {
  48. extern objtype dummyobj;
  49. GetNewObj(UseDummy);
  50. new->size = size;
  51. new->state = state;
  52. new->ticcount = random (state->tictime)+1;
  53. new->tilex = x;
  54. new->tiley = y;
  55. new->x = ((long)x<<TILESHIFT)+TILEGLOBAL/2;
  56. new->y = ((long)y<<TILESHIFT)+TILEGLOBAL/2;
  57. CalcBounds(new);
  58. new->dir = nodir;
  59. new->active = noalways;
  60. if (new != &dummyobj && PutInActorat)
  61. actorat[new->tilex][new->tiley] = new;
  62. }
  63. void Internal_SpawnNewObjFrac (long x, long y, statetype *state, unsigned size,boolean UseDummy)
  64. {
  65. GetNewObj(UseDummy);
  66. new->size = size;
  67. new->state = state;
  68. new->ticcount = random (state->tictime)+1;
  69. new->active = noalways;
  70. new->x = x;
  71. new->y = y;
  72. new->tilex = x>>TILESHIFT;
  73. new->tiley = y>>TILESHIFT;
  74. CalcBounds(new);
  75. new->distance = 100;
  76. new->dir = nodir;
  77. }
  78. /*
  79. ===================
  80. =
  81. = CheckHandAttack
  82. =
  83. = If the object can move next to the player, it will return true
  84. =
  85. ===================
  86. */
  87. boolean CheckHandAttack (objtype *ob)
  88. {
  89. long deltax,deltay,size;
  90. size = (long)ob->size + player->size + ob->speed*tics + SIZE_TEST;
  91. deltax = ob->x - player->x;
  92. deltay = ob->y - player->y;
  93. if (deltax > size || deltax < -size || deltay > size || deltay < -size)
  94. return false;
  95. return true;
  96. }
  97. /*
  98. ===================
  99. =
  100. = T_DoDamage
  101. =
  102. = Attacks the player if still nearby, then immediately changes to next state
  103. =
  104. ===================
  105. */
  106. void T_DoDamage (objtype *ob)
  107. {
  108. int points;
  109. if (CheckHandAttack(ob) && (!(ob->flags & of_damagedone)))
  110. {
  111. points = 0;
  112. switch (ob->obclass)
  113. {
  114. case aquamanobj:
  115. points = 7;
  116. break;
  117. case wizardobj:
  118. points = 7;
  119. break;
  120. case trollobj:
  121. points = 10;
  122. break;
  123. case invisdudeobj:
  124. points = 10;
  125. break;
  126. case demonobj:
  127. case cyborgdemonobj:
  128. points = 15;
  129. break;
  130. }
  131. points = EasyDoDamage(points);
  132. TakeDamage (points);
  133. ob->flags |= of_damagedone;
  134. }
  135. }
  136. //==========================================================================
  137. /*
  138. ==================================
  139. =
  140. = Walk
  141. =
  142. ==================================
  143. */
  144. boolean Walk (objtype *ob)
  145. {
  146. switch (ob->dir)
  147. {
  148. case north:
  149. if (actorat[ob->tilex][ob->tiley-1])
  150. return false;
  151. ob->tiley--;
  152. ob->distance = TILEGLOBAL;
  153. return true;
  154. case northeast:
  155. if (actorat[ob->tilex+1][ob->tiley-1])
  156. return false;
  157. ob->tilex++;
  158. ob->tiley--;
  159. ob->distance = TILEGLOBAL;
  160. return true;
  161. case east:
  162. if (actorat[ob->tilex+1][ob->tiley])
  163. return false;
  164. ob->tilex++;
  165. ob->distance = TILEGLOBAL;
  166. return true;
  167. case southeast:
  168. if (actorat[ob->tilex+1][ob->tiley+1])
  169. return false;
  170. ob->tilex++;
  171. ob->tiley++;
  172. ob->distance = TILEGLOBAL;
  173. return true;
  174. case south:
  175. if (actorat[ob->tilex][ob->tiley+1])
  176. return false;
  177. ob->tiley++;
  178. ob->distance = TILEGLOBAL;
  179. return true;
  180. case southwest:
  181. if (actorat[ob->tilex-1][ob->tiley+1])
  182. return false;
  183. ob->tilex--;
  184. ob->tiley++;
  185. ob->distance = TILEGLOBAL;
  186. return true;
  187. case west:
  188. if (actorat[ob->tilex-1][ob->tiley])
  189. return false;
  190. ob->tilex--;
  191. ob->distance = TILEGLOBAL;
  192. return true;
  193. case northwest:
  194. if (actorat[ob->tilex-1][ob->tiley-1])
  195. return false;
  196. ob->tilex--;
  197. ob->tiley--;
  198. ob->distance = TILEGLOBAL;
  199. return true;
  200. case nodir:
  201. return false;
  202. }
  203. Quit ("Walk: Bad dir");
  204. return false;
  205. }
  206. /*
  207. ==================================
  208. =
  209. = ChaseThink
  210. = have the current monster go after the player,
  211. = either diagonally or straight on
  212. =
  213. ==================================
  214. */
  215. void ChaseThink (objtype *obj, boolean diagonal)
  216. {
  217. int deltax,deltay,i;
  218. dirtype d[3];
  219. dirtype tdir, olddir, turnaround;
  220. olddir=obj->dir;
  221. turnaround=opposite[olddir];
  222. deltax=player->tilex - obj->tilex;
  223. deltay=player->tiley - obj->tiley;
  224. d[1]=nodir;
  225. d[2]=nodir;
  226. if (deltax>0)
  227. d[1]= east;
  228. if (deltax<0)
  229. d[1]= west;
  230. if (deltay>0)
  231. d[2]=south;
  232. if (deltay<0)
  233. d[2]=north;
  234. if (abs(deltay)>abs(deltax))
  235. {
  236. tdir=d[1];
  237. d[1]=d[2];
  238. d[2]=tdir;
  239. }
  240. if (d[1]==turnaround)
  241. d[1]=nodir;
  242. if (d[2]==turnaround)
  243. d[2]=nodir;
  244. if (diagonal)
  245. { /*ramdiagonals try the best dir first*/
  246. if (d[1]!=nodir)
  247. {
  248. obj->dir=d[1];
  249. if (Walk(obj))
  250. return; /*either moved forward or attacked*/
  251. }
  252. if (d[2]!=nodir)
  253. {
  254. obj->dir=d[2];
  255. if (Walk(obj))
  256. return;
  257. }
  258. }
  259. else
  260. { /*ramstraights try the second best dir first*/
  261. if (d[2]!=nodir)
  262. {
  263. obj->dir=d[2];
  264. if (Walk(obj))
  265. return;
  266. }
  267. if (d[1]!=nodir)
  268. {
  269. obj->dir=d[1];
  270. if (Walk(obj))
  271. return;
  272. }
  273. }
  274. // Kluge to make the running eye stay in place if blocked, ie, not divert
  275. // from path
  276. if (obj->obclass == reyeobj)
  277. return;
  278. /* there is no direct path to the player, so pick another direction */
  279. obj->dir=olddir;
  280. if (Walk(obj))
  281. return;
  282. if (US_RndT()>128) /*randomly determine direction of search*/
  283. {
  284. for (tdir=north;tdir<=west;tdir++)
  285. {
  286. if (tdir!=turnaround)
  287. {
  288. obj->dir=tdir;
  289. if (Walk(obj))
  290. return;
  291. }
  292. }
  293. }
  294. else
  295. {
  296. for (tdir=west;tdir>=north;tdir--)
  297. {
  298. if (tdir!=turnaround)
  299. {
  300. obj->dir=tdir;
  301. if (Walk(obj))
  302. return;
  303. }
  304. }
  305. }
  306. obj->dir=turnaround;
  307. Walk(obj); /*last chance, don't worry about returned value*/
  308. }
  309. /*
  310. =================
  311. =
  312. = MoveObj
  313. =
  314. =================
  315. */
  316. void MoveObj (objtype *ob, long move)
  317. {
  318. ob->distance -=move;
  319. switch (ob->dir)
  320. {
  321. case north:
  322. ob->y -= move;
  323. return;
  324. case northeast:
  325. ob->x += move;
  326. ob->y -= move;
  327. return;
  328. case east:
  329. ob->x += move;
  330. return;
  331. case southeast:
  332. ob->x += move;
  333. ob->y += move;
  334. return;
  335. case south:
  336. ob->y += move;
  337. return;
  338. case southwest:
  339. ob->x -= move;
  340. ob->y += move;
  341. return;
  342. case west:
  343. ob->x -= move;
  344. return;
  345. case northwest:
  346. ob->x -= move;
  347. ob->y -= move;
  348. return;
  349. case nodir:
  350. return;
  351. }
  352. }
  353. /*
  354. =================
  355. =
  356. = Chase
  357. =
  358. = returns true if hand attack range
  359. =
  360. =================
  361. */
  362. boolean Chase (objtype *ob, boolean diagonal)
  363. {
  364. long move;
  365. long deltax,deltay,size;
  366. ob->flags &= ~of_damagedone;
  367. move = ob->speed*tics;
  368. size = (long)ob->size + player->size + move + SIZE_TEST;
  369. while (move)
  370. {
  371. deltax = ob->x - player->x;
  372. deltay = ob->y - player->y;
  373. if (deltax <= size && deltax >= -size
  374. && deltay <= size && deltay >= -size)
  375. {
  376. CalcBounds (ob);
  377. return true;
  378. }
  379. if (move < ob->distance) //ob->distance - distance before you move
  380. { // over into next tile
  381. MoveObj (ob,move);
  382. break;
  383. }
  384. else
  385. if (ob->obclass == reyeobj) // Kludge for the "running eye"
  386. {
  387. if (ob->temp1 < 2)
  388. {
  389. MoveObj(ob, ob->distance/2);
  390. ob->temp1 = 0;
  391. }
  392. }
  393. actorat[ob->tilex][ob->tiley] = 0; // pick up marker from goal
  394. if (ob->dir == nodir)
  395. ob->dir = north;
  396. ob->x = ((long)ob->tilex<<TILESHIFT)+TILEGLOBAL/2;
  397. ob->y = ((long)ob->tiley<<TILESHIFT)+TILEGLOBAL/2;
  398. move -= ob->distance;
  399. ChaseThink (ob, diagonal);
  400. if (!ob->distance)
  401. break; // no possible move
  402. actorat[ob->tilex][ob->tiley] = ob; // set down a new goal marker
  403. }
  404. CalcBounds (ob);
  405. return false;
  406. }
  407. //===========================================================================
  408. /*
  409. ===================
  410. =
  411. = ShootActor
  412. =
  413. ===================
  414. */
  415. void ShootActor (objtype *ob, unsigned damage)
  416. {
  417. ob->hitpoints -= damage;
  418. if (ob->hitpoints<=0)
  419. {
  420. switch (ob->obclass)
  421. {
  422. case headobj:
  423. ob->state = &s_pshot_exp1;
  424. ob->obclass = expobj;
  425. ob->ticcount = ob->state->tictime;
  426. SpawnBigExplosion(ob->x,ob->y,12,(16l<<16L));
  427. break;
  428. case aquamanobj:
  429. ob->state = &s_aqua_die1;
  430. ob->temp1 = 10;
  431. break;
  432. case wizardobj:
  433. ob->state = &s_wizard_die1;
  434. break;
  435. case trollobj:
  436. ob->state = &s_trolldie1;
  437. break;
  438. case blobobj:
  439. ob->state = &s_blob_die1;
  440. break;
  441. case rayobj:
  442. ob->state = &s_ray_die1;
  443. break;
  444. case ramboneobj:
  445. ob->state = &s_skel_die1;
  446. break;
  447. case fmageobj:
  448. ob->state = &s_fmagedie1;
  449. break;
  450. case robotankobj:
  451. ob->state = &s_robotank_death1;
  452. ob->temp1 = 10;
  453. break;
  454. case stompyobj:
  455. ob->state = &s_stompy_death1;
  456. break;
  457. case bugobj:
  458. ob->state = &s_bug_death1;
  459. break;
  460. case demonobj:
  461. ob->state = &s_demondie1;
  462. break;
  463. case cyborgdemonobj:
  464. ob->state = &s_cyborg_demondie1;
  465. break;
  466. case invisdudeobj:
  467. ob->state = &s_invis_death1;
  468. break;
  469. case grelmobj:
  470. ob->state = &s_greldie1;
  471. break;
  472. case eyeobj:
  473. ob->state = &s_eye_die1;
  474. break;
  475. case reyeobj:
  476. ob->state = &s_reye_die1;
  477. break;
  478. case bounceobj:
  479. ob->state = &s_pshot_exp1;
  480. ob->obclass = expobj;
  481. ob->ticcount = ob->state->tictime;
  482. SpawnBigExplosion(ob->x,ob->y,12,(16l<<16L));
  483. break;
  484. case rshotobj:
  485. case eshotobj:
  486. case wshotobj:
  487. case hshotobj:
  488. case bshotobj:
  489. case rbshotobj:
  490. case fmshotobj:
  491. case rtshotobj:
  492. case syshotobj:
  493. case bgshotobj:
  494. ob->state = &s_bonus_die;
  495. #if USE_INERT_LIST
  496. ob->obclass = solidobj; // don't add these objs to inert list
  497. #endif
  498. break;
  499. case bonusobj:
  500. case freezeobj:
  501. switch (ob->temp1)
  502. {
  503. case B_POTION:
  504. case B_OLDCHEST:
  505. case B_CHEST:
  506. case B_NUKE:
  507. case B_BOLT:
  508. ob->state = &s_pshot_exp1;
  509. ob->obclass = expobj;
  510. ob->ticcount = ob->state->tictime;
  511. SpawnBigExplosion(ob->x,ob->y,12,(16l<<16L));
  512. bordertime = FLASHTICS<<2;
  513. bcolor = 14;
  514. VW_ColorBorder(14 | 56);
  515. DisplaySMsg("Item destroyed", NULL);
  516. status_flag = S_NONE;
  517. status_delay = 80;
  518. break;
  519. }
  520. #if USE_INERT_LIST
  521. ob->obclass = solidobj; // don't add this obj to inert list
  522. #endif
  523. break;
  524. }
  525. if (ob->obclass != solidobj && ob->obclass != realsolidobj)
  526. {
  527. ob->obclass = inertobj;
  528. ob->flags &= ~of_shootable;
  529. actorat[ob->tilex][ob->tiley] = NULL;
  530. #if USE_INERT_LIST
  531. MoveObjToInert(ob);
  532. #endif
  533. }
  534. else
  535. {
  536. if (ob->flags & of_forcefield)
  537. {
  538. ob->state = &s_force_field_die;
  539. ob->flags &= ~of_shootable;
  540. }
  541. }
  542. }
  543. else
  544. {
  545. switch (ob->obclass)
  546. {
  547. case wizardobj:
  548. ob->state = &s_wizard_ouch;
  549. break;
  550. case trollobj:
  551. if (!random(5))
  552. ob->state = &s_trollouch;
  553. else
  554. return;
  555. break;
  556. case blobobj:
  557. ob->state = &s_blob_ouch;
  558. break;
  559. case ramboneobj:
  560. ob->state = &s_skel_ouch;
  561. break;
  562. case fmageobj:
  563. ob->state = &s_fmageouch;
  564. break;
  565. case stompyobj:
  566. ob->state = &s_stompy_ouch;
  567. break;
  568. case bugobj:
  569. ob->state = &s_bug_ouch;
  570. break;
  571. case cyborgdemonobj:
  572. if (!(random(8)))
  573. ob->state = &s_cyborg_demonouch;
  574. else
  575. return;
  576. break;
  577. case demonobj:
  578. if (!(random(8)))
  579. ob->state = &s_demonouch;
  580. else
  581. return;
  582. break;
  583. case invisdudeobj:
  584. ob->state = &s_invis_fizz1;
  585. break;
  586. case grelmobj:
  587. ob->state = &s_grelouch;
  588. break;
  589. case eyeobj:
  590. ob->state = &s_eye_ouch;
  591. break;
  592. case reyeobj:
  593. ob->state = &s_reye_ouch;
  594. break;
  595. }
  596. }
  597. ob->ticcount = ob->state->tictime;
  598. }