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