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