p_floor.c 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159
  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. * General plane mover and floor mover action routines
  31. * Floor motion, pure changer types, raising stairs. donuts, elevators
  32. *
  33. *-----------------------------------------------------------------------------*/
  34. #include "doomstat.h"
  35. #include "r_main.h"
  36. #include "p_map.h"
  37. #include "p_spec.h"
  38. #include "p_tick.h"
  39. #include "s_sound.h"
  40. #include "sounds.h"
  41. #include "lprintf.h"
  42. #include "g_overflow.h"
  43. #include "e6y.h"//e6y
  44. //e6y
  45. #define STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE 10
  46. ///////////////////////////////////////////////////////////////////////
  47. //
  48. // Plane (floor or ceiling), Floor motion and Elevator action routines
  49. //
  50. ///////////////////////////////////////////////////////////////////////
  51. //
  52. // T_MovePlane()
  53. //
  54. // Move a plane (floor or ceiling) and check for crushing. Called
  55. // every tick by all actions that move floors or ceilings.
  56. //
  57. // Passed the sector to move a plane in, the speed to move it at,
  58. // the dest height it is to achieve, whether it crushes obstacles,
  59. // whether it moves a floor or ceiling, and the direction up or down
  60. // to move.
  61. //
  62. // Returns a result_e:
  63. // ok - plane moved normally, has not achieved destination yet
  64. // pastdest - plane moved normally and is now at destination height
  65. // crushed - plane encountered an obstacle, is holding until removed
  66. //
  67. result_e T_MovePlane
  68. ( sector_t* sector,
  69. fixed_t speed,
  70. fixed_t dest,
  71. dboolean crush,
  72. int floorOrCeiling,
  73. int direction )
  74. {
  75. dboolean flag;
  76. fixed_t lastpos;
  77. fixed_t destheight; //jff 02/04/98 used to keep floors/ceilings
  78. // from moving thru each other
  79. #ifdef GL_DOOM
  80. if (V_GetMode() == VID_MODEGL)
  81. {
  82. gld_UpdateSplitData(sector);
  83. }
  84. #endif
  85. switch(floorOrCeiling)
  86. {
  87. case 0:
  88. // Moving a floor
  89. switch(direction)
  90. {
  91. case -1:
  92. // Moving a floor down
  93. if (sector->floorheight - speed < dest)
  94. {
  95. lastpos = sector->floorheight;
  96. sector->floorheight = dest;
  97. flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
  98. if (flag == true)
  99. {
  100. sector->floorheight =lastpos;
  101. P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
  102. }
  103. return pastdest;
  104. }
  105. else
  106. {
  107. lastpos = sector->floorheight;
  108. sector->floorheight -= speed;
  109. flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
  110. /* cph - make more compatible with original Doom, by
  111. * reintroducing this code. This means floors can't lower
  112. * if objects are stuck in the ceiling */
  113. if ((flag == true) && comp[comp_floors]) {
  114. sector->floorheight = lastpos;
  115. P_ChangeSector(sector,crush);
  116. return crushed;
  117. }
  118. }
  119. break;
  120. case 1:
  121. // Moving a floor up
  122. // jff 02/04/98 keep floor from moving thru ceilings
  123. // jff 2/22/98 weaken check to demo_compatibility
  124. destheight = (comp[comp_floors] || dest<sector->ceilingheight)?
  125. dest : sector->ceilingheight;
  126. if (sector->floorheight + speed > destheight)
  127. {
  128. lastpos = sector->floorheight;
  129. sector->floorheight = destheight;
  130. flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
  131. if (flag == true)
  132. {
  133. sector->floorheight = lastpos;
  134. P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
  135. }
  136. return pastdest;
  137. }
  138. else
  139. {
  140. // crushing is possible
  141. lastpos = sector->floorheight;
  142. sector->floorheight += speed;
  143. flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
  144. if (flag == true)
  145. {
  146. /* jff 1/25/98 fix floor crusher */
  147. if (comp[comp_floors]) {
  148. //e6y: warning about potential desynch
  149. if (crush == STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE)
  150. {
  151. lprintf(LO_WARN, "T_MovePlane: Stairs which can potentially crush may lead to desynch in compatibility mode.\n");
  152. lprintf(LO_WARN, " gametic: %d, sector: %d, complevel: %d\n", gametic, sector->iSectorID, compatibility_level);
  153. }
  154. if (crush == true)
  155. return crushed;
  156. }
  157. sector->floorheight = lastpos;
  158. P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
  159. return crushed;
  160. }
  161. }
  162. break;
  163. }
  164. break;
  165. case 1:
  166. // moving a ceiling
  167. switch(direction)
  168. {
  169. case -1:
  170. // moving a ceiling down
  171. // jff 02/04/98 keep ceiling from moving thru floors
  172. // jff 2/22/98 weaken check to demo_compatibility
  173. destheight = (comp[comp_floors] || dest>sector->floorheight)?
  174. dest : sector->floorheight;
  175. if (sector->ceilingheight - speed < destheight)
  176. {
  177. lastpos = sector->ceilingheight;
  178. sector->ceilingheight = destheight;
  179. flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
  180. if (flag == true)
  181. {
  182. sector->ceilingheight = lastpos;
  183. P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
  184. }
  185. return pastdest;
  186. }
  187. else
  188. {
  189. // crushing is possible
  190. lastpos = sector->ceilingheight;
  191. sector->ceilingheight -= speed;
  192. flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
  193. if (flag == true)
  194. {
  195. if (crush == true)
  196. return crushed;
  197. sector->ceilingheight = lastpos;
  198. P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
  199. return crushed;
  200. }
  201. }
  202. break;
  203. case 1:
  204. // moving a ceiling up
  205. if (sector->ceilingheight + speed > dest)
  206. {
  207. lastpos = sector->ceilingheight;
  208. sector->ceilingheight = dest;
  209. flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
  210. if (flag == true)
  211. {
  212. sector->ceilingheight = lastpos;
  213. P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
  214. }
  215. return pastdest;
  216. }
  217. else
  218. {
  219. lastpos = sector->ceilingheight;
  220. sector->ceilingheight += speed;
  221. flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk
  222. }
  223. break;
  224. }
  225. break;
  226. }
  227. return ok;
  228. }
  229. //
  230. // T_MoveFloor()
  231. //
  232. // Move a floor to it's destination (up or down).
  233. // Called once per tick for each moving floor.
  234. //
  235. // Passed a floormove_t structure that contains all pertinent info about the
  236. // move. See P_SPEC.H for fields.
  237. // No return.
  238. //
  239. // jff 02/08/98 all cases with labels beginning with gen added to support
  240. // generalized line type behaviors.
  241. void T_MoveFloor(floormove_t* floor)
  242. {
  243. result_e res;
  244. res = T_MovePlane // move the floor
  245. (
  246. floor->sector,
  247. floor->speed,
  248. floor->floordestheight,
  249. floor->crush,
  250. 0,
  251. floor->direction
  252. );
  253. if (!(leveltime&7)) // make the floormove sound
  254. S_StartSound((mobj_t *)&floor->sector->soundorg, sfx_stnmov);
  255. if (res == pastdest) // if destination height is reached
  256. {
  257. if (floor->direction == 1) // going up
  258. {
  259. switch(floor->type) // handle texture/type changes
  260. {
  261. case donutRaise:
  262. floor->sector->special = floor->newspecial;
  263. floor->sector->floorpic = floor->texture;
  264. break;
  265. case genFloorChgT:
  266. case genFloorChg0:
  267. floor->sector->special = floor->newspecial;
  268. //jff add to fix bug in special transfers from changes
  269. floor->sector->oldspecial = floor->oldspecial;
  270. //fall thru
  271. case genFloorChg:
  272. floor->sector->floorpic = floor->texture;
  273. break;
  274. default:
  275. break;
  276. }
  277. }
  278. else if (floor->direction == -1) // going down
  279. {
  280. switch(floor->type) // handle texture/type changes
  281. {
  282. case lowerAndChange:
  283. floor->sector->special = floor->newspecial;
  284. //jff add to fix bug in special transfers from changes
  285. floor->sector->oldspecial = floor->oldspecial;
  286. floor->sector->floorpic = floor->texture;
  287. break;
  288. case genFloorChgT:
  289. case genFloorChg0:
  290. floor->sector->special = floor->newspecial;
  291. //jff add to fix bug in special transfers from changes
  292. floor->sector->oldspecial = floor->oldspecial;
  293. //fall thru
  294. case genFloorChg:
  295. floor->sector->floorpic = floor->texture;
  296. break;
  297. default:
  298. break;
  299. }
  300. }
  301. floor->sector->floordata = NULL; //jff 2/22/98
  302. P_RemoveThinker(&floor->thinker);//remove this floor from list of movers
  303. //jff 2/26/98 implement stair retrigger lockout while still building
  304. // note this only applies to the retriggerable generalized stairs
  305. if (floor->sector->stairlock==-2) // if this sector is stairlocked
  306. {
  307. sector_t *sec = floor->sector;
  308. sec->stairlock=-1; // thinker done, promote lock to -1
  309. while (sec->prevsec!=-1 && sectors[sec->prevsec].stairlock!=-2)
  310. sec = &sectors[sec->prevsec]; // search for a non-done thinker
  311. if (sec->prevsec==-1) // if all thinkers previous are done
  312. {
  313. sec = floor->sector; // search forward
  314. while (sec->nextsec!=-1 && sectors[sec->nextsec].stairlock!=-2)
  315. sec = &sectors[sec->nextsec];
  316. if (sec->nextsec==-1) // if all thinkers ahead are done too
  317. {
  318. while (sec->prevsec!=-1) // clear all locks
  319. {
  320. sec->stairlock = 0;
  321. sec = &sectors[sec->prevsec];
  322. }
  323. sec->stairlock = 0;
  324. }
  325. }
  326. }
  327. // make floor stop sound
  328. S_StartSound((mobj_t *)&floor->sector->soundorg, sfx_pstop);
  329. }
  330. }
  331. //
  332. // T_MoveElevator()
  333. //
  334. // Move an elevator to it's destination (up or down)
  335. // Called once per tick for each moving floor.
  336. //
  337. // Passed an elevator_t structure that contains all pertinent info about the
  338. // move. See P_SPEC.H for fields.
  339. // No return.
  340. //
  341. // jff 02/22/98 added to support parallel floor/ceiling motion
  342. //
  343. void T_MoveElevator(elevator_t* elevator)
  344. {
  345. result_e res;
  346. if (elevator->direction<0) // moving down
  347. {
  348. res = T_MovePlane //jff 4/7/98 reverse order of ceiling/floor
  349. (
  350. elevator->sector,
  351. elevator->speed,
  352. elevator->ceilingdestheight,
  353. 0,
  354. 1, // move floor
  355. elevator->direction
  356. );
  357. if (res==ok || res==pastdest) // jff 4/7/98 don't move ceil if blocked
  358. T_MovePlane
  359. (
  360. elevator->sector,
  361. elevator->speed,
  362. elevator->floordestheight,
  363. 0,
  364. 0, // move ceiling
  365. elevator->direction
  366. );
  367. }
  368. else // up
  369. {
  370. res = T_MovePlane //jff 4/7/98 reverse order of ceiling/floor
  371. (
  372. elevator->sector,
  373. elevator->speed,
  374. elevator->floordestheight,
  375. 0,
  376. 0, // move ceiling
  377. elevator->direction
  378. );
  379. if (res==ok || res==pastdest) // jff 4/7/98 don't move floor if blocked
  380. T_MovePlane
  381. (
  382. elevator->sector,
  383. elevator->speed,
  384. elevator->ceilingdestheight,
  385. 0,
  386. 1, // move floor
  387. elevator->direction
  388. );
  389. }
  390. // make floor move sound
  391. if (!(leveltime&7))
  392. S_StartSound((mobj_t *)&elevator->sector->soundorg, sfx_stnmov);
  393. if (res == pastdest) // if destination height acheived
  394. {
  395. elevator->sector->floordata = NULL; //jff 2/22/98
  396. elevator->sector->ceilingdata = NULL; //jff 2/22/98
  397. P_RemoveThinker(&elevator->thinker); // remove elevator from actives
  398. // make floor stop sound
  399. S_StartSound((mobj_t *)&elevator->sector->soundorg, sfx_pstop);
  400. }
  401. }
  402. ///////////////////////////////////////////////////////////////////////
  403. //
  404. // Floor motion linedef handlers
  405. //
  406. ///////////////////////////////////////////////////////////////////////
  407. //
  408. // EV_DoFloor()
  409. //
  410. // Handle regular and extended floor types
  411. //
  412. // Passed the line that activated the floor and the type of floor motion
  413. // Returns true if a thinker was created.
  414. //
  415. int EV_DoFloor
  416. ( line_t* line,
  417. floor_e floortype )
  418. {
  419. int secnum;
  420. int rtn;
  421. int i;
  422. sector_t* sec;
  423. floormove_t* floor;
  424. secnum = -1;
  425. rtn = 0;
  426. if (ProcessNoTagLines(line, &sec, &secnum)) {if (zerotag_manual) goto manual_floor; else {return rtn;}};//e6y
  427. // move all floors with the same tag as the linedef
  428. while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
  429. {
  430. sec = &sectors[secnum];
  431. manual_floor://e6y
  432. // Don't start a second thinker on the same floor
  433. if (P_SectorActive(floor_special,sec)) //jff 2/23/98
  434. { if (!zerotag_manual) continue; else return rtn; }//e6y
  435. // new floor thinker
  436. rtn = 1;
  437. floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
  438. memset(floor, 0, sizeof(*floor));
  439. P_AddThinker (&floor->thinker);
  440. sec->floordata = floor; //jff 2/22/98
  441. floor->thinker.function = T_MoveFloor;
  442. floor->type = floortype;
  443. floor->crush = false;
  444. // setup the thinker according to the linedef type
  445. switch(floortype)
  446. {
  447. case lowerFloor:
  448. floor->direction = -1;
  449. floor->sector = sec;
  450. floor->speed = FLOORSPEED;
  451. floor->floordestheight = P_FindHighestFloorSurrounding(sec);
  452. break;
  453. //jff 02/03/30 support lowering floor by 24 absolute
  454. case lowerFloor24:
  455. floor->direction = -1;
  456. floor->sector = sec;
  457. floor->speed = FLOORSPEED;
  458. floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT;
  459. break;
  460. //jff 02/03/30 support lowering floor by 32 absolute (fast)
  461. case lowerFloor32Turbo:
  462. floor->direction = -1;
  463. floor->sector = sec;
  464. floor->speed = FLOORSPEED*4;
  465. floor->floordestheight = floor->sector->floorheight + 32 * FRACUNIT;
  466. break;
  467. case lowerFloorToLowest:
  468. floor->direction = -1;
  469. floor->sector = sec;
  470. floor->speed = FLOORSPEED;
  471. floor->floordestheight = P_FindLowestFloorSurrounding(sec);
  472. break;
  473. //jff 02/03/30 support lowering floor to next lowest floor
  474. case lowerFloorToNearest:
  475. floor->direction = -1;
  476. floor->sector = sec;
  477. floor->speed = FLOORSPEED;
  478. floor->floordestheight =
  479. P_FindNextLowestFloor(sec,floor->sector->floorheight);
  480. break;
  481. case turboLower:
  482. floor->direction = -1;
  483. floor->sector = sec;
  484. floor->speed = FLOORSPEED * 4;
  485. floor->floordestheight = P_FindHighestFloorSurrounding(sec);
  486. if (compatibility_level == doom_12_compatibility ||
  487. floor->floordestheight != sec->floorheight)
  488. floor->floordestheight += 8*FRACUNIT;
  489. break;
  490. case raiseFloorCrush:
  491. floor->crush = true;
  492. case raiseFloor:
  493. floor->direction = 1;
  494. floor->sector = sec;
  495. floor->speed = FLOORSPEED;
  496. floor->floordestheight = P_FindLowestCeilingSurrounding(sec);
  497. if (floor->floordestheight > sec->ceilingheight)
  498. floor->floordestheight = sec->ceilingheight;
  499. floor->floordestheight -= (8*FRACUNIT)*(floortype == raiseFloorCrush);
  500. break;
  501. case raiseFloorTurbo:
  502. floor->direction = 1;
  503. floor->sector = sec;
  504. floor->speed = FLOORSPEED*4;
  505. floor->floordestheight = P_FindNextHighestFloor(sec,sec->floorheight);
  506. break;
  507. case raiseFloorToNearest:
  508. floor->direction = 1;
  509. floor->sector = sec;
  510. floor->speed = FLOORSPEED;
  511. floor->floordestheight = P_FindNextHighestFloor(sec,sec->floorheight);
  512. break;
  513. case raiseFloor24:
  514. floor->direction = 1;
  515. floor->sector = sec;
  516. floor->speed = FLOORSPEED;
  517. floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT;
  518. break;
  519. // jff 2/03/30 support straight raise by 32 (fast)
  520. case raiseFloor32Turbo:
  521. floor->direction = 1;
  522. floor->sector = sec;
  523. floor->speed = FLOORSPEED*4;
  524. floor->floordestheight = floor->sector->floorheight + 32 * FRACUNIT;
  525. break;
  526. case raiseFloor512:
  527. floor->direction = 1;
  528. floor->sector = sec;
  529. floor->speed = FLOORSPEED;
  530. floor->floordestheight = floor->sector->floorheight + 512 * FRACUNIT;
  531. break;
  532. case raiseFloor24AndChange:
  533. floor->direction = 1;
  534. floor->sector = sec;
  535. floor->speed = FLOORSPEED;
  536. floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT;
  537. sec->floorpic = line->frontsector->floorpic;
  538. sec->special = line->frontsector->special;
  539. //jff 3/14/98 transfer both old and new special
  540. sec->oldspecial = line->frontsector->oldspecial;
  541. break;
  542. case raiseToTexture:
  543. {
  544. int minsize = INT_MAX;
  545. side_t* side;
  546. /* jff 3/13/98 no ovf */
  547. if (!comp[comp_model]) minsize = 32000<<FRACBITS;
  548. floor->direction = 1;
  549. floor->sector = sec;
  550. floor->speed = FLOORSPEED;
  551. for (i = 0; i < sec->linecount; i++)
  552. {
  553. if (twoSided (secnum, i) )
  554. {
  555. side = getSide(secnum,i,0);
  556. // jff 8/14/98 don't scan texture 0, its not real
  557. if (side->bottomtexture > 0 ||
  558. (comp[comp_model] && !side->bottomtexture))
  559. if (textureheight[side->bottomtexture] < minsize)
  560. minsize = textureheight[side->bottomtexture];
  561. side = getSide(secnum,i,1);
  562. // jff 8/14/98 don't scan texture 0, its not real
  563. if (side->bottomtexture > 0 ||
  564. (comp[comp_model] && !side->bottomtexture))
  565. if (textureheight[side->bottomtexture] < minsize)
  566. minsize = textureheight[side->bottomtexture];
  567. }
  568. }
  569. if (comp[comp_model])
  570. floor->floordestheight = floor->sector->floorheight + minsize;
  571. else
  572. {
  573. floor->floordestheight =
  574. (floor->sector->floorheight>>FRACBITS) + (minsize>>FRACBITS);
  575. if (floor->floordestheight>32000)
  576. floor->floordestheight = 32000; //jff 3/13/98 do not
  577. floor->floordestheight<<=FRACBITS; // allow height overflow
  578. }
  579. }
  580. break;
  581. case lowerAndChange:
  582. floor->direction = -1;
  583. floor->sector = sec;
  584. floor->speed = FLOORSPEED;
  585. floor->floordestheight = P_FindLowestFloorSurrounding(sec);
  586. floor->texture = sec->floorpic;
  587. // jff 1/24/98 make sure floor->newspecial gets initialized
  588. // in case no surrounding sector is at floordestheight
  589. // --> should not affect compatibility <--
  590. floor->newspecial = sec->special;
  591. //jff 3/14/98 transfer both old and new special
  592. floor->oldspecial = sec->oldspecial;
  593. //jff 5/23/98 use model subroutine to unify fixes and handling
  594. sec = P_FindModelFloorSector(floor->floordestheight,sec->iSectorID);
  595. if (sec)
  596. {
  597. floor->texture = sec->floorpic;
  598. floor->newspecial = sec->special;
  599. //jff 3/14/98 transfer both old and new special
  600. floor->oldspecial = sec->oldspecial;
  601. }
  602. break;
  603. default:
  604. break;
  605. }
  606. if (zerotag_manual) return rtn; //e6y
  607. }
  608. return rtn;
  609. }
  610. //
  611. // EV_DoChange()
  612. //
  613. // Handle pure change types. These change floor texture and sector type
  614. // by trigger or numeric model without moving the floor.
  615. //
  616. // The linedef causing the change and the type of change is passed
  617. // Returns true if any sector changes
  618. //
  619. // jff 3/15/98 added to better support generalized sector types
  620. //
  621. int EV_DoChange
  622. ( line_t* line,
  623. change_e changetype )
  624. {
  625. int secnum;
  626. int rtn;
  627. sector_t* sec;
  628. sector_t* secm;
  629. secnum = -1;
  630. rtn = 0;
  631. // change all sectors with the same tag as the linedef
  632. while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
  633. {
  634. sec = &sectors[secnum];
  635. rtn = 1;
  636. // handle trigger or numeric change type
  637. switch(changetype)
  638. {
  639. case trigChangeOnly:
  640. sec->floorpic = line->frontsector->floorpic;
  641. sec->special = line->frontsector->special;
  642. sec->oldspecial = line->frontsector->oldspecial;
  643. break;
  644. case numChangeOnly:
  645. secm = P_FindModelFloorSector(sec->floorheight,secnum);
  646. if (secm) // if no model, no change
  647. {
  648. sec->floorpic = secm->floorpic;
  649. sec->special = secm->special;
  650. sec->oldspecial = secm->oldspecial;
  651. }
  652. break;
  653. default:
  654. break;
  655. }
  656. }
  657. return rtn;
  658. }
  659. /*
  660. * EV_BuildStairs()
  661. *
  662. * Handles staircase building. A sequence of sectors chosen by algorithm
  663. * rise at a speed indicated to a height that increases by the stepsize
  664. * each step.
  665. *
  666. * Passed the linedef triggering the stairs and the type of stair rise
  667. * Returns true if any thinkers are created
  668. *
  669. * cph 2001/09/21 - compatibility nightmares again
  670. * There are three different ways this function has, during its history, stepped
  671. * through all the stairs to be triggered by the single switch
  672. * - original Doom used a linear P_FindSectorFromLineTag, but failed to preserve
  673. * the index of the previous sector found, so instead it would restart its
  674. * linear search from the last sector of the previous staircase
  675. * - MBF/PrBoom with comp_stairs fail to emulate this, because their
  676. * P_FindSectorFromLineTag is a chained hash table implementation. Instead they
  677. * start following the hash chain from the last sector of the previous
  678. * staircase, which will (probably) have the wrong tag, so they miss any further
  679. * stairs
  680. * - Boom fixed the bug, and MBF/PrBoom without comp_stairs work right
  681. */
  682. static inline int P_FindSectorFromLineTagWithLowerBound
  683. (line_t* l, int start, int min)
  684. {
  685. /* Emulate original Doom's linear lower-bounded P_FindSectorFromLineTag
  686. * as needed */
  687. do {
  688. start = P_FindSectorFromLineTag(l,start);
  689. } while (start >= 0 && start <= min);
  690. return start;
  691. }
  692. int EV_BuildStairs
  693. ( line_t* line,
  694. stair_e type )
  695. {
  696. /* cph 2001/09/22 - cleaned up this function to save my sanity. A separate
  697. * outer loop index makes the logic much cleared, and local variables moved
  698. * into the inner blocks helps too */
  699. int ssec = -1;
  700. int minssec = -1;
  701. int rtn = 0;
  702. //e6y
  703. int secnum = -1;
  704. sector_t* sec;
  705. if (ProcessNoTagLines(line, &sec, &secnum)) {if (zerotag_manual) goto manual_stair; else {return rtn;}};//e6y
  706. // start a stair at each sector tagged the same as the linedef
  707. while ((ssec = P_FindSectorFromLineTagWithLowerBound(line,ssec,minssec)) >= 0)
  708. {
  709. //e6y int
  710. secnum = ssec;
  711. //e6y sector_t*
  712. sec = &sectors[secnum];
  713. manual_stair://e6y
  714. // don't start a stair if the first step's floor is already moving
  715. if (!P_SectorActive(floor_special,sec)) { //jff 2/22/98
  716. floormove_t* floor;
  717. int texture, height;
  718. fixed_t stairsize;
  719. fixed_t speed;
  720. int ok;
  721. // create new floor thinker for first step
  722. rtn = 1;
  723. floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
  724. memset(floor, 0, sizeof(*floor));
  725. P_AddThinker (&floor->thinker);
  726. sec->floordata = floor;
  727. floor->thinker.function = T_MoveFloor;
  728. floor->direction = 1;
  729. floor->sector = sec;
  730. floor->type = buildStair; //jff 3/31/98 do not leave uninited
  731. // set up the speed and stepsize according to the stairs type
  732. switch(type)
  733. {
  734. default: // killough -- prevent compiler warning
  735. case build8:
  736. speed = FLOORSPEED/4;
  737. stairsize = 8*FRACUNIT;
  738. if (!demo_compatibility)
  739. floor->crush = false; //jff 2/27/98 fix uninitialized crush field
  740. // e6y
  741. // Uninitialized crush field will not be equal to 0 or 1 (true)
  742. // with high probability. So, initialize it with any other value
  743. // There is no more desync on icarus.wad/ic29uv.lmp
  744. // http://competn.doom2.net/pub/sda/i-o/icuvlmps.zip
  745. // http://www.doomworld.com/idgames/index.php?id=5191
  746. else
  747. {
  748. if (!prboom_comp[PC_UNINITIALIZE_CRUSH_FIELD_FOR_STAIRS].state)
  749. floor->crush = STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE;
  750. }
  751. break;
  752. case turbo16:
  753. speed = FLOORSPEED*4;
  754. stairsize = 16*FRACUNIT;
  755. if (!demo_compatibility)
  756. floor->crush = true; //jff 2/27/98 fix uninitialized crush field
  757. // e6y
  758. // Uninitialized crush field will not be equal to 0 or 1 (true)
  759. // with high probability. So, initialize it with any other value
  760. else
  761. {
  762. if (!prboom_comp[PC_UNINITIALIZE_CRUSH_FIELD_FOR_STAIRS].state)
  763. floor->crush = STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE;
  764. }
  765. break;
  766. }
  767. floor->speed = speed;
  768. height = sec->floorheight + stairsize;
  769. floor->floordestheight = height;
  770. texture = sec->floorpic;
  771. // Find next sector to raise
  772. // 1. Find 2-sided line with same sector side[0] (lowest numbered)
  773. // 2. Other side is the next sector to raise
  774. // 3. Unless already moving, or different texture, then stop building
  775. do
  776. {
  777. int i;
  778. ok = 0;
  779. for (i = 0;i < sec->linecount;i++)
  780. {
  781. sector_t* tsec = (sec->lines[i])->frontsector;
  782. int newsecnum;
  783. if ( !((sec->lines[i])->flags & ML_TWOSIDED) )
  784. continue;
  785. newsecnum = tsec->iSectorID;
  786. if (secnum != newsecnum)
  787. continue;
  788. tsec = (sec->lines[i])->backsector;
  789. if (!tsec) continue; //jff 5/7/98 if no backside, continue
  790. newsecnum = tsec->iSectorID;
  791. // if sector's floor is different texture, look for another
  792. if (tsec->floorpic != texture)
  793. continue;
  794. /* jff 6/19/98 prevent double stepsize
  795. * killough 10/98: intentionally left this way [MBF comment]
  796. * cph 2001/02/06: stair bug fix should be controlled by comp_stairs,
  797. * except if we're emulating MBF which perversly reverted the fix
  798. */
  799. if (comp[comp_stairs] || (compatibility_level == mbf_compatibility))
  800. height += stairsize; // jff 6/28/98 change demo compatibility
  801. // if sector's floor already moving, look for another
  802. if (P_SectorActive(floor_special,tsec)) //jff 2/22/98
  803. continue;
  804. /* cph - see comment above - do this iff we didn't do so above */
  805. if (!comp[comp_stairs] && (compatibility_level != mbf_compatibility))
  806. height += stairsize;
  807. sec = tsec;
  808. secnum = newsecnum;
  809. // create and initialize a thinker for the next step
  810. floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
  811. memset(floor, 0, sizeof(*floor));
  812. P_AddThinker (&floor->thinker);
  813. sec->floordata = floor; //jff 2/22/98
  814. floor->thinker.function = T_MoveFloor;
  815. floor->direction = 1;
  816. floor->sector = sec;
  817. floor->speed = speed;
  818. floor->floordestheight = height;
  819. floor->type = buildStair; //jff 3/31/98 do not leave uninited
  820. //jff 2/27/98 fix uninitialized crush field
  821. if (!demo_compatibility)
  822. floor->crush = type==build8? false : true;
  823. // e6y
  824. // Uninitialized crush field will not be equal to 0 or 1 (true)
  825. // with high probability. So, initialize it with any other value
  826. else
  827. {
  828. if (!prboom_comp[PC_UNINITIALIZE_CRUSH_FIELD_FOR_STAIRS].state)
  829. floor->crush = STAIRS_UNINITIALIZED_CRUSH_FIELD_VALUE;
  830. }
  831. ok = 1;
  832. break;
  833. }
  834. } while(ok); // continue until no next step is found
  835. }
  836. /* killough 10/98: compatibility option */
  837. if (comp[comp_stairs]) {
  838. /* cph 2001/09/22 - emulate buggy MBF comp_stairs for demos, with logic
  839. * reversed since we now have a separate outer loop index.
  840. * DEMOSYNC - what about boom_compatibility_compatibility?
  841. */
  842. if ((compatibility_level >= mbf_compatibility) && (compatibility_level <
  843. prboom_3_compatibility)) ssec = secnum; /* Trash outer loop index */
  844. else {
  845. /* cph 2001/09/22 - now the correct comp_stairs - Doom used a linear
  846. * search from the last secnum, so we set that as a minimum value and do
  847. * a fresh tag search
  848. */
  849. ssec = -1; minssec = secnum;
  850. }
  851. }
  852. if (zerotag_manual) return rtn; //e6y
  853. }
  854. return rtn;
  855. }
  856. //
  857. // EV_DoDonut()
  858. //
  859. // Handle donut function: lower pillar, raise surrounding pool, both to height,
  860. // texture and type of the sector surrounding the pool.
  861. //
  862. // Passed the linedef that triggered the donut
  863. // Returns whether a thinker was created
  864. //
  865. int EV_DoDonut(line_t* line)
  866. {
  867. sector_t* s1;
  868. sector_t* s2;
  869. sector_t* s3;
  870. int secnum;
  871. int rtn;
  872. int i;
  873. floormove_t* floor;
  874. //e6y
  875. fixed_t s3_floorheight;
  876. short s3_floorpic;
  877. secnum = -1;
  878. rtn = 0;
  879. // do function on all sectors with same tag as linedef
  880. while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
  881. {
  882. s1 = &sectors[secnum]; // s1 is pillar's sector
  883. // do not start the donut if the pillar is already moving
  884. if (P_SectorActive(floor_special,s1)) //jff 2/22/98
  885. continue;
  886. s2 = getNextSector(s1->lines[0],s1); // s2 is pool's sector
  887. // note lowest numbered line around
  888. // pillar must be two-sided
  889. if (!s2)
  890. {
  891. if (demo_compatibility)
  892. {
  893. lprintf(LO_ERROR,
  894. "EV_DoDonut: lowest numbered line (linedef: %d) "
  895. "around pillar (sector: %d) must be two-sided. "
  896. "Unexpected behavior may occur in Vanilla Doom.\n",
  897. s1->lines[0]->iLineID, s1->iSectorID);
  898. continue;
  899. }
  900. else
  901. {
  902. continue;
  903. }
  904. }
  905. /* do not start the donut if the pool is already moving
  906. * cph - DEMOSYNC - was !compatibility */
  907. if (!comp[comp_floors] && P_SectorActive(floor_special,s2))
  908. continue; //jff 5/7/98
  909. // find a two sided line around the pool whose other side isn't the pillar
  910. for (i = 0;i < s2->linecount;i++)
  911. {
  912. //jff 3/29/98 use true two-sidedness, not the flag
  913. // killough 4/5/98: changed demo_compatibility to compatibility
  914. if (comp[comp_model])
  915. {
  916. // original code: !s2->lines[i]->flags & ML_TWOSIDED
  917. // equivalent to: (!s2->lines[i]->flags) & ML_TWOSIDED , i.e. 0
  918. // should be: !(s2->lines[i]->flags & ML_TWOSIDED)
  919. if (((!s2->lines[i]->flags) & ML_TWOSIDED) ||
  920. (s2->lines[i]->backsector == s1))
  921. continue;
  922. }
  923. else if (!s2->lines[i]->backsector || s2->lines[i]->backsector == s1)
  924. continue;
  925. rtn = 1; //jff 1/26/98 no donut action - no switch change on return
  926. s3 = s2->lines[i]->backsector; // s3 is model sector for changes
  927. if (!s3)
  928. {
  929. // e6y
  930. // s3->floorheight is an int at 0000:0000
  931. // s3->floorpic is a short at 0000:0008
  932. // Trying to emulate
  933. lprintf(LO_ERROR,
  934. "EV_DoDonut: Access violation at linedef %d, sector %d. "
  935. "Unexpected behavior may occur in Vanilla Doom.\n",
  936. line->iLineID, s1->iSectorID);
  937. if (DonutOverrun(&s3_floorheight, &s3_floorpic))
  938. {
  939. lprintf(LO_WARN, "EV_DoDonut: Emulated with floorheight %d, floor pic %d.\n",
  940. s3_floorheight >> 16, s3_floorpic);
  941. }
  942. else
  943. {
  944. lprintf(LO_WARN, "EV_DoDonut: Not emulated.\n");
  945. break;
  946. }
  947. }
  948. else
  949. {
  950. s3_floorheight = s3->floorheight;
  951. s3_floorpic = s3->floorpic;
  952. }
  953. // Spawn rising slime
  954. floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
  955. memset(floor, 0, sizeof(*floor));
  956. P_AddThinker (&floor->thinker);
  957. s2->floordata = floor; //jff 2/22/98
  958. floor->thinker.function = T_MoveFloor;
  959. floor->type = donutRaise;
  960. floor->crush = false;
  961. floor->direction = 1;
  962. floor->sector = s2;
  963. floor->speed = FLOORSPEED / 2;
  964. floor->texture = s3_floorpic;
  965. floor->newspecial = 0;
  966. floor->floordestheight = s3_floorheight;
  967. // Spawn lowering donut-hole pillar
  968. floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
  969. memset(floor, 0, sizeof(*floor));
  970. P_AddThinker (&floor->thinker);
  971. s1->floordata = floor; //jff 2/22/98
  972. floor->thinker.function = T_MoveFloor;
  973. floor->type = lowerFloor;
  974. floor->crush = false;
  975. floor->direction = -1;
  976. floor->sector = s1;
  977. floor->speed = FLOORSPEED / 2;
  978. floor->floordestheight = s3_floorheight;
  979. break;
  980. }
  981. }
  982. return rtn;
  983. }
  984. //
  985. // EV_DoElevator
  986. //
  987. // Handle elevator linedef types
  988. //
  989. // Passed the linedef that triggered the elevator and the elevator action
  990. //
  991. // jff 2/22/98 new type to move floor and ceiling in parallel
  992. //
  993. int EV_DoElevator
  994. ( line_t* line,
  995. elevator_e elevtype )
  996. {
  997. int secnum;
  998. int rtn;
  999. sector_t* sec;
  1000. elevator_t* elevator;
  1001. secnum = -1;
  1002. rtn = 0;
  1003. // act on all sectors with the same tag as the triggering linedef
  1004. while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
  1005. {
  1006. sec = &sectors[secnum];
  1007. // If either floor or ceiling is already activated, skip it
  1008. if (sec->floordata || sec->ceilingdata) //jff 2/22/98
  1009. continue;
  1010. // create and initialize new elevator thinker
  1011. rtn = 1;
  1012. elevator = Z_Malloc (sizeof(*elevator), PU_LEVSPEC, 0);
  1013. memset(elevator, 0, sizeof(*elevator));
  1014. P_AddThinker (&elevator->thinker);
  1015. sec->floordata = elevator; //jff 2/22/98
  1016. sec->ceilingdata = elevator; //jff 2/22/98
  1017. elevator->thinker.function = T_MoveElevator;
  1018. elevator->type = elevtype;
  1019. // set up the fields according to the type of elevator action
  1020. switch(elevtype)
  1021. {
  1022. // elevator down to next floor
  1023. case elevateDown:
  1024. elevator->direction = -1;
  1025. elevator->sector = sec;
  1026. elevator->speed = ELEVATORSPEED;
  1027. elevator->floordestheight =
  1028. P_FindNextLowestFloor(sec,sec->floorheight);
  1029. elevator->ceilingdestheight =
  1030. elevator->floordestheight + sec->ceilingheight - sec->floorheight;
  1031. break;
  1032. // elevator up to next floor
  1033. case elevateUp:
  1034. elevator->direction = 1;
  1035. elevator->sector = sec;
  1036. elevator->speed = ELEVATORSPEED;
  1037. elevator->floordestheight =
  1038. P_FindNextHighestFloor(sec,sec->floorheight);
  1039. elevator->ceilingdestheight =
  1040. elevator->floordestheight + sec->ceilingheight - sec->floorheight;
  1041. break;
  1042. // elevator to floor height of activating switch's front sector
  1043. case elevateCurrent:
  1044. elevator->sector = sec;
  1045. elevator->speed = ELEVATORSPEED;
  1046. elevator->floordestheight = line->frontsector->floorheight;
  1047. elevator->ceilingdestheight =
  1048. elevator->floordestheight + sec->ceilingheight - sec->floorheight;
  1049. elevator->direction =
  1050. elevator->floordestheight>sec->floorheight? 1 : -1;
  1051. break;
  1052. default:
  1053. break;
  1054. }
  1055. }
  1056. return rtn;
  1057. }