P_FLOOR.C 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932
  1. //**************************************************************************
  2. //**
  3. //** p_floor.c : Heretic 2 : Raven Software, Corp.
  4. //**
  5. //** $RCSfile: p_floor.c,v $
  6. //** $Revision: 1.23 $
  7. //** $Date: 95/10/06 16:53:19 $
  8. //** $Author: paul $
  9. //**
  10. //**************************************************************************
  11. #include "h2def.h"
  12. #include "p_local.h"
  13. #include "soundst.h"
  14. extern fixed_t FloatBobOffsets[64];
  15. //==================================================================
  16. //==================================================================
  17. //
  18. // FLOORS
  19. //
  20. //==================================================================
  21. //==================================================================
  22. //==================================================================
  23. //
  24. // Move a plane (floor or ceiling) and check for crushing
  25. //
  26. //==================================================================
  27. result_e T_MovePlane(sector_t *sector,fixed_t speed,
  28. fixed_t dest, int crush,int floorOrCeiling,int direction)
  29. {
  30. boolean flag;
  31. fixed_t lastpos;
  32. switch(floorOrCeiling)
  33. {
  34. case 0: // FLOOR
  35. switch(direction)
  36. {
  37. case -1: // DOWN
  38. if (sector->floorheight - speed < dest)
  39. {
  40. lastpos = sector->floorheight;
  41. sector->floorheight = dest;
  42. flag = P_ChangeSector(sector,crush);
  43. if (flag == true)
  44. {
  45. sector->floorheight =lastpos;
  46. P_ChangeSector(sector,crush);
  47. //return RES_CRUSHED;
  48. }
  49. return RES_PASTDEST;
  50. }
  51. else
  52. {
  53. lastpos = sector->floorheight;
  54. sector->floorheight -= speed;
  55. flag = P_ChangeSector(sector,crush);
  56. if (flag == true)
  57. {
  58. sector->floorheight = lastpos;
  59. P_ChangeSector(sector,crush);
  60. return RES_CRUSHED;
  61. }
  62. }
  63. break;
  64. case 1: // UP
  65. if (sector->floorheight + speed > dest)
  66. {
  67. lastpos = sector->floorheight;
  68. sector->floorheight = dest;
  69. flag = P_ChangeSector(sector,crush);
  70. if (flag == true)
  71. {
  72. sector->floorheight = lastpos;
  73. P_ChangeSector(sector,crush);
  74. //return RES_CRUSHED;
  75. }
  76. return RES_PASTDEST;
  77. }
  78. else // COULD GET CRUSHED
  79. {
  80. lastpos = sector->floorheight;
  81. sector->floorheight += speed;
  82. flag = P_ChangeSector(sector,crush);
  83. if (flag == true)
  84. {
  85. //if (crush == true)
  86. //{
  87. // return RES_CRUSHED;
  88. //}
  89. sector->floorheight = lastpos;
  90. P_ChangeSector(sector,crush);
  91. return RES_CRUSHED;
  92. }
  93. }
  94. break;
  95. }
  96. break;
  97. case 1: // CEILING
  98. switch(direction)
  99. {
  100. case -1: // DOWN
  101. if (sector->ceilingheight - speed < dest)
  102. {
  103. lastpos = sector->ceilingheight;
  104. sector->ceilingheight = dest;
  105. flag = P_ChangeSector(sector,crush);
  106. if (flag == true)
  107. {
  108. sector->ceilingheight = lastpos;
  109. P_ChangeSector(sector,crush);
  110. //return RES_CRUSHED;
  111. }
  112. return RES_PASTDEST;
  113. }
  114. else // COULD GET CRUSHED
  115. {
  116. lastpos = sector->ceilingheight;
  117. sector->ceilingheight -= speed;
  118. flag = P_ChangeSector(sector,crush);
  119. if (flag == true)
  120. {
  121. //if (crush == true)
  122. //{
  123. // return RES_CRUSHED;
  124. //}
  125. sector->ceilingheight = lastpos;
  126. P_ChangeSector(sector,crush);
  127. return RES_CRUSHED;
  128. }
  129. }
  130. break;
  131. case 1: // UP
  132. if (sector->ceilingheight + speed > dest)
  133. {
  134. lastpos = sector->ceilingheight;
  135. sector->ceilingheight = dest;
  136. flag = P_ChangeSector(sector,crush);
  137. if (flag == true)
  138. {
  139. sector->ceilingheight = lastpos;
  140. P_ChangeSector(sector,crush);
  141. //return RES_CRUSHED;
  142. }
  143. return RES_PASTDEST;
  144. }
  145. else
  146. {
  147. lastpos = sector->ceilingheight;
  148. sector->ceilingheight += speed;
  149. flag = P_ChangeSector(sector,crush);
  150. #if 0
  151. if (flag == true)
  152. {
  153. sector->ceilingheight = lastpos;
  154. P_ChangeSector(sector,crush);
  155. return RES_CRUSHED;
  156. }
  157. #endif
  158. }
  159. break;
  160. }
  161. break;
  162. }
  163. return RES_OK;
  164. }
  165. //==================================================================
  166. //
  167. // MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN)
  168. //
  169. //==================================================================
  170. void T_MoveFloor(floormove_t *floor)
  171. {
  172. result_e res;
  173. if(floor->resetDelayCount)
  174. {
  175. floor->resetDelayCount--;
  176. if(!floor->resetDelayCount)
  177. {
  178. floor->floordestheight = floor->resetHeight;
  179. floor->direction = -floor->direction;
  180. floor->resetDelay = 0;
  181. floor->delayCount = 0;
  182. floor->delayTotal = 0;
  183. }
  184. }
  185. if(floor->delayCount)
  186. {
  187. floor->delayCount--;
  188. if(!floor->delayCount && floor->textureChange)
  189. {
  190. floor->sector->floorpic += floor->textureChange;
  191. }
  192. return;
  193. }
  194. res = T_MovePlane(floor->sector,floor->speed,
  195. floor->floordestheight,floor->crush,0,floor->direction);
  196. if(floor->type == FLEV_RAISEBUILDSTEP)
  197. {
  198. if((floor->direction == 1 && floor->sector->floorheight >=
  199. floor->stairsDelayHeight) || (floor->direction == -1 &&
  200. floor->sector->floorheight <= floor->stairsDelayHeight))
  201. {
  202. floor->delayCount = floor->delayTotal;
  203. floor->stairsDelayHeight += floor->stairsDelayHeightDelta;
  204. }
  205. }
  206. if (res == RES_PASTDEST)
  207. {
  208. SN_StopSequence((mobj_t *)&floor->sector->soundorg);
  209. if(floor->delayTotal)
  210. {
  211. floor->delayTotal = 0;
  212. }
  213. if(floor->resetDelay)
  214. {
  215. // floor->resetDelayCount = floor->resetDelay;
  216. // floor->resetDelay = 0;
  217. return;
  218. }
  219. floor->sector->specialdata = NULL;
  220. /*
  221. if (floor->direction == 1)
  222. switch(floor->type)
  223. {
  224. case donutRaise:
  225. floor->sector->special = floor->newspecial;
  226. floor->sector->floorpic = floor->texture;
  227. default:
  228. break;
  229. }
  230. else if (floor->direction == -1)
  231. switch(floor->type)
  232. {
  233. case lowerAndChange:
  234. floor->sector->special = floor->newspecial;
  235. floor->sector->floorpic = floor->texture;
  236. default:
  237. break;
  238. }
  239. */
  240. if(floor->textureChange)
  241. {
  242. floor->sector->floorpic -= floor->textureChange;
  243. }
  244. P_TagFinished(floor->sector->tag);
  245. P_RemoveThinker(&floor->thinker);
  246. }
  247. }
  248. //==================================================================
  249. //
  250. // HANDLE FLOOR TYPES
  251. //
  252. //==================================================================
  253. int EV_DoFloor(line_t *line, byte *args, floor_e floortype)
  254. {
  255. int secnum;
  256. int rtn;
  257. sector_t *sec;
  258. floormove_t *floor=NULL;
  259. secnum = -1;
  260. rtn = 0;
  261. while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
  262. {
  263. sec = &sectors[secnum];
  264. // ALREADY MOVING? IF SO, KEEP GOING...
  265. if (sec->specialdata)
  266. continue;
  267. //
  268. // new floor thinker
  269. //
  270. rtn = 1;
  271. floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
  272. memset(floor, 0, sizeof(*floor));
  273. P_AddThinker (&floor->thinker);
  274. sec->specialdata = floor;
  275. floor->thinker.function = T_MoveFloor;
  276. floor->type = floortype;
  277. floor->crush = 0;
  278. floor->speed = args[1]*(FRACUNIT/8);
  279. if(floortype == FLEV_LOWERTIMES8INSTANT ||
  280. floortype == FLEV_RAISETIMES8INSTANT)
  281. {
  282. floor->speed = 2000<<FRACBITS;
  283. }
  284. switch(floortype)
  285. {
  286. case FLEV_LOWERFLOOR:
  287. floor->direction = -1;
  288. floor->sector = sec;
  289. floor->floordestheight =
  290. P_FindHighestFloorSurrounding(sec);
  291. break;
  292. case FLEV_LOWERFLOORTOLOWEST:
  293. floor->direction = -1;
  294. floor->sector = sec;
  295. floor->floordestheight =
  296. P_FindLowestFloorSurrounding(sec);
  297. break;
  298. case FLEV_LOWERFLOORBYVALUE:
  299. floor->direction = -1;
  300. floor->sector = sec;
  301. floor->floordestheight = floor->sector->floorheight-
  302. args[2]*FRACUNIT;
  303. break;
  304. case FLEV_LOWERTIMES8INSTANT:
  305. case FLEV_LOWERBYVALUETIMES8:
  306. floor->direction = -1;
  307. floor->sector = sec;
  308. floor->floordestheight = floor->sector->floorheight-
  309. args[2]*FRACUNIT*8;
  310. break;
  311. case FLEV_RAISEFLOORCRUSH:
  312. floor->crush = args[2]; // arg[2] = crushing value
  313. floor->direction = 1;
  314. floor->sector = sec;
  315. floor->floordestheight = sec->ceilingheight-8*FRACUNIT;
  316. break;
  317. case FLEV_RAISEFLOOR:
  318. floor->direction = 1;
  319. floor->sector = sec;
  320. floor->floordestheight =
  321. P_FindLowestCeilingSurrounding(sec);
  322. if (floor->floordestheight > sec->ceilingheight)
  323. floor->floordestheight = sec->ceilingheight;
  324. break;
  325. case FLEV_RAISEFLOORTONEAREST:
  326. floor->direction = 1;
  327. floor->sector = sec;
  328. floor->floordestheight =
  329. P_FindNextHighestFloor(sec,sec->floorheight);
  330. break;
  331. case FLEV_RAISEFLOORBYVALUE:
  332. floor->direction = 1;
  333. floor->sector = sec;
  334. floor->floordestheight = floor->sector->floorheight+
  335. args[2]*FRACUNIT;
  336. break;
  337. case FLEV_RAISETIMES8INSTANT:
  338. case FLEV_RAISEBYVALUETIMES8:
  339. floor->direction = 1;
  340. floor->sector = sec;
  341. floor->floordestheight = floor->sector->floorheight+
  342. args[2]*FRACUNIT*8;
  343. break;
  344. case FLEV_MOVETOVALUETIMES8:
  345. floor->sector = sec;
  346. floor->floordestheight = args[2]*FRACUNIT*8;
  347. if(args[3])
  348. {
  349. floor->floordestheight = -floor->floordestheight;
  350. }
  351. if(floor->floordestheight > floor->sector->floorheight)
  352. {
  353. floor->direction = 1;
  354. }
  355. else if(floor->floordestheight < floor->sector->floorheight)
  356. {
  357. floor->direction = -1;
  358. }
  359. else
  360. { // already at lowest position
  361. rtn = 0;
  362. }
  363. break;
  364. default:
  365. rtn = 0;
  366. break;
  367. }
  368. }
  369. if(rtn)
  370. {
  371. SN_StartSequence((mobj_t *)&floor->sector->soundorg,
  372. SEQ_PLATFORM+floor->sector->seqType);
  373. }
  374. return rtn;
  375. }
  376. //============================================================================
  377. //
  378. // EV_DoFloorAndCeiling
  379. //
  380. //============================================================================
  381. int EV_DoFloorAndCeiling(line_t *line, byte *args, boolean raise)
  382. {
  383. boolean floor, ceiling;
  384. int secnum;
  385. sector_t *sec;
  386. if(raise)
  387. {
  388. floor = EV_DoFloor(line, args, FLEV_RAISEFLOORBYVALUE);
  389. secnum = -1;
  390. while((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
  391. {
  392. sec = &sectors[secnum];
  393. sec->specialdata = NULL;
  394. }
  395. ceiling = EV_DoCeiling(line, args, CLEV_RAISEBYVALUE);
  396. }
  397. else
  398. {
  399. floor = EV_DoFloor(line, args, FLEV_LOWERFLOORBYVALUE);
  400. secnum = -1;
  401. while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
  402. {
  403. sec = &sectors[secnum];
  404. sec->specialdata = NULL;
  405. }
  406. ceiling = EV_DoCeiling(line, args, CLEV_LOWERBYVALUE);
  407. }
  408. return (floor|ceiling);
  409. }
  410. // ===== Build Stairs Private Data =====
  411. #define STAIR_SECTOR_TYPE 26
  412. #define STAIR_QUEUE_SIZE 32
  413. struct
  414. {
  415. sector_t *sector;
  416. int type;
  417. int height;
  418. } StairQueue[STAIR_QUEUE_SIZE];
  419. static int QueueHead;
  420. static int QueueTail;
  421. static int StepDelta;
  422. static int Direction;
  423. static int Speed;
  424. static int Texture;
  425. static int StartDelay;
  426. static int StartDelayDelta;
  427. static int TextureChange;
  428. static int StartHeight;
  429. //==========================================================================
  430. //
  431. // QueueStairSector
  432. //
  433. //==========================================================================
  434. static void QueueStairSector(sector_t *sec, int type, int height)
  435. {
  436. if((QueueTail+1)%STAIR_QUEUE_SIZE == QueueHead)
  437. {
  438. I_Error("BuildStairs: Too many branches located.\n");
  439. }
  440. StairQueue[QueueTail].sector = sec;
  441. StairQueue[QueueTail].type = type;
  442. StairQueue[QueueTail].height = height;
  443. QueueTail = (QueueTail+1)%STAIR_QUEUE_SIZE;
  444. }
  445. //==========================================================================
  446. //
  447. // DequeueStairSector
  448. //
  449. //==========================================================================
  450. static sector_t *DequeueStairSector(int *type, int *height)
  451. {
  452. sector_t *sec;
  453. if(QueueHead == QueueTail)
  454. { // queue is empty
  455. return NULL;
  456. }
  457. *type = StairQueue[QueueHead].type;
  458. *height = StairQueue[QueueHead].height;
  459. sec = StairQueue[QueueHead].sector;
  460. QueueHead = (QueueHead+1)%STAIR_QUEUE_SIZE;
  461. return sec;
  462. }
  463. //==========================================================================
  464. //
  465. // ProcessStairSector
  466. //
  467. //==========================================================================
  468. static void ProcessStairSector(sector_t *sec, int type, int height,
  469. stairs_e stairsType, int delay, int resetDelay)
  470. {
  471. int i;
  472. sector_t *tsec;
  473. floormove_t *floor;
  474. //
  475. // new floor thinker
  476. //
  477. height += StepDelta;
  478. floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0);
  479. memset(floor, 0, sizeof(*floor));
  480. P_AddThinker(&floor->thinker);
  481. sec->specialdata = floor;
  482. floor->thinker.function = T_MoveFloor;
  483. floor->type = FLEV_RAISEBUILDSTEP;
  484. floor->direction = Direction;
  485. floor->sector = sec;
  486. floor->floordestheight = height;
  487. switch(stairsType)
  488. {
  489. case STAIRS_NORMAL:
  490. floor->speed = Speed;
  491. if(delay)
  492. {
  493. floor->delayTotal = delay;
  494. floor->stairsDelayHeight = sec->floorheight+StepDelta;
  495. floor->stairsDelayHeightDelta = StepDelta;
  496. }
  497. floor->resetDelay = resetDelay;
  498. floor->resetDelayCount = resetDelay;
  499. floor->resetHeight = sec->floorheight;
  500. break;
  501. case STAIRS_SYNC:
  502. floor->speed = FixedMul(Speed, FixedDiv(height-StartHeight,
  503. StepDelta));
  504. floor->resetDelay = delay; //arg4
  505. floor->resetDelayCount = delay;
  506. floor->resetHeight = sec->floorheight;
  507. break;
  508. /*
  509. case STAIRS_PHASED:
  510. floor->floordestheight = sec->floorheight+StepDelta;
  511. floor->speed = Speed;
  512. floor->delayCount = StartDelay;
  513. StartDelay += StartDelayDelta;
  514. floor->textureChange = TextureChange;
  515. floor->resetDelayCount = StartDelay;
  516. break;
  517. */
  518. default:
  519. break;
  520. }
  521. SN_StartSequence((mobj_t *)&sec->soundorg, SEQ_PLATFORM+sec->seqType);
  522. //
  523. // Find next sector to raise
  524. // Find nearby sector with sector special equal to type
  525. //
  526. for (i = 0; i < sec->linecount; i++)
  527. {
  528. if(!((sec->lines[i])->flags&ML_TWOSIDED))
  529. {
  530. continue;
  531. }
  532. tsec = (sec->lines[i])->frontsector;
  533. if(tsec->special == type+STAIR_SECTOR_TYPE && !tsec->specialdata
  534. && tsec->floorpic == Texture && tsec->validcount != validcount)
  535. {
  536. QueueStairSector(tsec, type^1, height);
  537. tsec->validcount = validcount;
  538. //tsec->special = 0;
  539. }
  540. tsec = (sec->lines[i])->backsector;
  541. if(tsec->special == type+STAIR_SECTOR_TYPE && !tsec->specialdata
  542. && tsec->floorpic == Texture && tsec->validcount != validcount)
  543. {
  544. QueueStairSector(tsec, type^1, height);
  545. tsec->validcount = validcount;
  546. //tsec->special = 0;
  547. }
  548. }
  549. }
  550. //==================================================================
  551. //
  552. // BUILD A STAIRCASE!
  553. //
  554. // Direction is either positive or negative, denoting build stairs
  555. // up or down.
  556. //==================================================================
  557. int EV_BuildStairs(line_t *line, byte *args, int direction,
  558. stairs_e stairsType)
  559. {
  560. int secnum;
  561. int height;
  562. int delay;
  563. int resetDelay;
  564. sector_t *sec;
  565. sector_t *qSec;
  566. int type;
  567. // Set global stairs variables
  568. TextureChange = 0;
  569. Direction = direction;
  570. StepDelta = Direction*(args[2]*FRACUNIT);
  571. Speed = args[1]*(FRACUNIT/8);
  572. resetDelay = args[4];
  573. delay = args[3];
  574. if(stairsType == STAIRS_PHASED)
  575. {
  576. StartDelayDelta = args[3];
  577. StartDelay = StartDelayDelta;
  578. resetDelay = StartDelayDelta;
  579. delay = 0;
  580. TextureChange = args[4];
  581. }
  582. secnum = -1;
  583. validcount++;
  584. while ((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
  585. {
  586. sec = &sectors[secnum];
  587. Texture = sec->floorpic;
  588. StartHeight = sec->floorheight;
  589. // ALREADY MOVING? IF SO, KEEP GOING...
  590. if (sec->specialdata)
  591. continue;
  592. QueueStairSector(sec, 0, sec->floorheight);
  593. sec->special = 0;
  594. }
  595. while((qSec = DequeueStairSector(&type, &height)) != NULL)
  596. {
  597. ProcessStairSector(qSec, type, height, stairsType, delay, resetDelay);
  598. }
  599. return(1);
  600. }
  601. //=========================================================================
  602. //
  603. // T_BuildPillar
  604. //
  605. //=========================================================================
  606. void T_BuildPillar(pillar_t *pillar)
  607. {
  608. result_e res1;
  609. result_e res2;
  610. // First, raise the floor
  611. res1 = T_MovePlane(pillar->sector, pillar->floorSpeed, pillar->floordest,
  612. pillar->crush, 0, pillar->direction); // floorOrCeiling, direction
  613. // Then, lower the ceiling
  614. res2 = T_MovePlane(pillar->sector, pillar->ceilingSpeed,
  615. pillar->ceilingdest, pillar->crush, 1, -pillar->direction);
  616. if (res1 == RES_PASTDEST && res2 == RES_PASTDEST)
  617. {
  618. pillar->sector->specialdata = NULL;
  619. SN_StopSequence((mobj_t *)&pillar->sector->soundorg);
  620. P_TagFinished(pillar->sector->tag);
  621. P_RemoveThinker(&pillar->thinker);
  622. }
  623. }
  624. //=========================================================================
  625. //
  626. // EV_BuildPillar
  627. //
  628. //=========================================================================
  629. int EV_BuildPillar(line_t *line, byte *args, boolean crush)
  630. {
  631. int secnum;
  632. sector_t *sec;
  633. pillar_t *pillar;
  634. int newHeight;
  635. int rtn;
  636. rtn = 0;
  637. secnum = -1;
  638. while((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
  639. {
  640. sec = &sectors[secnum];
  641. if(sec->specialdata)
  642. continue; // already moving
  643. if(sec->floorheight == sec->ceilingheight)
  644. { // pillar is already closed
  645. continue;
  646. }
  647. rtn = 1;
  648. if(!args[2])
  649. {
  650. newHeight = sec->floorheight+
  651. ((sec->ceilingheight-sec->floorheight)/2);
  652. }
  653. else
  654. {
  655. newHeight = sec->floorheight+(args[2]<<FRACBITS);
  656. }
  657. pillar = Z_Malloc(sizeof(*pillar), PU_LEVSPEC, 0);
  658. sec->specialdata = pillar;
  659. P_AddThinker(&pillar->thinker);
  660. pillar->thinker.function = T_BuildPillar;
  661. pillar->sector = sec;
  662. if(!args[2])
  663. {
  664. pillar->ceilingSpeed = pillar->floorSpeed = args[1]*(FRACUNIT/8);
  665. }
  666. else if(newHeight-sec->floorheight > sec->ceilingheight-newHeight)
  667. {
  668. pillar->floorSpeed = args[1]*(FRACUNIT/8);
  669. pillar->ceilingSpeed = FixedMul(sec->ceilingheight-newHeight,
  670. FixedDiv(pillar->floorSpeed, newHeight-sec->floorheight));
  671. }
  672. else
  673. {
  674. pillar->ceilingSpeed = args[1]*(FRACUNIT/8);
  675. pillar->floorSpeed = FixedMul(newHeight-sec->floorheight,
  676. FixedDiv(pillar->ceilingSpeed, sec->ceilingheight-newHeight));
  677. }
  678. pillar->floordest = newHeight;
  679. pillar->ceilingdest = newHeight;
  680. pillar->direction = 1;
  681. pillar->crush = crush*args[3];
  682. SN_StartSequence((mobj_t *)&pillar->sector->soundorg,
  683. SEQ_PLATFORM+pillar->sector->seqType);
  684. }
  685. return rtn;
  686. }
  687. //=========================================================================
  688. //
  689. // EV_OpenPillar
  690. //
  691. //=========================================================================
  692. int EV_OpenPillar(line_t *line, byte *args)
  693. {
  694. int secnum;
  695. sector_t *sec;
  696. pillar_t *pillar;
  697. int rtn;
  698. rtn = 0;
  699. secnum = -1;
  700. while((secnum = P_FindSectorFromTag(args[0], secnum)) >= 0)
  701. {
  702. sec = &sectors[secnum];
  703. if(sec->specialdata)
  704. continue; // already moving
  705. if(sec->floorheight != sec->ceilingheight)
  706. { // pillar isn't closed
  707. continue;
  708. }
  709. rtn = 1;
  710. pillar = Z_Malloc(sizeof(*pillar), PU_LEVSPEC, 0);
  711. sec->specialdata = pillar;
  712. P_AddThinker(&pillar->thinker);
  713. pillar->thinker.function = T_BuildPillar;
  714. pillar->sector = sec;
  715. if(!args[2])
  716. {
  717. pillar->floordest = P_FindLowestFloorSurrounding(sec);
  718. }
  719. else
  720. {
  721. pillar->floordest = sec->floorheight-(args[2]<<FRACBITS);
  722. }
  723. if(!args[3])
  724. {
  725. pillar->ceilingdest = P_FindHighestCeilingSurrounding(sec);
  726. }
  727. else
  728. {
  729. pillar->ceilingdest = sec->ceilingheight+(args[3]<<FRACBITS);
  730. }
  731. if(sec->floorheight-pillar->floordest >= pillar->ceilingdest-
  732. sec->ceilingheight)
  733. {
  734. pillar->floorSpeed = args[1]*(FRACUNIT/8);
  735. pillar->ceilingSpeed = FixedMul(sec->ceilingheight-
  736. pillar->ceilingdest, FixedDiv(pillar->floorSpeed,
  737. pillar->floordest-sec->floorheight));
  738. }
  739. else
  740. {
  741. pillar->ceilingSpeed = args[1]*(FRACUNIT/8);
  742. pillar->floorSpeed = FixedMul(pillar->floordest-sec->floorheight,
  743. FixedDiv(pillar->ceilingSpeed, sec->ceilingheight-
  744. pillar->ceilingdest));
  745. }
  746. pillar->direction = -1; // open the pillar
  747. SN_StartSequence((mobj_t *)&pillar->sector->soundorg,
  748. SEQ_PLATFORM+pillar->sector->seqType);
  749. }
  750. return rtn;
  751. }
  752. //=========================================================================
  753. //
  754. // EV_FloorCrushStop
  755. //
  756. //=========================================================================
  757. int EV_FloorCrushStop(line_t *line, byte *args)
  758. {
  759. thinker_t *think;
  760. floormove_t *floor;
  761. boolean rtn;
  762. rtn = 0;
  763. for(think = thinkercap.next; think != &thinkercap; think = think->next)
  764. {
  765. if(think->function != T_MoveFloor)
  766. {
  767. continue;
  768. }
  769. floor = (floormove_t *)think;
  770. if(floor->type != FLEV_RAISEFLOORCRUSH)
  771. {
  772. continue;
  773. }
  774. // Completely remove the crushing floor
  775. SN_StopSequence((mobj_t *)&floor->sector->soundorg);
  776. floor->sector->specialdata = NULL;
  777. P_TagFinished(floor->sector->tag);
  778. P_RemoveThinker(&floor->thinker);
  779. rtn = 1;
  780. }
  781. return rtn;
  782. }
  783. //==========================================================================
  784. //
  785. // T_FloorWaggle
  786. //
  787. //==========================================================================
  788. #define WGLSTATE_EXPAND 1
  789. #define WGLSTATE_STABLE 2
  790. #define WGLSTATE_REDUCE 3
  791. void T_FloorWaggle(floorWaggle_t *waggle)
  792. {
  793. switch(waggle->state)
  794. {
  795. case WGLSTATE_EXPAND:
  796. if((waggle->scale += waggle->scaleDelta)
  797. >= waggle->targetScale)
  798. {
  799. waggle->scale = waggle->targetScale;
  800. waggle->state = WGLSTATE_STABLE;
  801. }
  802. break;
  803. case WGLSTATE_REDUCE:
  804. if((waggle->scale -= waggle->scaleDelta) <= 0)
  805. { // Remove
  806. waggle->sector->floorheight = waggle->originalHeight;
  807. P_ChangeSector(waggle->sector, true);
  808. waggle->sector->specialdata = NULL;
  809. P_TagFinished(waggle->sector->tag);
  810. P_RemoveThinker(&waggle->thinker);
  811. return;
  812. }
  813. break;
  814. case WGLSTATE_STABLE:
  815. if(waggle->ticker != -1)
  816. {
  817. if(!--waggle->ticker)
  818. {
  819. waggle->state = WGLSTATE_REDUCE;
  820. }
  821. }
  822. break;
  823. }
  824. waggle->accumulator += waggle->accDelta;
  825. waggle->sector->floorheight = waggle->originalHeight
  826. +FixedMul(FloatBobOffsets[(waggle->accumulator>>FRACBITS)&63],
  827. waggle->scale);
  828. P_ChangeSector(waggle->sector, true);
  829. }
  830. //==========================================================================
  831. //
  832. // EV_StartFloorWaggle
  833. //
  834. //==========================================================================
  835. boolean EV_StartFloorWaggle(int tag, int height, int speed, int offset,
  836. int timer)
  837. {
  838. int sectorIndex;
  839. sector_t *sector;
  840. floorWaggle_t *waggle;
  841. boolean retCode;
  842. retCode = false;
  843. sectorIndex = -1;
  844. while((sectorIndex = P_FindSectorFromTag(tag, sectorIndex)) >= 0)
  845. {
  846. sector = &sectors[sectorIndex];
  847. if(sector->specialdata)
  848. { // Already busy with another thinker
  849. continue;
  850. }
  851. retCode = true;
  852. waggle = Z_Malloc(sizeof(*waggle), PU_LEVSPEC, 0);
  853. sector->specialdata = waggle;
  854. waggle->thinker.function = T_FloorWaggle;
  855. waggle->sector = sector;
  856. waggle->originalHeight = sector->floorheight;
  857. waggle->accumulator = offset*FRACUNIT;
  858. waggle->accDelta = speed<<10;
  859. waggle->scale = 0;
  860. waggle->targetScale = height<<10;
  861. waggle->scaleDelta = waggle->targetScale
  862. /(35+((3*35)*height)/255);
  863. waggle->ticker = timer ? timer*35 : -1;
  864. waggle->state = WGLSTATE_EXPAND;
  865. P_AddThinker(&waggle->thinker);
  866. }
  867. return retCode;
  868. }