p_floor.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "Precompiled.h"
  21. #include "globaldata.h"
  22. #include "z_zone.h"
  23. #include "doomdef.h"
  24. #include "p_local.h"
  25. #include "s_sound.h"
  26. // State.
  27. #include "doomstat.h"
  28. #include "r_state.h"
  29. // Data.
  30. #include "sounds.h"
  31. //
  32. // FLOORS
  33. //
  34. //
  35. // Move a plane (floor or ceiling) and check for crushing
  36. //
  37. result_e
  38. T_MovePlane
  39. ( sector_t* sector,
  40. fixed_t speed,
  41. fixed_t dest,
  42. qboolean crush,
  43. int floorOrCeiling,
  44. int direction )
  45. {
  46. qboolean flag;
  47. fixed_t lastpos;
  48. switch(floorOrCeiling)
  49. {
  50. case 0:
  51. // FLOOR
  52. switch(direction)
  53. {
  54. case -1:
  55. // DOWN
  56. if (sector->floorheight - speed < dest)
  57. {
  58. lastpos = sector->floorheight;
  59. sector->floorheight = dest;
  60. flag = P_ChangeSector(sector,crush);
  61. if (flag == true)
  62. {
  63. sector->floorheight =lastpos;
  64. P_ChangeSector(sector,crush);
  65. //return crushed;
  66. }
  67. return pastdest;
  68. }
  69. else
  70. {
  71. lastpos = sector->floorheight;
  72. sector->floorheight -= speed;
  73. flag = P_ChangeSector(sector,crush);
  74. if (flag == true)
  75. {
  76. sector->floorheight = lastpos;
  77. P_ChangeSector(sector,crush);
  78. return crushed;
  79. }
  80. }
  81. break;
  82. case 1:
  83. // UP
  84. if (sector->floorheight + speed > dest)
  85. {
  86. lastpos = sector->floorheight;
  87. sector->floorheight = dest;
  88. flag = P_ChangeSector(sector,crush);
  89. if (flag == true)
  90. {
  91. sector->floorheight = lastpos;
  92. P_ChangeSector(sector,crush);
  93. //return crushed;
  94. }
  95. return pastdest;
  96. }
  97. else
  98. {
  99. // COULD GET CRUSHED
  100. lastpos = sector->floorheight;
  101. sector->floorheight += speed;
  102. flag = P_ChangeSector(sector,crush);
  103. if (flag == true)
  104. {
  105. if (crush == true)
  106. return crushed;
  107. sector->floorheight = lastpos;
  108. P_ChangeSector(sector,crush);
  109. return crushed;
  110. }
  111. }
  112. break;
  113. }
  114. break;
  115. case 1:
  116. // CEILING
  117. switch(direction)
  118. {
  119. case -1:
  120. // DOWN
  121. if (sector->ceilingheight - speed < dest)
  122. {
  123. lastpos = sector->ceilingheight;
  124. sector->ceilingheight = dest;
  125. flag = P_ChangeSector(sector,crush);
  126. if (flag == true)
  127. {
  128. sector->ceilingheight = lastpos;
  129. P_ChangeSector(sector,crush);
  130. //return crushed;
  131. }
  132. return pastdest;
  133. }
  134. else
  135. {
  136. // COULD GET CRUSHED
  137. lastpos = sector->ceilingheight;
  138. sector->ceilingheight -= speed;
  139. flag = P_ChangeSector(sector,crush);
  140. if (flag == true)
  141. {
  142. if (crush == true)
  143. return crushed;
  144. sector->ceilingheight = lastpos;
  145. P_ChangeSector(sector,crush);
  146. return crushed;
  147. }
  148. }
  149. break;
  150. case 1:
  151. // UP
  152. if (sector->ceilingheight + speed > dest)
  153. {
  154. lastpos = sector->ceilingheight;
  155. sector->ceilingheight = dest;
  156. flag = P_ChangeSector(sector,crush);
  157. if (flag == true)
  158. {
  159. sector->ceilingheight = lastpos;
  160. P_ChangeSector(sector,crush);
  161. //return crushed;
  162. }
  163. return pastdest;
  164. }
  165. else
  166. {
  167. lastpos = sector->ceilingheight;
  168. sector->ceilingheight += speed;
  169. flag = P_ChangeSector(sector,crush);
  170. // UNUSED
  171. #if 0
  172. if (flag == true)
  173. {
  174. sector->ceilingheight = lastpos;
  175. P_ChangeSector(sector,crush);
  176. return crushed;
  177. }
  178. #endif
  179. }
  180. break;
  181. }
  182. break;
  183. }
  184. return ok;
  185. }
  186. //
  187. // MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN)
  188. //
  189. void T_MoveFloor(floormove_t* floor)
  190. {
  191. result_e res;
  192. res = T_MovePlane(floor->sector,
  193. floor->speed,
  194. floor->floordestheight,
  195. floor->crush,0,floor->direction);
  196. if (!(::g->leveltime&7))
  197. S_StartSound( &floor->sector->soundorg,
  198. sfx_stnmov);
  199. if (res == pastdest)
  200. {
  201. floor->sector->specialdata = NULL;
  202. if (floor->direction == 1)
  203. {
  204. switch(floor->type)
  205. {
  206. case donutRaise:
  207. floor->sector->special = floor->newspecial;
  208. floor->sector->floorpic = floor->texture;
  209. default:
  210. break;
  211. }
  212. }
  213. else if (floor->direction == -1)
  214. {
  215. switch(floor->type)
  216. {
  217. case lowerAndChange:
  218. floor->sector->special = floor->newspecial;
  219. floor->sector->floorpic = floor->texture;
  220. default:
  221. break;
  222. }
  223. }
  224. P_RemoveThinker(&floor->thinker);
  225. S_StartSound( &floor->sector->soundorg,
  226. sfx_pstop);
  227. }
  228. }
  229. //
  230. // HANDLE FLOOR TYPES
  231. //
  232. int
  233. EV_DoFloor
  234. ( line_t* line,
  235. floor_e floortype )
  236. {
  237. int secnum;
  238. int rtn;
  239. int i;
  240. sector_t* sec;
  241. floormove_t* floor;
  242. secnum = -1;
  243. rtn = 0;
  244. while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
  245. {
  246. sec = &::g->sectors[secnum];
  247. // ALREADY MOVING? IF SO, KEEP GOING...
  248. if (sec->specialdata)
  249. continue;
  250. // new floor thinker
  251. rtn = 1;
  252. floor = (floormove_t*)DoomLib::Z_Malloc(sizeof(*floor), PU_LEVEL, 0);
  253. P_AddThinker (&floor->thinker);
  254. sec->specialdata = floor;
  255. floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
  256. floor->type = floortype;
  257. floor->crush = false;
  258. switch(floortype)
  259. {
  260. case lowerFloor:
  261. floor->direction = -1;
  262. floor->sector = sec;
  263. floor->speed = FLOORSPEED;
  264. floor->floordestheight =
  265. P_FindHighestFloorSurrounding(sec);
  266. break;
  267. case lowerFloorToLowest:
  268. floor->direction = -1;
  269. floor->sector = sec;
  270. floor->speed = FLOORSPEED;
  271. floor->floordestheight =
  272. P_FindLowestFloorSurrounding(sec);
  273. break;
  274. case turboLower:
  275. floor->direction = -1;
  276. floor->sector = sec;
  277. floor->speed = FLOORSPEED * 4;
  278. floor->floordestheight =
  279. P_FindHighestFloorSurrounding(sec);
  280. if (floor->floordestheight != sec->floorheight)
  281. floor->floordestheight += 8*FRACUNIT;
  282. break;
  283. case raiseFloorCrush:
  284. floor->crush = true;
  285. case raiseFloor:
  286. floor->direction = 1;
  287. floor->sector = sec;
  288. floor->speed = FLOORSPEED;
  289. floor->floordestheight =
  290. P_FindLowestCeilingSurrounding(sec);
  291. if (floor->floordestheight > sec->ceilingheight)
  292. floor->floordestheight = sec->ceilingheight;
  293. floor->floordestheight -= (8*FRACUNIT)*
  294. (floortype == raiseFloorCrush);
  295. break;
  296. case raiseFloorTurbo:
  297. floor->direction = 1;
  298. floor->sector = sec;
  299. floor->speed = FLOORSPEED*4;
  300. floor->floordestheight =
  301. P_FindNextHighestFloor(sec,sec->floorheight);
  302. break;
  303. case raiseFloorToNearest:
  304. floor->direction = 1;
  305. floor->sector = sec;
  306. floor->speed = FLOORSPEED;
  307. floor->floordestheight =
  308. P_FindNextHighestFloor(sec,sec->floorheight);
  309. break;
  310. case raiseFloor24:
  311. floor->direction = 1;
  312. floor->sector = sec;
  313. floor->speed = FLOORSPEED;
  314. floor->floordestheight = floor->sector->floorheight +
  315. 24 * FRACUNIT;
  316. break;
  317. case raiseFloor512:
  318. floor->direction = 1;
  319. floor->sector = sec;
  320. floor->speed = FLOORSPEED;
  321. floor->floordestheight = floor->sector->floorheight +
  322. 512 * FRACUNIT;
  323. break;
  324. case raiseFloor24AndChange:
  325. floor->direction = 1;
  326. floor->sector = sec;
  327. floor->speed = FLOORSPEED;
  328. floor->floordestheight = floor->sector->floorheight +
  329. 24 * FRACUNIT;
  330. sec->floorpic = line->frontsector->floorpic;
  331. sec->special = line->frontsector->special;
  332. break;
  333. case raiseToTexture:
  334. {
  335. int minsize = MAXINT;
  336. side_t* side;
  337. floor->direction = 1;
  338. floor->sector = sec;
  339. floor->speed = FLOORSPEED;
  340. for (i = 0; i < sec->linecount; i++)
  341. {
  342. if (twoSided (secnum, i) )
  343. {
  344. side = getSide(secnum,i,0);
  345. if (side->bottomtexture >= 0)
  346. if (::g->s_textureheight[side->bottomtexture] <
  347. minsize)
  348. minsize =
  349. ::g->s_textureheight[side->bottomtexture];
  350. side = getSide(secnum,i,1);
  351. if (side->bottomtexture >= 0)
  352. if (::g->s_textureheight[side->bottomtexture] <
  353. minsize)
  354. minsize =
  355. ::g->s_textureheight[side->bottomtexture];
  356. }
  357. }
  358. floor->floordestheight =
  359. floor->sector->floorheight + minsize;
  360. }
  361. break;
  362. case lowerAndChange:
  363. floor->direction = -1;
  364. floor->sector = sec;
  365. floor->speed = FLOORSPEED;
  366. floor->floordestheight =
  367. P_FindLowestFloorSurrounding(sec);
  368. floor->texture = sec->floorpic;
  369. for (i = 0; i < sec->linecount; i++)
  370. {
  371. if ( twoSided(secnum, i) )
  372. {
  373. if (getSide(secnum,i,0)->sector-::g->sectors == secnum)
  374. {
  375. sec = getSector(secnum,i,1);
  376. if (sec->floorheight == floor->floordestheight)
  377. {
  378. floor->texture = sec->floorpic;
  379. floor->newspecial = sec->special;
  380. break;
  381. }
  382. }
  383. else
  384. {
  385. sec = getSector(secnum,i,0);
  386. if (sec->floorheight == floor->floordestheight)
  387. {
  388. floor->texture = sec->floorpic;
  389. floor->newspecial = sec->special;
  390. break;
  391. }
  392. }
  393. }
  394. }
  395. default:
  396. break;
  397. }
  398. }
  399. return rtn;
  400. }
  401. //
  402. // BUILD A STAIRCASE!
  403. //
  404. int
  405. EV_BuildStairs
  406. ( line_t* line,
  407. stair_e type )
  408. {
  409. int secnum;
  410. int height;
  411. int i;
  412. int newsecnum;
  413. int texture;
  414. int ok;
  415. int rtn;
  416. sector_t* sec;
  417. sector_t* tsec;
  418. floormove_t* floor;
  419. fixed_t stairsize = 0;
  420. fixed_t speed = 0;
  421. secnum = -1;
  422. rtn = 0;
  423. while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
  424. {
  425. sec = &::g->sectors[secnum];
  426. // ALREADY MOVING? IF SO, KEEP GOING...
  427. if (sec->specialdata)
  428. continue;
  429. // new floor thinker
  430. rtn = 1;
  431. floor = (floormove_t*)DoomLib::Z_Malloc(sizeof(*floor), PU_LEVEL, 0);
  432. P_AddThinker (&floor->thinker);
  433. sec->specialdata = floor;
  434. floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
  435. floor->direction = 1;
  436. floor->sector = sec;
  437. switch(type)
  438. {
  439. case build8:
  440. speed = FLOORSPEED/4;
  441. stairsize = 8*FRACUNIT;
  442. break;
  443. case turbo16:
  444. speed = FLOORSPEED*4;
  445. stairsize = 16*FRACUNIT;
  446. break;
  447. }
  448. floor->speed = speed;
  449. height = sec->floorheight + stairsize;
  450. floor->floordestheight = height;
  451. texture = sec->floorpic;
  452. // Find next sector to raise
  453. // 1. Find 2-sided line with same sector side[0]
  454. // 2. Other side is the next sector to raise
  455. do
  456. {
  457. ok = 0;
  458. for (i = 0;i < sec->linecount;i++)
  459. {
  460. if ( !((sec->lines[i])->flags & ML_TWOSIDED) )
  461. continue;
  462. tsec = (sec->lines[i])->frontsector;
  463. newsecnum = tsec-::g->sectors;
  464. if (secnum != newsecnum)
  465. continue;
  466. tsec = (sec->lines[i])->backsector;
  467. newsecnum = tsec - ::g->sectors;
  468. if (tsec->floorpic != texture)
  469. continue;
  470. height += stairsize;
  471. if (tsec->specialdata)
  472. continue;
  473. sec = tsec;
  474. secnum = newsecnum;
  475. floor = (floormove_t*)DoomLib::Z_Malloc(sizeof(*floor), PU_LEVEL, 0);
  476. P_AddThinker (&floor->thinker);
  477. sec->specialdata = floor;
  478. floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
  479. floor->direction = 1;
  480. floor->sector = sec;
  481. floor->speed = speed;
  482. floor->floordestheight = height;
  483. ok = 1;
  484. break;
  485. }
  486. } while(ok);
  487. }
  488. return rtn;
  489. }