p_ceilng.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. /* Emacs style mode select -*- C++ -*-
  2. *-----------------------------------------------------------------------------
  3. *
  4. *
  5. * PrBoom: a Doom port merged with LxDoom and LSDLDoom
  6. * based on BOOM, a modified and improved DOOM engine
  7. * Copyright (C) 1999 by
  8. * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
  9. * Copyright (C) 1999-2000 by
  10. * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
  11. * Copyright 2005, 2006 by
  12. * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License
  16. * as published by the Free Software Foundation; either version 2
  17. * of the License, or (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software
  26. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  27. * 02111-1307, USA.
  28. *
  29. * DESCRIPTION:
  30. * Ceiling aninmation (lowering, crushing, raising)
  31. *
  32. *-----------------------------------------------------------------------------*/
  33. #include "doomstat.h"
  34. #include "r_main.h"
  35. #include "p_spec.h"
  36. #include "p_tick.h"
  37. #include "s_sound.h"
  38. #include "sounds.h"
  39. // the list of ceilings moving currently, including crushers
  40. ceilinglist_t *activeceilings;
  41. /////////////////////////////////////////////////////////////////
  42. //
  43. // Ceiling action routine and linedef type handler
  44. //
  45. /////////////////////////////////////////////////////////////////
  46. //
  47. // T_MoveCeiling
  48. //
  49. // Action routine that moves ceilings. Called once per tick.
  50. //
  51. // Passed a ceiling_t structure that contains all the info about the move.
  52. // see P_SPEC.H for fields. No return.
  53. //
  54. // jff 02/08/98 all cases with labels beginning with gen added to support
  55. // generalized line type behaviors.
  56. //
  57. void T_MoveCeiling (ceiling_t* ceiling)
  58. {
  59. result_e res;
  60. switch(ceiling->direction)
  61. {
  62. case 0:
  63. // If ceiling in stasis, do nothing
  64. break;
  65. case 1:
  66. // Ceiling is moving up
  67. res = T_MovePlane
  68. (
  69. ceiling->sector,
  70. ceiling->speed,
  71. ceiling->topheight,
  72. false,
  73. 1,
  74. ceiling->direction
  75. );
  76. // if not a silent crusher, make moving sound
  77. if (!(leveltime&7))
  78. {
  79. switch(ceiling->type)
  80. {
  81. case silentCrushAndRaise:
  82. case genSilentCrusher:
  83. break;
  84. default:
  85. S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov);
  86. break;
  87. }
  88. }
  89. // handle reaching destination height
  90. if (res == pastdest)
  91. {
  92. switch(ceiling->type)
  93. {
  94. // plain movers are just removed
  95. case raiseToHighest:
  96. case genCeiling:
  97. P_RemoveActiveCeiling(ceiling);
  98. break;
  99. // movers with texture change, change the texture then get removed
  100. case genCeilingChgT:
  101. case genCeilingChg0:
  102. ceiling->sector->special = ceiling->newspecial;
  103. //jff 3/14/98 transfer old special field as well
  104. ceiling->sector->oldspecial = ceiling->oldspecial;
  105. case genCeilingChg:
  106. ceiling->sector->ceilingpic = ceiling->texture;
  107. P_RemoveActiveCeiling(ceiling);
  108. break;
  109. // crushers reverse direction at the top
  110. case silentCrushAndRaise:
  111. S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_pstop);
  112. case genSilentCrusher:
  113. case genCrusher:
  114. case fastCrushAndRaise:
  115. case crushAndRaise:
  116. ceiling->direction = -1;
  117. break;
  118. default:
  119. break;
  120. }
  121. }
  122. break;
  123. case -1:
  124. // Ceiling moving down
  125. res = T_MovePlane
  126. (
  127. ceiling->sector,
  128. ceiling->speed,
  129. ceiling->bottomheight,
  130. ceiling->crush,
  131. 1,
  132. ceiling->direction
  133. );
  134. // if not silent crusher type make moving sound
  135. if (!(leveltime&7))
  136. {
  137. switch(ceiling->type)
  138. {
  139. case silentCrushAndRaise:
  140. case genSilentCrusher:
  141. break;
  142. default:
  143. S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov);
  144. }
  145. }
  146. // handle reaching destination height
  147. if (res == pastdest)
  148. {
  149. switch(ceiling->type)
  150. {
  151. // 02/09/98 jff change slow crushers' speed back to normal
  152. // start back up
  153. case genSilentCrusher:
  154. case genCrusher:
  155. if (ceiling->oldspeed<CEILSPEED*3)
  156. ceiling->speed = ceiling->oldspeed;
  157. ceiling->direction = 1; //jff 2/22/98 make it go back up!
  158. break;
  159. // make platform stop at bottom of all crusher strokes
  160. // except generalized ones, reset speed, start back up
  161. case silentCrushAndRaise:
  162. S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_pstop);
  163. case crushAndRaise:
  164. ceiling->speed = CEILSPEED;
  165. case fastCrushAndRaise:
  166. ceiling->direction = 1;
  167. break;
  168. // in the case of ceiling mover/changer, change the texture
  169. // then remove the active ceiling
  170. case genCeilingChgT:
  171. case genCeilingChg0:
  172. ceiling->sector->special = ceiling->newspecial;
  173. //jff add to fix bug in special transfers from changes
  174. ceiling->sector->oldspecial = ceiling->oldspecial;
  175. case genCeilingChg:
  176. ceiling->sector->ceilingpic = ceiling->texture;
  177. P_RemoveActiveCeiling(ceiling);
  178. break;
  179. // all other case, just remove the active ceiling
  180. case lowerAndCrush:
  181. case lowerToFloor:
  182. case lowerToLowest:
  183. case lowerToMaxFloor:
  184. case genCeiling:
  185. P_RemoveActiveCeiling(ceiling);
  186. break;
  187. default:
  188. break;
  189. }
  190. }
  191. else // ( res != pastdest )
  192. {
  193. // handle the crusher encountering an obstacle
  194. if (res == crushed)
  195. {
  196. switch(ceiling->type)
  197. {
  198. //jff 02/08/98 slow down slow crushers on obstacle
  199. case genCrusher:
  200. case genSilentCrusher:
  201. if (ceiling->oldspeed < CEILSPEED*3)
  202. ceiling->speed = CEILSPEED / 8;
  203. break;
  204. case silentCrushAndRaise:
  205. case crushAndRaise:
  206. case lowerAndCrush:
  207. ceiling->speed = CEILSPEED / 8;
  208. break;
  209. default:
  210. break;
  211. }
  212. }
  213. }
  214. break;
  215. }
  216. }
  217. //
  218. // EV_DoCeiling
  219. //
  220. // Move a ceiling up/down or start a crusher
  221. //
  222. // Passed the linedef activating the function and the type of function desired
  223. // returns true if a thinker started
  224. //
  225. int EV_DoCeiling
  226. ( line_t* line,
  227. ceiling_e type )
  228. {
  229. int secnum;
  230. int rtn;
  231. sector_t* sec;
  232. ceiling_t* ceiling;
  233. secnum = -1;
  234. rtn = 0;
  235. // Reactivate in-stasis ceilings...for certain types.
  236. // This restarts a crusher after it has been stopped
  237. switch(type)
  238. {
  239. case fastCrushAndRaise:
  240. case silentCrushAndRaise:
  241. case crushAndRaise:
  242. //jff 4/5/98 return if activated
  243. rtn = P_ActivateInStasisCeiling(line);
  244. default:
  245. break;
  246. }
  247. // affects all sectors with the same tag as the linedef
  248. while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
  249. {
  250. sec = &sectors[secnum];
  251. // if ceiling already moving, don't start a second function on it
  252. if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
  253. continue;
  254. // create a new ceiling thinker
  255. rtn = 1;
  256. ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
  257. memset(ceiling, 0, sizeof(*ceiling));
  258. P_AddThinker (&ceiling->thinker);
  259. sec->ceilingdata = ceiling; //jff 2/22/98
  260. ceiling->thinker.function = T_MoveCeiling;
  261. ceiling->sector = sec;
  262. ceiling->crush = false;
  263. // setup ceiling structure according to type of function
  264. switch(type)
  265. {
  266. case fastCrushAndRaise:
  267. ceiling->crush = true;
  268. ceiling->topheight = sec->ceilingheight;
  269. ceiling->bottomheight = sec->floorheight + (8*FRACUNIT);
  270. ceiling->direction = -1;
  271. ceiling->speed = CEILSPEED * 2;
  272. break;
  273. case silentCrushAndRaise:
  274. case crushAndRaise:
  275. ceiling->crush = true;
  276. ceiling->topheight = sec->ceilingheight;
  277. case lowerAndCrush:
  278. case lowerToFloor:
  279. ceiling->bottomheight = sec->floorheight;
  280. if (type != lowerToFloor)
  281. ceiling->bottomheight += 8*FRACUNIT;
  282. ceiling->direction = -1;
  283. ceiling->speed = CEILSPEED;
  284. break;
  285. case raiseToHighest:
  286. ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
  287. ceiling->direction = 1;
  288. ceiling->speed = CEILSPEED;
  289. break;
  290. case lowerToLowest:
  291. ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec);
  292. ceiling->direction = -1;
  293. ceiling->speed = CEILSPEED;
  294. break;
  295. case lowerToMaxFloor:
  296. ceiling->bottomheight = P_FindHighestFloorSurrounding(sec);
  297. ceiling->direction = -1;
  298. ceiling->speed = CEILSPEED;
  299. break;
  300. default:
  301. break;
  302. }
  303. // add the ceiling to the active list
  304. ceiling->tag = sec->tag;
  305. ceiling->type = type;
  306. P_AddActiveCeiling(ceiling);
  307. }
  308. return rtn;
  309. }
  310. //////////////////////////////////////////////////////////////////////
  311. //
  312. // Active ceiling list primitives
  313. //
  314. /////////////////////////////////////////////////////////////////////
  315. // jff 2/22/98 - modified Lee's plat code to work for ceilings
  316. //
  317. // The following were all rewritten by Lee Killough
  318. // to use the new structure which places no limits
  319. // on active ceilings. It also avoids spending as much
  320. // time searching for active ceilings. Previously a
  321. // fixed-size array was used, with NULL indicating
  322. // empty entries, while now a doubly-linked list
  323. // is used.
  324. //
  325. // P_ActivateInStasisCeiling()
  326. //
  327. // Reactivates all stopped crushers with the right tag
  328. //
  329. // Passed the line reactivating the crusher
  330. // Returns true if a ceiling reactivated
  331. //
  332. //jff 4/5/98 return if activated
  333. int P_ActivateInStasisCeiling(line_t *line)
  334. {
  335. ceilinglist_t *cl;
  336. int rtn=0;
  337. for (cl=activeceilings; cl; cl=cl->next)
  338. {
  339. ceiling_t *ceiling = cl->ceiling;
  340. if (ceiling->tag == line->tag && ceiling->direction == 0)
  341. {
  342. ceiling->direction = ceiling->olddirection;
  343. ceiling->thinker.function = T_MoveCeiling;
  344. //jff 4/5/98 return if activated
  345. rtn=1;
  346. }
  347. }
  348. return rtn;
  349. }
  350. //
  351. // EV_CeilingCrushStop()
  352. //
  353. // Stops all active ceilings with the right tag
  354. //
  355. // Passed the linedef stopping the ceilings
  356. // Returns true if a ceiling put in stasis
  357. //
  358. int EV_CeilingCrushStop(line_t* line)
  359. {
  360. int rtn=0;
  361. ceilinglist_t *cl;
  362. for (cl=activeceilings; cl; cl=cl->next)
  363. {
  364. ceiling_t *ceiling = cl->ceiling;
  365. if (ceiling->direction != 0 && ceiling->tag == line->tag)
  366. {
  367. ceiling->olddirection = ceiling->direction;
  368. ceiling->direction = 0;
  369. ceiling->thinker.function = NULL;
  370. rtn=1;
  371. }
  372. }
  373. return rtn;
  374. }
  375. //
  376. // P_AddActiveCeiling()
  377. //
  378. // Adds a ceiling to the head of the list of active ceilings
  379. //
  380. // Passed the ceiling motion structure
  381. // Returns nothing
  382. //
  383. void P_AddActiveCeiling(ceiling_t* ceiling)
  384. {
  385. ceilinglist_t *list = malloc(sizeof *list);
  386. list->ceiling = ceiling;
  387. ceiling->list = list;
  388. if ((list->next = activeceilings))
  389. list->next->prev = &list->next;
  390. list->prev = &activeceilings;
  391. activeceilings = list;
  392. }
  393. //
  394. // P_RemoveActiveCeiling()
  395. //
  396. // Removes a ceiling from the list of active ceilings
  397. //
  398. // Passed the ceiling motion structure
  399. // Returns nothing
  400. //
  401. void P_RemoveActiveCeiling(ceiling_t* ceiling)
  402. {
  403. ceilinglist_t *list = ceiling->list;
  404. ceiling->sector->ceilingdata = NULL; //jff 2/22/98
  405. P_RemoveThinker(&ceiling->thinker);
  406. if ((*list->prev = list->next))
  407. list->next->prev = list->prev;
  408. free(list);
  409. }
  410. //
  411. // P_RemoveAllActiveCeilings()
  412. //
  413. // Removes all ceilings from the active ceiling list
  414. //
  415. // Passed nothing, returns nothing
  416. //
  417. void P_RemoveAllActiveCeilings(void)
  418. {
  419. while (activeceilings)
  420. {
  421. ceilinglist_t *next = activeceilings->next;
  422. free(activeceilings);
  423. activeceilings = next;
  424. }
  425. }