summaryrefslogtreecommitdiff
path: root/apps/plugins/doom/p_genlin.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/doom/p_genlin.c')
-rw-r--r--apps/plugins/doom/p_genlin.c1154
1 files changed, 1154 insertions, 0 deletions
diff --git a/apps/plugins/doom/p_genlin.c b/apps/plugins/doom/p_genlin.c
new file mode 100644
index 0000000000..a521210c64
--- /dev/null
+++ b/apps/plugins/doom/p_genlin.c
@@ -0,0 +1,1154 @@
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 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
26 *
27 * DESCRIPTION:
28 * Generalized linedef type handlers
29 * Floors, Ceilings, Doors, Locked Doors, Lifts, Stairs, Crushers
30 *
31 *-----------------------------------------------------------------------------*/
32
33#include "doomstat.h" //jff 6/19/98 for demo_compatibility
34#include "r_main.h"
35#include "p_spec.h"
36#include "p_tick.h"
37#include "m_random.h"
38#include "s_sound.h"
39#include "sounds.h"
40
41//////////////////////////////////////////////////////////
42//
43// Generalized Linedef Type handlers
44//
45//////////////////////////////////////////////////////////
46
47//
48// EV_DoGenFloor()
49//
50// Handle generalized floor types
51//
52// Passed the line activating the generalized floor function
53// Returns true if a thinker is created
54//
55// jff 02/04/98 Added this routine (and file) to handle generalized
56// floor movers using bit fields in the line special type.
57//
58int EV_DoGenFloor
59( line_t* line )
60{
61 int secnum;
62 int rtn;
63 boolean manual;
64 sector_t* sec;
65 floormove_t* floor;
66 unsigned value = (unsigned)line->special - GenFloorBase;
67
68 // parse the bit fields in the line's special type
69
70 int Crsh = (value & FloorCrush) >> FloorCrushShift;
71 int ChgT = (value & FloorChange) >> FloorChangeShift;
72 int Targ = (value & FloorTarget) >> FloorTargetShift;
73 int Dirn = (value & FloorDirection) >> FloorDirectionShift;
74 int ChgM = (value & FloorModel) >> FloorModelShift;
75 int Sped = (value & FloorSpeed) >> FloorSpeedShift;
76 int Trig = (value & TriggerType) >> TriggerTypeShift;
77
78 rtn = 0;
79
80 // check if a manual trigger, if so do just the sector on the backside
81 manual = false;
82 if (Trig==PushOnce || Trig==PushMany)
83 {
84 if (!(sec = line->backsector))
85 return rtn;
86 secnum = sec-sectors;
87 manual = true;
88 goto manual_floor;
89 }
90
91 secnum = -1;
92 // if not manual do all sectors tagged the same as the line
93 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
94 {
95 sec = &sectors[secnum];
96
97manual_floor:
98 // Do not start another function if floor already moving
99 if (P_SectorActive(floor_special,sec))
100 {
101 if (!manual)
102 continue;
103 else
104 return rtn;
105 }
106
107 // new floor thinker
108 rtn = 1;
109 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
110 P_AddThinker (&floor->thinker);
111 sec->floordata = floor;
112 floor->thinker.function = T_MoveFloor;
113 floor->crush = Crsh;
114 floor->direction = Dirn? 1 : -1;
115 floor->sector = sec;
116 floor->texture = sec->floorpic;
117 floor->newspecial = sec->special;
118 //jff 3/14/98 transfer old special field too
119 floor->oldspecial = sec->oldspecial;
120 floor->type = genFloor;
121
122 // set the speed of motion
123 switch (Sped)
124 {
125 case SpeedSlow:
126 floor->speed = FLOORSPEED;
127 break;
128 case SpeedNormal:
129 floor->speed = FLOORSPEED*2;
130 break;
131 case SpeedFast:
132 floor->speed = FLOORSPEED*4;
133 break;
134 case SpeedTurbo:
135 floor->speed = FLOORSPEED*8;
136 break;
137 default:
138 break;
139 }
140
141 // set the destination height
142 switch(Targ)
143 {
144 case FtoHnF:
145 floor->floordestheight = P_FindHighestFloorSurrounding(sec);
146 break;
147 case FtoLnF:
148 floor->floordestheight = P_FindLowestFloorSurrounding(sec);
149 break;
150 case FtoNnF:
151 floor->floordestheight = Dirn?
152 P_FindNextHighestFloor(sec,sec->floorheight) :
153 P_FindNextLowestFloor(sec,sec->floorheight);
154 break;
155 case FtoLnC:
156 floor->floordestheight = P_FindLowestCeilingSurrounding(sec);
157 break;
158 case FtoC:
159 floor->floordestheight = sec->ceilingheight;
160 break;
161 case FbyST:
162 floor->floordestheight = (floor->sector->floorheight>>FRACBITS) +
163 floor->direction * (P_FindShortestTextureAround(secnum)>>FRACBITS);
164 if (floor->floordestheight>32000) //jff 3/13/98 prevent overflow
165 floor->floordestheight=32000; // wraparound in floor height
166 if (floor->floordestheight<-32000)
167 floor->floordestheight=-32000;
168 floor->floordestheight<<=FRACBITS;
169 break;
170 case Fby24:
171 floor->floordestheight = floor->sector->floorheight +
172 floor->direction * 24*FRACUNIT;
173 break;
174 case Fby32:
175 floor->floordestheight = floor->sector->floorheight +
176 floor->direction * 32*FRACUNIT;
177 break;
178 default:
179 break;
180 }
181
182 // set texture/type change properties
183 if (ChgT) // if a texture change is indicated
184 {
185 if (ChgM) // if a numeric model change
186 {
187 sector_t *sec;
188
189 //jff 5/23/98 find model with ceiling at target height if target
190 //is a ceiling type
191 sec = (Targ==FtoLnC || Targ==FtoC)?
192 P_FindModelCeilingSector(floor->floordestheight,secnum) :
193 P_FindModelFloorSector(floor->floordestheight,secnum);
194 if (sec)
195 {
196 floor->texture = sec->floorpic;
197 switch(ChgT)
198 {
199 case FChgZero: // zero type
200 floor->newspecial = 0;
201 //jff 3/14/98 change old field too
202 floor->oldspecial = 0;
203 floor->type = genFloorChg0;
204 break;
205 case FChgTyp: // copy type
206 floor->newspecial = sec->special;
207 //jff 3/14/98 change old field too
208 floor->oldspecial = sec->oldspecial;
209 floor->type = genFloorChgT;
210 break;
211 case FChgTxt: // leave type be
212 floor->type = genFloorChg;
213 break;
214 default:
215 break;
216 }
217 }
218 }
219 else // else if a trigger model change
220 {
221 floor->texture = line->frontsector->floorpic;
222 switch (ChgT)
223 {
224 case FChgZero: // zero type
225 floor->newspecial = 0;
226 //jff 3/14/98 change old field too
227 floor->oldspecial = 0;
228 floor->type = genFloorChg0;
229 break;
230 case FChgTyp: // copy type
231 floor->newspecial = line->frontsector->special;
232 //jff 3/14/98 change old field too
233 floor->oldspecial = line->frontsector->oldspecial;
234 floor->type = genFloorChgT;
235 break;
236 case FChgTxt: // leave type be
237 floor->type = genFloorChg;
238 default:
239 break;
240 }
241 }
242 }
243 if (manual) return rtn;
244 }
245 return rtn;
246}
247
248
249//
250// EV_DoGenCeiling()
251//
252// Handle generalized ceiling types
253//
254// Passed the linedef activating the ceiling function
255// Returns true if a thinker created
256//
257// jff 02/04/98 Added this routine (and file) to handle generalized
258// floor movers using bit fields in the line special type.
259//
260int EV_DoGenCeiling
261( line_t* line )
262{
263 int secnum;
264 int rtn;
265 boolean manual;
266 fixed_t targheight;
267 sector_t* sec;
268 ceiling_t* ceiling;
269 unsigned value = (unsigned)line->special - GenCeilingBase;
270
271 // parse the bit fields in the line's special type
272
273 int Crsh = (value & CeilingCrush) >> CeilingCrushShift;
274 int ChgT = (value & CeilingChange) >> CeilingChangeShift;
275 int Targ = (value & CeilingTarget) >> CeilingTargetShift;
276 int Dirn = (value & CeilingDirection) >> CeilingDirectionShift;
277 int ChgM = (value & CeilingModel) >> CeilingModelShift;
278 int Sped = (value & CeilingSpeed) >> CeilingSpeedShift;
279 int Trig = (value & TriggerType) >> TriggerTypeShift;
280
281 rtn = 0;
282
283 // check if a manual trigger, if so do just the sector on the backside
284 manual = false;
285 if (Trig==PushOnce || Trig==PushMany)
286 {
287 if (!(sec = line->backsector))
288 return rtn;
289 secnum = sec-sectors;
290 manual = true;
291 goto manual_ceiling;
292 }
293
294 secnum = -1;
295 // if not manual do all sectors tagged the same as the line
296 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
297 {
298 sec = &sectors[secnum];
299
300manual_ceiling:
301 // Do not start another function if ceiling already moving
302 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
303 {
304 if (!manual)
305 continue;
306 else
307 return rtn;
308 }
309
310 // new ceiling thinker
311 rtn = 1;
312 ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
313 P_AddThinker (&ceiling->thinker);
314 sec->ceilingdata = ceiling; //jff 2/22/98
315 ceiling->thinker.function = T_MoveCeiling;
316 ceiling->crush = Crsh;
317 ceiling->direction = Dirn? 1 : -1;
318 ceiling->sector = sec;
319 ceiling->texture = sec->ceilingpic;
320 ceiling->newspecial = sec->special;
321 //jff 3/14/98 change old field too
322 ceiling->oldspecial = sec->oldspecial;
323 ceiling->tag = sec->tag;
324 ceiling->type = genCeiling;
325
326 // set speed of motion
327 switch (Sped)
328 {
329 case SpeedSlow:
330 ceiling->speed = CEILSPEED;
331 break;
332 case SpeedNormal:
333 ceiling->speed = CEILSPEED*2;
334 break;
335 case SpeedFast:
336 ceiling->speed = CEILSPEED*4;
337 break;
338 case SpeedTurbo:
339 ceiling->speed = CEILSPEED*8;
340 break;
341 default:
342 break;
343 }
344
345 // set destination target height
346 targheight = sec->ceilingheight;
347 switch(Targ)
348 {
349 case CtoHnC:
350 targheight = P_FindHighestCeilingSurrounding(sec);
351 break;
352 case CtoLnC:
353 targheight = P_FindLowestCeilingSurrounding(sec);
354 break;
355 case CtoNnC:
356 targheight = Dirn?
357 P_FindNextHighestCeiling(sec,sec->ceilingheight) :
358 P_FindNextLowestCeiling(sec,sec->ceilingheight);
359 break;
360 case CtoHnF:
361 targheight = P_FindHighestFloorSurrounding(sec);
362 break;
363 case CtoF:
364 targheight = sec->floorheight;
365 break;
366 case CbyST:
367 targheight = (ceiling->sector->ceilingheight>>FRACBITS) +
368 ceiling->direction * (P_FindShortestUpperAround(secnum)>>FRACBITS);
369 if (targheight>32000) //jff 3/13/98 prevent overflow
370 targheight=32000; // wraparound in ceiling height
371 if (targheight<-32000)
372 targheight=-32000;
373 targheight<<=FRACBITS;
374 break;
375 case Cby24:
376 targheight = ceiling->sector->ceilingheight +
377 ceiling->direction * 24*FRACUNIT;
378 break;
379 case Cby32:
380 targheight = ceiling->sector->ceilingheight +
381 ceiling->direction * 32*FRACUNIT;
382 break;
383 default:
384 break;
385 }
386 if (Dirn) ceiling->topheight = targheight;
387 else ceiling->bottomheight = targheight;
388
389 // set texture/type change properties
390 if (ChgT) // if a texture change is indicated
391 {
392 if (ChgM) // if a numeric model change
393 {
394 sector_t *sec;
395
396 //jff 5/23/98 find model with floor at target height if target
397 //is a floor type
398 sec = (Targ==CtoHnF || Targ==CtoF)?
399 P_FindModelFloorSector(targheight,secnum) :
400 P_FindModelCeilingSector(targheight,secnum);
401 if (sec)
402 {
403 ceiling->texture = sec->ceilingpic;
404 switch (ChgT)
405 {
406 case CChgZero: // type is zeroed
407 ceiling->newspecial = 0;
408 //jff 3/14/98 change old field too
409 ceiling->oldspecial = 0;
410 ceiling->type = genCeilingChg0;
411 break;
412 case CChgTyp: // type is copied
413 ceiling->newspecial = sec->special;
414 //jff 3/14/98 change old field too
415 ceiling->oldspecial = sec->oldspecial;
416 ceiling->type = genCeilingChgT;
417 break;
418 case CChgTxt: // type is left alone
419 ceiling->type = genCeilingChg;
420 break;
421 default:
422 break;
423 }
424 }
425 }
426 else // else if a trigger model change
427 {
428 ceiling->texture = line->frontsector->ceilingpic;
429 switch (ChgT)
430 {
431 case CChgZero: // type is zeroed
432 ceiling->newspecial = 0;
433 //jff 3/14/98 change old field too
434 ceiling->oldspecial = 0;
435 ceiling->type = genCeilingChg0;
436 break;
437 case CChgTyp: // type is copied
438 ceiling->newspecial = line->frontsector->special;
439 //jff 3/14/98 change old field too
440 ceiling->oldspecial = line->frontsector->oldspecial;
441 ceiling->type = genCeilingChgT;
442 break;
443 case CChgTxt: // type is left alone
444 ceiling->type = genCeilingChg;
445 break;
446 default:
447 break;
448 }
449 }
450 }
451 P_AddActiveCeiling(ceiling); // add this ceiling to the active list
452 if (manual) return rtn;
453 }
454 return rtn;
455}
456
457//
458// EV_DoGenLift()
459//
460// Handle generalized lift types
461//
462// Passed the linedef activating the lift
463// Returns true if a thinker is created
464//
465int EV_DoGenLift
466( line_t* line )
467{
468 plat_t* plat;
469 int secnum;
470 int rtn;
471 boolean manual;
472 sector_t* sec;
473 unsigned value = (unsigned)line->special - GenLiftBase;
474
475 // parse the bit fields in the line's special type
476
477 int Targ = (value & LiftTarget) >> LiftTargetShift;
478 int Dely = (value & LiftDelay) >> LiftDelayShift;
479 int Sped = (value & LiftSpeed) >> LiftSpeedShift;
480 int Trig = (value & TriggerType) >> TriggerTypeShift;
481
482 secnum = -1;
483 rtn = 0;
484
485 // Activate all <type> plats that are in_stasis
486
487 if (Targ==LnF2HnF)
488 P_ActivateInStasis(line->tag);
489
490 // check if a manual trigger, if so do just the sector on the backside
491 manual = false;
492 if (Trig==PushOnce || Trig==PushMany)
493 {
494 if (!(sec = line->backsector))
495 return rtn;
496 secnum = sec-sectors;
497 manual = true;
498 goto manual_lift;
499 }
500
501 // if not manual do all sectors tagged the same as the line
502 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
503 {
504 sec = &sectors[secnum];
505
506manual_lift:
507 // Do not start another function if floor already moving
508 if (P_SectorActive(floor_special,sec))
509 {
510 if (!manual)
511 continue;
512 else
513 return rtn;
514 }
515
516 // Setup the plat thinker
517 rtn = 1;
518 plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0);
519 P_AddThinker(&plat->thinker);
520
521 plat->sector = sec;
522 plat->sector->floordata = plat;
523 plat->thinker.function = T_PlatRaise;
524 plat->crush = false;
525 plat->tag = line->tag;
526
527 plat->type = genLift;
528 plat->high = sec->floorheight;
529 plat->status = down;
530
531 // setup the target destination height
532 switch(Targ)
533 {
534 case F2LnF:
535 plat->low = P_FindLowestFloorSurrounding(sec);
536 if (plat->low > sec->floorheight)
537 plat->low = sec->floorheight;
538 break;
539 case F2NnF:
540 plat->low = P_FindNextLowestFloor(sec,sec->floorheight);
541 break;
542 case F2LnC:
543 plat->low = P_FindLowestCeilingSurrounding(sec);
544 if (plat->low > sec->floorheight)
545 plat->low = sec->floorheight;
546 break;
547 case LnF2HnF:
548 plat->type = genPerpetual;
549 plat->low = P_FindLowestFloorSurrounding(sec);
550 if (plat->low > sec->floorheight)
551 plat->low = sec->floorheight;
552 plat->high = P_FindHighestFloorSurrounding(sec);
553 if (plat->high < sec->floorheight)
554 plat->high = sec->floorheight;
555 plat->status = P_Random(pr_genlift)&1;
556 break;
557 default:
558 break;
559 }
560
561 // setup the speed of motion
562 switch(Sped)
563 {
564 case SpeedSlow:
565 plat->speed = PLATSPEED * 2;
566 break;
567 case SpeedNormal:
568 plat->speed = PLATSPEED * 4;
569 break;
570 case SpeedFast:
571 plat->speed = PLATSPEED * 8;
572 break;
573 case SpeedTurbo:
574 plat->speed = PLATSPEED * 16;
575 break;
576 default:
577 break;
578 }
579
580 // setup the delay time before the floor returns
581 switch(Dely)
582 {
583 case 0:
584 plat->wait = 1*35;
585 break;
586 case 1:
587 plat->wait = PLATWAIT*35;
588 break;
589 case 2:
590 plat->wait = 5*35;
591 break;
592 case 3:
593 plat->wait = 10*35;
594 break;
595 }
596
597 S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart);
598 P_AddActivePlat(plat); // add this plat to the list of active plats
599
600 if (manual)
601 return rtn;
602 }
603 return rtn;
604}
605
606//
607// EV_DoGenStairs()
608//
609// Handle generalized stair building
610//
611// Passed the linedef activating the stairs
612// Returns true if a thinker is created
613//
614int EV_DoGenStairs
615( line_t* line )
616{
617 int secnum;
618 int osecnum; //jff 3/4/98 preserve loop index
619 int height;
620 int i;
621 int newsecnum;
622 int texture;
623 int ok;
624 int rtn;
625 boolean manual;
626
627 sector_t* sec;
628 sector_t* tsec;
629
630 floormove_t* floor;
631
632 fixed_t stairsize;
633 fixed_t speed;
634
635 unsigned value = (unsigned)line->special - GenStairsBase;
636
637 // parse the bit fields in the line's special type
638
639 int Igno = (value & StairIgnore) >> StairIgnoreShift;
640 int Dirn = (value & StairDirection) >> StairDirectionShift;
641 int Step = (value & StairStep) >> StairStepShift;
642 int Sped = (value & StairSpeed) >> StairSpeedShift;
643 int Trig = (value & TriggerType) >> TriggerTypeShift;
644
645 rtn = 0;
646
647 // check if a manual trigger, if so do just the sector on the backside
648 manual = false;
649 if (Trig==PushOnce || Trig==PushMany)
650 {
651 if (!(sec = line->backsector))
652 return rtn;
653 secnum = sec-sectors;
654 manual = true;
655 goto manual_stair;
656 }
657
658 secnum = -1;
659 // if not manual do all sectors tagged the same as the line
660 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
661 {
662 sec = &sectors[secnum];
663
664manual_stair:
665 //Do not start another function if floor already moving
666 //jff 2/26/98 add special lockout condition to wait for entire
667 //staircase to build before retriggering
668 if (P_SectorActive(floor_special,sec) || sec->stairlock)
669 {
670 if (!manual)
671 continue;
672 else
673 return rtn;
674 }
675
676 // new floor thinker
677 rtn = 1;
678 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
679 P_AddThinker (&floor->thinker);
680 sec->floordata = floor;
681 floor->thinker.function = T_MoveFloor;
682 floor->direction = Dirn? 1 : -1;
683 floor->sector = sec;
684
685 // setup speed of stair building
686 switch(Sped)
687 {
688 default:
689 case SpeedSlow:
690 floor->speed = FLOORSPEED/4;
691 break;
692 case SpeedNormal:
693 floor->speed = FLOORSPEED/2;
694 break;
695 case SpeedFast:
696 floor->speed = FLOORSPEED*2;
697 break;
698 case SpeedTurbo:
699 floor->speed = FLOORSPEED*4;
700 break;
701 }
702
703 // setup stepsize for stairs
704 switch(Step)
705 {
706 default:
707 case 0:
708 stairsize = 4*FRACUNIT;
709 break;
710 case 1:
711 stairsize = 8*FRACUNIT;
712 break;
713 case 2:
714 stairsize = 16*FRACUNIT;
715 break;
716 case 3:
717 stairsize = 24*FRACUNIT;
718 break;
719 }
720
721 speed = floor->speed;
722 height = sec->floorheight + floor->direction * stairsize;
723 floor->floordestheight = height;
724 texture = sec->floorpic;
725 floor->crush = false;
726 floor->type = genBuildStair; // jff 3/31/98 do not leave uninited
727
728 sec->stairlock = -2; // jff 2/26/98 set up lock on current sector
729 sec->nextsec = -1;
730 sec->prevsec = -1;
731
732 osecnum = secnum; //jff 3/4/98 preserve loop index
733 // Find next sector to raise
734 // 1. Find 2-sided line with same sector side[0]
735 // 2. Other side is the next sector to raise
736 do
737 {
738 ok = 0;
739 for (i = 0;i < sec->linecount;i++)
740 {
741 if ( !((sec->lines[i])->backsector) )
742 continue;
743
744 tsec = (sec->lines[i])->frontsector;
745 newsecnum = tsec-sectors;
746
747 if (secnum != newsecnum)
748 continue;
749
750 tsec = (sec->lines[i])->backsector;
751 newsecnum = tsec - sectors;
752
753 if (!Igno && tsec->floorpic != texture)
754 continue;
755
756 /* jff 6/19/98 prevent double stepsize */
757 if (compatibility_level < boom_202_compatibility)
758 height += floor->direction * stairsize;
759
760 //jff 2/26/98 special lockout condition for retriggering
761 if (P_SectorActive(floor_special,tsec) || tsec->stairlock)
762 continue;
763
764 /* jff 6/19/98 increase height AFTER continue */
765 if (compatibility_level >= boom_202_compatibility)
766 height += floor->direction * stairsize;
767
768 // jff 2/26/98
769 // link the stair chain in both directions
770 // lock the stair sector until building complete
771 sec->nextsec = newsecnum; // link step to next
772 tsec->prevsec = secnum; // link next back
773 tsec->nextsec = -1; // set next forward link as end
774 tsec->stairlock = -2; // lock the step
775
776 sec = tsec;
777 secnum = newsecnum;
778 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
779
780 P_AddThinker (&floor->thinker);
781
782 sec->floordata = floor;
783 floor->thinker.function = T_MoveFloor;
784 floor->direction = Dirn? 1 : -1;
785 floor->sector = sec;
786 floor->speed = speed;
787 floor->floordestheight = height;
788 floor->crush = false;
789 floor->type = genBuildStair; // jff 3/31/98 do not leave uninited
790
791 ok = 1;
792 break;
793 }
794 } while(ok);
795 if (manual)
796 return rtn;
797 secnum = osecnum; //jff 3/4/98 restore old loop index
798 }
799 // retriggerable generalized stairs build up or down alternately
800 if (rtn)
801 line->special ^= StairDirection; // alternate dir on succ activations
802 return rtn;
803}
804
805//
806// EV_DoGenCrusher()
807//
808// Handle generalized crusher types
809//
810// Passed the linedef activating the crusher
811// Returns true if a thinker created
812//
813int EV_DoGenCrusher
814( line_t* line )
815{
816 int secnum;
817 int rtn;
818 boolean manual;
819 sector_t* sec;
820 ceiling_t* ceiling;
821 unsigned value = (unsigned)line->special - GenCrusherBase;
822
823 // parse the bit fields in the line's special type
824
825 int Slnt = (value & CrusherSilent) >> CrusherSilentShift;
826 int Sped = (value & CrusherSpeed) >> CrusherSpeedShift;
827 int Trig = (value & TriggerType) >> TriggerTypeShift;
828
829 //jff 2/22/98 Reactivate in-stasis ceilings...for certain types.
830 //jff 4/5/98 return if activated
831 rtn = P_ActivateInStasisCeiling(line);
832
833 // check if a manual trigger, if so do just the sector on the backside
834 manual = false;
835 if (Trig==PushOnce || Trig==PushMany)
836 {
837 if (!(sec = line->backsector))
838 return rtn;
839 secnum = sec-sectors;
840 manual = true;
841 goto manual_crusher;
842 }
843
844 secnum = -1;
845 // if not manual do all sectors tagged the same as the line
846 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
847 {
848 sec = &sectors[secnum];
849
850manual_crusher:
851 // Do not start another function if ceiling already moving
852 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
853 {
854 if (!manual)
855 continue;
856 else
857 return rtn;
858 }
859
860 // new ceiling thinker
861 rtn = 1;
862 ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
863 P_AddThinker (&ceiling->thinker);
864 sec->ceilingdata = ceiling; //jff 2/22/98
865 ceiling->thinker.function = T_MoveCeiling;
866 ceiling->crush = true;
867 ceiling->direction = -1;
868 ceiling->sector = sec;
869 ceiling->texture = sec->ceilingpic;
870 ceiling->newspecial = sec->special;
871 ceiling->tag = sec->tag;
872 ceiling->type = Slnt? genSilentCrusher : genCrusher;
873 ceiling->topheight = sec->ceilingheight;
874 ceiling->bottomheight = sec->floorheight + (8*FRACUNIT);
875
876 // setup ceiling motion speed
877 switch (Sped)
878 {
879 case SpeedSlow:
880 ceiling->speed = CEILSPEED;
881 break;
882 case SpeedNormal:
883 ceiling->speed = CEILSPEED*2;
884 break;
885 case SpeedFast:
886 ceiling->speed = CEILSPEED*4;
887 break;
888 case SpeedTurbo:
889 ceiling->speed = CEILSPEED*8;
890 break;
891 default:
892 break;
893 }
894 ceiling->oldspeed=ceiling->speed;
895
896 P_AddActiveCeiling(ceiling); // add to list of active ceilings
897 if (manual) return rtn;
898 }
899 return rtn;
900}
901
902//
903// EV_DoGenLockedDoor()
904//
905// Handle generalized locked door types
906//
907// Passed the linedef activating the generalized locked door
908// Returns true if a thinker created
909//
910int EV_DoGenLockedDoor
911( line_t* line )
912{
913 int secnum,rtn;
914 sector_t* sec;
915 vldoor_t* door;
916 boolean manual;
917 unsigned value = (unsigned)line->special - GenLockedBase;
918
919 // parse the bit fields in the line's special type
920
921 int Kind = (value & LockedKind) >> LockedKindShift;
922 int Sped = (value & LockedSpeed) >> LockedSpeedShift;
923 int Trig = (value & TriggerType) >> TriggerTypeShift;
924
925 rtn = 0;
926
927 // check if a manual trigger, if so do just the sector on the backside
928 manual = false;
929 if (Trig==PushOnce || Trig==PushMany)
930 {
931 if (!(sec = line->backsector))
932 return rtn;
933 secnum = sec-sectors;
934 manual = true;
935 goto manual_locked;
936 }
937
938 secnum = -1;
939 rtn = 0;
940
941 // if not manual do all sectors tagged the same as the line
942 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
943 {
944 sec = &sectors[secnum];
945manual_locked:
946 // Do not start another function if ceiling already moving
947 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
948 {
949 if (!manual)
950 continue;
951 else
952 return rtn;
953 }
954
955 // new door thinker
956 rtn = 1;
957 door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
958 P_AddThinker (&door->thinker);
959 sec->ceilingdata = door; //jff 2/22/98
960
961 door->thinker.function = T_VerticalDoor;
962 door->sector = sec;
963 door->topwait = VDOORWAIT;
964 door->line = line;
965 door->topheight = P_FindLowestCeilingSurrounding(sec);
966 door->topheight -= 4*FRACUNIT;
967 door->direction = 1;
968
969 /* killough 10/98: implement gradual lighting */
970 door->lighttag = !comp[comp_doorlight] &&
971 (line->special&6) == 6 &&
972 line->special > GenLockedBase ? line->tag : 0;
973
974 // setup speed of door motion
975 switch(Sped)
976 {
977 default:
978 case SpeedSlow:
979 door->type = Kind? genOpen : genRaise;
980 door->speed = VDOORSPEED;
981 break;
982 case SpeedNormal:
983 door->type = Kind? genOpen : genRaise;
984 door->speed = VDOORSPEED*2;
985 break;
986 case SpeedFast:
987 door->type = Kind? genBlazeOpen : genBlazeRaise;
988 door->speed = VDOORSPEED*4;
989 break;
990 case SpeedTurbo:
991 door->type = Kind? genBlazeOpen : genBlazeRaise;
992 door->speed = VDOORSPEED*8;
993
994 break;
995 }
996
997 // killough 4/15/98: fix generalized door opening sounds
998 // (previously they always had the blazing door close sound)
999
1000 S_StartSound((mobj_t *)&door->sector->soundorg, // killough 4/15/98
1001 door->speed >= VDOORSPEED*4 ? sfx_bdopn : sfx_doropn);
1002
1003 if (manual)
1004 return rtn;
1005 }
1006 return rtn;
1007}
1008
1009//
1010// EV_DoGenDoor()
1011//
1012// Handle generalized door types
1013//
1014// Passed the linedef activating the generalized door
1015// Returns true if a thinker created
1016//
1017int EV_DoGenDoor
1018( line_t* line )
1019{
1020 int secnum,rtn;
1021 sector_t* sec;
1022 boolean manual;
1023 vldoor_t* door;
1024 unsigned value = (unsigned)line->special - GenDoorBase;
1025
1026 // parse the bit fields in the line's special type
1027
1028 int Dely = (value & DoorDelay) >> DoorDelayShift;
1029 int Kind = (value & DoorKind) >> DoorKindShift;
1030 int Sped = (value & DoorSpeed) >> DoorSpeedShift;
1031 int Trig = (value & TriggerType) >> TriggerTypeShift;
1032
1033 rtn = 0;
1034
1035 // check if a manual trigger, if so do just the sector on the backside
1036 manual = false;
1037 if (Trig==PushOnce || Trig==PushMany)
1038 {
1039 if (!(sec = line->backsector))
1040 return rtn;
1041 secnum = sec-sectors;
1042 manual = true;
1043 goto manual_door;
1044 }
1045
1046
1047 secnum = -1;
1048 rtn = 0;
1049
1050 // if not manual do all sectors tagged the same as the line
1051 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
1052 {
1053 sec = &sectors[secnum];
1054manual_door:
1055 // Do not start another function if ceiling already moving
1056 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
1057 {
1058 if (!manual)
1059 continue;
1060 else
1061 return rtn;
1062 }
1063
1064 // new door thinker
1065 rtn = 1;
1066 door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
1067 P_AddThinker (&door->thinker);
1068 sec->ceilingdata = door; //jff 2/22/98
1069
1070 door->thinker.function = T_VerticalDoor;
1071 door->sector = sec;
1072 // setup delay for door remaining open/closed
1073 switch(Dely)
1074 {
1075 default:
1076 case 0:
1077 door->topwait = 35;
1078 break;
1079 case 1:
1080 door->topwait = VDOORWAIT;
1081 break;
1082 case 2:
1083 door->topwait = 2*VDOORWAIT;
1084 break;
1085 case 3:
1086 door->topwait = 7*VDOORWAIT;
1087 break;
1088 }
1089
1090 // setup speed of door motion
1091 switch(Sped)
1092 {
1093 default:
1094 case SpeedSlow:
1095 door->speed = VDOORSPEED;
1096 break;
1097 case SpeedNormal:
1098 door->speed = VDOORSPEED*2;
1099 break;
1100 case SpeedFast:
1101 door->speed = VDOORSPEED*4;
1102 break;
1103 case SpeedTurbo:
1104 door->speed = VDOORSPEED*8;
1105 break;
1106 }
1107 door->line = line; // jff 1/31/98 remember line that triggered us
1108
1109 /* killough 10/98: implement gradual lighting */
1110 door->lighttag = !comp[comp_doorlight] &&
1111 (line->special&6) == 6 &&
1112 line->special > GenLockedBase ? line->tag : 0;
1113
1114 // set kind of door, whether it opens then close, opens, closes etc.
1115 // assign target heights accordingly
1116 switch(Kind)
1117 {
1118 case OdCDoor:
1119 door->direction = 1;
1120 door->topheight = P_FindLowestCeilingSurrounding(sec);
1121 door->topheight -= 4*FRACUNIT;
1122 if (door->topheight != sec->ceilingheight)
1123 S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast || comp[comp_sound] ? sfx_bdopn : sfx_doropn);
1124 door->type = Sped>=SpeedFast? genBlazeRaise : genRaise;
1125 break;
1126 case ODoor:
1127 door->direction = 1;
1128 door->topheight = P_FindLowestCeilingSurrounding(sec);
1129 door->topheight -= 4*FRACUNIT;
1130 if (door->topheight != sec->ceilingheight)
1131 S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast || comp[comp_sound] ? sfx_bdopn : sfx_doropn);
1132 door->type = Sped>=SpeedFast? genBlazeOpen : genOpen;
1133 break;
1134 case CdODoor:
1135 door->topheight = sec->ceilingheight;
1136 door->direction = -1;
1137 S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast && !comp[comp_sound] ? sfx_bdcls : sfx_dorcls);
1138 door->type = Sped>=SpeedFast? genBlazeCdO : genCdO;
1139 break;
1140 case CDoor:
1141 door->topheight = P_FindLowestCeilingSurrounding(sec);
1142 door->topheight -= 4*FRACUNIT;
1143 door->direction = -1;
1144 S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast && !comp[comp_sound] ? sfx_bdcls : sfx_dorcls);
1145 door->type = Sped>=SpeedFast? genBlazeClose : genClose;
1146 break;
1147 default:
1148 break;
1149 }
1150 if (manual)
1151 return rtn;
1152 }
1153 return rtn;
1154}