Move c/h files implementing/defining standard library stuff into a new libc directory...
[kugel-rb.git] / apps / plugins / doom / p_genlin.c
bloba521210c6456dce4cd493e7f0ffa3a145d2798fd
1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
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
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.
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.
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.
27 * DESCRIPTION:
28 * Generalized linedef type handlers
29 * Floors, Ceilings, Doors, Locked Doors, Lifts, Stairs, Crushers
31 *-----------------------------------------------------------------------------*/
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"
41 //////////////////////////////////////////////////////////
43 // Generalized Linedef Type handlers
45 //////////////////////////////////////////////////////////
48 // EV_DoGenFloor()
50 // Handle generalized floor types
52 // Passed the line activating the generalized floor function
53 // Returns true if a thinker is created
55 // jff 02/04/98 Added this routine (and file) to handle generalized
56 // floor movers using bit fields in the line special type.
58 int EV_DoGenFloor
59 ( line_t* line )
61 int secnum;
62 int rtn;
63 boolean manual;
64 sector_t* sec;
65 floormove_t* floor;
66 unsigned value = (unsigned)line->special - GenFloorBase;
68 // parse the bit fields in the line's special type
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;
78 rtn = 0;
80 // check if a manual trigger, if so do just the sector on the backside
81 manual = false;
82 if (Trig==PushOnce || Trig==PushMany)
84 if (!(sec = line->backsector))
85 return rtn;
86 secnum = sec-sectors;
87 manual = true;
88 goto manual_floor;
91 secnum = -1;
92 // if not manual do all sectors tagged the same as the line
93 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
95 sec = &sectors[secnum];
97 manual_floor:
98 // Do not start another function if floor already moving
99 if (P_SectorActive(floor_special,sec))
101 if (!manual)
102 continue;
103 else
104 return rtn;
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;
122 // set the speed of motion
123 switch (Sped)
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;
141 // set the destination height
142 switch(Targ)
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;
182 // set texture/type change properties
183 if (ChgT) // if a texture change is indicated
185 if (ChgM) // if a numeric model change
187 sector_t *sec;
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)
196 floor->texture = sec->floorpic;
197 switch(ChgT)
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;
219 else // else if a trigger model change
221 floor->texture = line->frontsector->floorpic;
222 switch (ChgT)
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;
243 if (manual) return rtn;
245 return rtn;
250 // EV_DoGenCeiling()
252 // Handle generalized ceiling types
254 // Passed the linedef activating the ceiling function
255 // Returns true if a thinker created
257 // jff 02/04/98 Added this routine (and file) to handle generalized
258 // floor movers using bit fields in the line special type.
260 int EV_DoGenCeiling
261 ( line_t* line )
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;
271 // parse the bit fields in the line's special type
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;
281 rtn = 0;
283 // check if a manual trigger, if so do just the sector on the backside
284 manual = false;
285 if (Trig==PushOnce || Trig==PushMany)
287 if (!(sec = line->backsector))
288 return rtn;
289 secnum = sec-sectors;
290 manual = true;
291 goto manual_ceiling;
294 secnum = -1;
295 // if not manual do all sectors tagged the same as the line
296 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
298 sec = &sectors[secnum];
300 manual_ceiling:
301 // Do not start another function if ceiling already moving
302 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
304 if (!manual)
305 continue;
306 else
307 return rtn;
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;
326 // set speed of motion
327 switch (Sped)
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;
345 // set destination target height
346 targheight = sec->ceilingheight;
347 switch(Targ)
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;
386 if (Dirn) ceiling->topheight = targheight;
387 else ceiling->bottomheight = targheight;
389 // set texture/type change properties
390 if (ChgT) // if a texture change is indicated
392 if (ChgM) // if a numeric model change
394 sector_t *sec;
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)
403 ceiling->texture = sec->ceilingpic;
404 switch (ChgT)
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;
426 else // else if a trigger model change
428 ceiling->texture = line->frontsector->ceilingpic;
429 switch (ChgT)
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;
451 P_AddActiveCeiling(ceiling); // add this ceiling to the active list
452 if (manual) return rtn;
454 return rtn;
458 // EV_DoGenLift()
460 // Handle generalized lift types
462 // Passed the linedef activating the lift
463 // Returns true if a thinker is created
465 int EV_DoGenLift
466 ( line_t* line )
468 plat_t* plat;
469 int secnum;
470 int rtn;
471 boolean manual;
472 sector_t* sec;
473 unsigned value = (unsigned)line->special - GenLiftBase;
475 // parse the bit fields in the line's special type
477 int Targ = (value & LiftTarget) >> LiftTargetShift;
478 int Dely = (value & LiftDelay) >> LiftDelayShift;
479 int Sped = (value & LiftSpeed) >> LiftSpeedShift;
480 int Trig = (value & TriggerType) >> TriggerTypeShift;
482 secnum = -1;
483 rtn = 0;
485 // Activate all <type> plats that are in_stasis
487 if (Targ==LnF2HnF)
488 P_ActivateInStasis(line->tag);
490 // check if a manual trigger, if so do just the sector on the backside
491 manual = false;
492 if (Trig==PushOnce || Trig==PushMany)
494 if (!(sec = line->backsector))
495 return rtn;
496 secnum = sec-sectors;
497 manual = true;
498 goto manual_lift;
501 // if not manual do all sectors tagged the same as the line
502 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
504 sec = &sectors[secnum];
506 manual_lift:
507 // Do not start another function if floor already moving
508 if (P_SectorActive(floor_special,sec))
510 if (!manual)
511 continue;
512 else
513 return rtn;
516 // Setup the plat thinker
517 rtn = 1;
518 plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0);
519 P_AddThinker(&plat->thinker);
521 plat->sector = sec;
522 plat->sector->floordata = plat;
523 plat->thinker.function = T_PlatRaise;
524 plat->crush = false;
525 plat->tag = line->tag;
527 plat->type = genLift;
528 plat->high = sec->floorheight;
529 plat->status = down;
531 // setup the target destination height
532 switch(Targ)
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;
561 // setup the speed of motion
562 switch(Sped)
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;
580 // setup the delay time before the floor returns
581 switch(Dely)
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;
597 S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart);
598 P_AddActivePlat(plat); // add this plat to the list of active plats
600 if (manual)
601 return rtn;
603 return rtn;
607 // EV_DoGenStairs()
609 // Handle generalized stair building
611 // Passed the linedef activating the stairs
612 // Returns true if a thinker is created
614 int EV_DoGenStairs
615 ( line_t* line )
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;
627 sector_t* sec;
628 sector_t* tsec;
630 floormove_t* floor;
632 fixed_t stairsize;
633 fixed_t speed;
635 unsigned value = (unsigned)line->special - GenStairsBase;
637 // parse the bit fields in the line's special type
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;
645 rtn = 0;
647 // check if a manual trigger, if so do just the sector on the backside
648 manual = false;
649 if (Trig==PushOnce || Trig==PushMany)
651 if (!(sec = line->backsector))
652 return rtn;
653 secnum = sec-sectors;
654 manual = true;
655 goto manual_stair;
658 secnum = -1;
659 // if not manual do all sectors tagged the same as the line
660 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
662 sec = &sectors[secnum];
664 manual_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)
670 if (!manual)
671 continue;
672 else
673 return rtn;
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;
685 // setup speed of stair building
686 switch(Sped)
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;
703 // setup stepsize for stairs
704 switch(Step)
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;
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
728 sec->stairlock = -2; // jff 2/26/98 set up lock on current sector
729 sec->nextsec = -1;
730 sec->prevsec = -1;
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
738 ok = 0;
739 for (i = 0;i < sec->linecount;i++)
741 if ( !((sec->lines[i])->backsector) )
742 continue;
744 tsec = (sec->lines[i])->frontsector;
745 newsecnum = tsec-sectors;
747 if (secnum != newsecnum)
748 continue;
750 tsec = (sec->lines[i])->backsector;
751 newsecnum = tsec - sectors;
753 if (!Igno && tsec->floorpic != texture)
754 continue;
756 /* jff 6/19/98 prevent double stepsize */
757 if (compatibility_level < boom_202_compatibility)
758 height += floor->direction * stairsize;
760 //jff 2/26/98 special lockout condition for retriggering
761 if (P_SectorActive(floor_special,tsec) || tsec->stairlock)
762 continue;
764 /* jff 6/19/98 increase height AFTER continue */
765 if (compatibility_level >= boom_202_compatibility)
766 height += floor->direction * stairsize;
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
776 sec = tsec;
777 secnum = newsecnum;
778 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
780 P_AddThinker (&floor->thinker);
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
791 ok = 1;
792 break;
794 } while(ok);
795 if (manual)
796 return rtn;
797 secnum = osecnum; //jff 3/4/98 restore old loop index
799 // retriggerable generalized stairs build up or down alternately
800 if (rtn)
801 line->special ^= StairDirection; // alternate dir on succ activations
802 return rtn;
806 // EV_DoGenCrusher()
808 // Handle generalized crusher types
810 // Passed the linedef activating the crusher
811 // Returns true if a thinker created
813 int EV_DoGenCrusher
814 ( line_t* line )
816 int secnum;
817 int rtn;
818 boolean manual;
819 sector_t* sec;
820 ceiling_t* ceiling;
821 unsigned value = (unsigned)line->special - GenCrusherBase;
823 // parse the bit fields in the line's special type
825 int Slnt = (value & CrusherSilent) >> CrusherSilentShift;
826 int Sped = (value & CrusherSpeed) >> CrusherSpeedShift;
827 int Trig = (value & TriggerType) >> TriggerTypeShift;
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);
833 // check if a manual trigger, if so do just the sector on the backside
834 manual = false;
835 if (Trig==PushOnce || Trig==PushMany)
837 if (!(sec = line->backsector))
838 return rtn;
839 secnum = sec-sectors;
840 manual = true;
841 goto manual_crusher;
844 secnum = -1;
845 // if not manual do all sectors tagged the same as the line
846 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
848 sec = &sectors[secnum];
850 manual_crusher:
851 // Do not start another function if ceiling already moving
852 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
854 if (!manual)
855 continue;
856 else
857 return rtn;
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);
876 // setup ceiling motion speed
877 switch (Sped)
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;
894 ceiling->oldspeed=ceiling->speed;
896 P_AddActiveCeiling(ceiling); // add to list of active ceilings
897 if (manual) return rtn;
899 return rtn;
903 // EV_DoGenLockedDoor()
905 // Handle generalized locked door types
907 // Passed the linedef activating the generalized locked door
908 // Returns true if a thinker created
910 int EV_DoGenLockedDoor
911 ( line_t* line )
913 int secnum,rtn;
914 sector_t* sec;
915 vldoor_t* door;
916 boolean manual;
917 unsigned value = (unsigned)line->special - GenLockedBase;
919 // parse the bit fields in the line's special type
921 int Kind = (value & LockedKind) >> LockedKindShift;
922 int Sped = (value & LockedSpeed) >> LockedSpeedShift;
923 int Trig = (value & TriggerType) >> TriggerTypeShift;
925 rtn = 0;
927 // check if a manual trigger, if so do just the sector on the backside
928 manual = false;
929 if (Trig==PushOnce || Trig==PushMany)
931 if (!(sec = line->backsector))
932 return rtn;
933 secnum = sec-sectors;
934 manual = true;
935 goto manual_locked;
938 secnum = -1;
939 rtn = 0;
941 // if not manual do all sectors tagged the same as the line
942 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
944 sec = &sectors[secnum];
945 manual_locked:
946 // Do not start another function if ceiling already moving
947 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
949 if (!manual)
950 continue;
951 else
952 return rtn;
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
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;
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;
974 // setup speed of door motion
975 switch(Sped)
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;
994 break;
997 // killough 4/15/98: fix generalized door opening sounds
998 // (previously they always had the blazing door close sound)
1000 S_StartSound((mobj_t *)&door->sector->soundorg, // killough 4/15/98
1001 door->speed >= VDOORSPEED*4 ? sfx_bdopn : sfx_doropn);
1003 if (manual)
1004 return rtn;
1006 return rtn;
1010 // EV_DoGenDoor()
1012 // Handle generalized door types
1014 // Passed the linedef activating the generalized door
1015 // Returns true if a thinker created
1017 int EV_DoGenDoor
1018 ( line_t* line )
1020 int secnum,rtn;
1021 sector_t* sec;
1022 boolean manual;
1023 vldoor_t* door;
1024 unsigned value = (unsigned)line->special - GenDoorBase;
1026 // parse the bit fields in the line's special type
1028 int Dely = (value & DoorDelay) >> DoorDelayShift;
1029 int Kind = (value & DoorKind) >> DoorKindShift;
1030 int Sped = (value & DoorSpeed) >> DoorSpeedShift;
1031 int Trig = (value & TriggerType) >> TriggerTypeShift;
1033 rtn = 0;
1035 // check if a manual trigger, if so do just the sector on the backside
1036 manual = false;
1037 if (Trig==PushOnce || Trig==PushMany)
1039 if (!(sec = line->backsector))
1040 return rtn;
1041 secnum = sec-sectors;
1042 manual = true;
1043 goto manual_door;
1047 secnum = -1;
1048 rtn = 0;
1050 // if not manual do all sectors tagged the same as the line
1051 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
1053 sec = &sectors[secnum];
1054 manual_door:
1055 // Do not start another function if ceiling already moving
1056 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
1058 if (!manual)
1059 continue;
1060 else
1061 return rtn;
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
1070 door->thinker.function = T_VerticalDoor;
1071 door->sector = sec;
1072 // setup delay for door remaining open/closed
1073 switch(Dely)
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;
1090 // setup speed of door motion
1091 switch(Sped)
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;
1107 door->line = line; // jff 1/31/98 remember line that triggered us
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;
1114 // set kind of door, whether it opens then close, opens, closes etc.
1115 // assign target heights accordingly
1116 switch(Kind)
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;
1150 if (manual)
1151 return rtn;
1153 return rtn;