1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: p_switch.c 1456 2019-09-11 12:26:00Z wesleyjohnson $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Portions Copyright (C) 1998-2000 by DooM Legacy Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 //
20 // $Log: p_switch.c,v $
21 // Revision 1.10  2001/04/18 21:00:22  metzgermeister
22 // fix crash bug
23 //
24 // Revision 1.9  2001/02/24 13:35:21  bpereira
25 //
26 // Revision 1.8  2001/01/25 22:15:44  bpereira
27 // added heretic support
28 //
29 // Revision 1.7  2000/11/02 17:50:09  stroggonmeth
30 // Big 3Dfloors & FraggleScript commit!!
31 //
32 // Revision 1.6  2000/09/28 20:57:17  bpereira
33 // Revision 1.5  2000/04/16 18:38:07  bpereira
34 //
35 // Revision 1.4  2000/04/06 20:40:22  hurdler
36 // Mostly remove warnings under windows
37 //
38 // Revision 1.3  2000/04/04 00:32:47  stroggonmeth
39 // Initial Boom compatability plus few misc changes all around.
40 //
41 // Revision 1.2  2000/02/27 00:42:10  hurdler
42 // Revision 1.1.1.1  2000/02/22 20:32:32  hurdler
43 // Initial import into CVS (v1.29 pr3)
44 //
45 //
46 // DESCRIPTION:
47 //      Switches, buttons. Two-state animation. Exits.
48 //
49 //-----------------------------------------------------------------------------
50 
51 
52 #include "doomincl.h"
53 #include "g_game.h"
54 #include "p_local.h"
55 #include "s_sound.h"
56 #include "r_main.h"
57 #include "w_wad.h"
58   // SoM: 3/22/2000
59 #include "z_zone.h"
60 #include "t_script.h"
61 #include "m_swap.h"
62   // LE_SWAP16
63 
64 //
65 // CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE
66 //
67 switchlist_t doom_alphSwitchList[] =
68 {
69     // Doom shareware episode 1 switches
70     {"SW1BRCOM","SW2BRCOM",     1},
71     {"SW1BRN1", "SW2BRN1",      1},
72     {"SW1BRN2", "SW2BRN2",      1},
73     {"SW1BRNGN","SW2BRNGN",     1},
74     {"SW1BROWN","SW2BROWN",     1},
75     {"SW1COMM", "SW2COMM",      1},
76     {"SW1COMP", "SW2COMP",      1},
77     {"SW1DIRT", "SW2DIRT",      1},
78     {"SW1EXIT", "SW2EXIT",      1},
79     {"SW1GRAY", "SW2GRAY",      1},
80     {"SW1GRAY1","SW2GRAY1",     1},
81     {"SW1METAL","SW2METAL",     1},
82     {"SW1PIPE", "SW2PIPE",      1},
83     {"SW1SLAD", "SW2SLAD",      1},
84     {"SW1STARG","SW2STARG",     1},
85     {"SW1STON1","SW2STON1",     1},
86     {"SW1STON2","SW2STON2",     1},
87     {"SW1STONE","SW2STONE",     1},
88     {"SW1STRTN","SW2STRTN",     1},
89 
90     // Doom registered episodes 2&3 switches
91     {"SW1BLUE", "SW2BLUE",      2},
92     {"SW1CMT",  "SW2CMT",       2},
93     {"SW1GARG", "SW2GARG",      2},
94     {"SW1GSTON","SW2GSTON",     2},
95     {"SW1HOT",  "SW2HOT",       2},
96     {"SW1LION", "SW2LION",      2},
97     {"SW1SATYR","SW2SATYR",     2},
98     {"SW1SKIN", "SW2SKIN",      2},
99     {"SW1VINE", "SW2VINE",      2},
100     {"SW1WOOD", "SW2WOOD",      2},
101 
102     // Doom II switches
103     {"SW1PANEL","SW2PANEL",     3},
104     {"SW1ROCK", "SW2ROCK",      3},
105     {"SW1MET2", "SW2MET2",      3},
106     {"SW1WDMET","SW2WDMET",     3},
107     {"SW1BRIK", "SW2BRIK",      3},
108     {"SW1MOD1", "SW2MOD1",      3},
109     {"SW1ZIM",  "SW2ZIM",       3},
110     {"SW1STON6","SW2STON6",     3},
111     {"SW1TEK",  "SW2TEK",       3},
112     {"SW1MARB", "SW2MARB",      3},
113     {"SW1SKULL","SW2SKULL",     3},
114 
115     {"\0",      "\0",           0}
116 };
117 
118 switchlist_t heretic_alphSwitchList[] =
119 {
120     // heretic
121     {"SW1OFF",  "SW1ON",        1},
122     {"SW2OFF",  "SW2ON",        1},
123 
124     {"\0",      "\0",           0}
125 };
126 
127 //SoM: 3/22/2000: Switch limit removal
128 
129 // Increment in switches array.  May be as small as 2, or more than 40.
130 #define NUMSWITCHES_INC  32
131 
132 static int *  switchlist = NULL;  // malloc
133 static int    max_numswitches = 0;  // allocated switch array
134 static int    numswitches = 0;  // actual number of entries in switchlist
135 static int    numswitch_pairs = 0;  // strangness from Doom, renamed numswitches
136 
137 button_t      buttonlist[MAXBUTTONS];
138 
139 
140 //
141 // P_Init_SwitchList
142 // - this is now called at P_SetupLevel () time.
143 //
144 //SoM: 3/22/2000: Use boom code.
P_Init_SwitchList(void)145 void P_Init_SwitchList(void)
146 {
147   int            i, index = 0;
148   int            episode; // select switches based on game
149   switchlist_t   * alphSwitchList = NULL;
150   switchlist_t   * switches_lump = NULL;
151 
152   //SoM: 3/22/2000: No Switches lump? Use old table!
153   // DOOM, HERETIC, and HERETIC shareware do not have SWITCHES lump.
154   alphSwitchList = doom_alphSwitchList;  // default
155   switch (gamemode){
156       case doom_registered :
157       case ultdoom_retail:
158           episode = 2;
159           break;
160       case doom2_commercial :
161           episode = 3;
162           break;
163       case heretic :
164           episode = 4;  // As was in 1.45, Blasphemer may need this as test.
165 #if 0
166           // Like Heretic.  But it would not gain anything because
167           // there are only two switches in the list and both are needed.
168           if( gamedesc_id == GDESC_heretic )
169             episode = 2;
170           if( gamedesc_id == GDESC_heretic_shareware )
171             episode = 1;
172 #endif
173           alphSwitchList = heretic_alphSwitchList;
174           break;
175       default:
176           episode = 1;
177   }
178 
179   // Check for Boom SWITCHES lump.
180   if( VALID_LUMP( W_CheckNumForName("SWITCHES") ) )
181   {
182     // Load the SWITCHES lump.
183     switches_lump = (switchlist_t *)W_CacheLumpName("SWITCHES", PU_IN_USE);
184     alphSwitchList = switches_lump;
185 // __BIG_ENDIAN__ is defined on MAC compilers, not on WIN, nor LINUX
186 #ifdef __BIG_ENDIAN__
187     // [WDJ] Endian conversion, only when BIG_ENDIAN, when from wad,
188     // and not when cache hit.
189     if( lump_read )
190     {
191       // endian conversion only when loading from extra lump
192       for (i=0;alphSwitchList[i].episode!=0;i++)
193         alphSwitchList[i].episode = (uint16_t)( LE_SWAP16(alphSwitchList[i].episode) );
194     }
195 #endif
196   }
197 
198   // initialization for artificial levels without switches (yes, they exist!)
199   if( switchlist == NULL )
200       switchlist = malloc(sizeof(*switchlist));
201 
202   for (i=0;alphSwitchList[i].episode!=0;i++)
203   {
204     if (index+1 >= max_numswitches)  // use 2 at a time
205     {
206       // [WDJ] Unnecessary complicated *2 size, simplified to inc size.
207       // Must have 1 extra for terminating -1 entry.
208       max_numswitches += NUMSWITCHES_INC;
209       switchlist = realloc(switchlist, sizeof(*switchlist) * (max_numswitches+1) );
210     }
211 
212     // [WDJ] 11/9/2012, remove restriction on Heretic using SWITCHES lump.
213     // [WDJ] 9/1/2016, handle default list without error messages.
214     // Blasphemer may have a SWITCHES lump, cannot assume contents.
215     if (alphSwitchList[i].episode <= episode)
216     {
217       // Check, without error first.
218       int tex1 = R_CheckTextureNumForName(alphSwitchList[i].name1);
219       int tex2 = R_CheckTextureNumForName(alphSwitchList[i].name2);
220       // default missing textures to texture 1
221       if( tex1 == -1 )
222       {
223           I_SoftError("Switch %i missing texture %s, using 1\n", i, alphSwitchList[i].name1 );
224           tex1 = 1;
225       }
226       if( tex2 == -1 )
227       {
228           I_SoftError("Switch %i missing texture %s, using 1\n", i, alphSwitchList[i].name2 );
229           tex2 = 1;
230       }
231       switchlist[index++] = tex1;
232       switchlist[index++] = tex2;
233     }
234   }
235 
236   // [WDJ] The index/2 is from Doom and Heretic.  It accomplishes nothing as
237   // the only usage had it *2 again. Made it less misleading.
238   numswitch_pairs = index/2;
239   numswitches = numswitch_pairs * 2;
240   switchlist[index] = -1;  // unnecessary, never checked
241 
242   //SoM: 3/22/2000: Don't change tag if not from lump
243   if( switches_lump )
244     Z_ChangeTag( switches_lump, PU_CACHE);
245 }
246 
247 
248 //
249 // Start a button counting down till it turns off.
250 //
251 static
P_StartButton(line_t * line,bwhere_e w,int texture,int timer)252 void P_StartButton ( line_t*       line,
253                      bwhere_e      w,
254                      int           texture,
255                      int           timer )
256 {
257     int         i;
258 
259     // See if button is already pressed
260     for (i = 0;i < MAXBUTTONS;i++)
261     {
262       if (buttonlist[i].btimer && buttonlist[i].line == line)
263         return;
264     }
265 
266     for (i = 0;i < MAXBUTTONS;i++)
267     {
268         if (!buttonlist[i].btimer)
269         {
270             buttonlist[i].line = line;
271             buttonlist[i].where = w;
272             buttonlist[i].btexture = texture;
273             buttonlist[i].btimer = timer;
274             // Bug fix: Save button sound origin as sector (xyz_t*)
275             buttonlist[i].soundorg = &line->frontsector->soundorg;
276             return;
277         }
278     }
279 
280     I_Error("P_StartButton: no button slots left!");
281 }
282 
283 
284 
285 
286 
287 //
288 // Function that changes wall texture.
289 // Tell it if switch is ok to use again (1=yes, it's a button).
290 //
P_ChangeSwitchTexture(line_t * line,int useAgain)291 void P_ChangeSwitchTexture ( line_t*       line,
292                              int           useAgain )
293 {
294     int     texTop, texMid, texBot;
295     int     i;
296     int     sound;
297     side_t * swside;
298 
299     if ( line->sidenum[0] == NULL_INDEX )
300         goto done;  // fragglescript dummy line
301 
302     swside = & sides[line->sidenum[0]];
303 
304     if (!useAgain)
305         line->special = 0;
306 
307     // texture num are either 0=no-texture, or valid
308     texTop = swside->toptexture;
309     texMid = swside->midtexture;
310     texBot = swside->bottomtexture;
311 
312     sound = sfx_swtchn;
313 
314     // EXIT SWITCH?
315     if (line->special == 11)
316         sound = sfx_swtchx;
317 
318     for (i = 0; i < numswitches; i++)
319     {
320         if (switchlist[i] == texTop)
321         {
322             S_StartXYZSound(buttonlist->soundorg, sound);
323             swside->toptexture = switchlist[i^1];
324 
325             if (useAgain)
326                 P_StartButton(line, B_top_texture, switchlist[i], BUTTONTIME);
327 
328             goto done;
329         }
330         else
331         {
332             if (switchlist[i] == texMid)
333             {
334                 S_StartXYZSound(buttonlist->soundorg, sound);
335                 swside->midtexture = switchlist[i^1];
336                 if (useAgain)
337                     P_StartButton(line, B_middle_texture, switchlist[i], BUTTONTIME);
338 
339                 return;
340             }
341             else
342             {
343                 if (switchlist[i] == texBot)
344                 {
345                     S_StartXYZSound(buttonlist->soundorg, sound);
346                     swside->bottomtexture = switchlist[i^1];
347 
348                     if (useAgain)
349                         P_StartButton(line, B_bottom_texture, switchlist[i], BUTTONTIME);
350 
351                     goto done;
352                 }
353             }
354         }
355     }
356 done:
357     return;
358 }
359 
360 
361 //
362 // P_UseSpecialLine
363 // Called when a thing uses a special line.
364 // Only the front sides of lines are usable.
365 //
366 // For monsters, return true when is a door that actor can use ??
367 // (is actually when any monster operated switch).
368 // For players, return true when switch is activated.
P_UseSpecialLine(mobj_t * thing,line_t * line,int side)369 boolean P_UseSpecialLine ( mobj_t*       thing,
370                            line_t*       line,
371                            int           side )
372 {
373 
374     // Err...
375     // Use the back sides of VERY SPECIAL lines...
376     if (side)  goto nopass;
377 
378     //SoM: 3/18/2000: Add check for Generalized linedefs.
379     if (EN_boom)
380     {
381       // pointer to line function is NULL by default, set non-null if
382       // line special is push or switch generalized linedef type
383       int (*linefunc)(line_t *line)=NULL;
384 
385       // check each range of generalized linedefs
386       if ((unsigned)line->special >= (GenFloorBase+0x2000))
387       {} // not boom generalized
388       else if ((unsigned)line->special >= GenFloorBase)
389       {
390         if (!thing->player)
391           if ((line->special & FloorChange) || !(line->special & FloorModel))
392             goto nopass; // FloorModel is "Allow Monsters" if FloorChange is 0
393         if (!line->tag && ((line->special&6)!=6)) //all non-manual
394           goto nopass;  //generalized types require tag
395         linefunc = EV_DoGenFloor;
396       }
397       else if ((unsigned)line->special >= GenCeilingBase)
398       {
399         if (!thing->player)
400           if ((line->special & CeilingChange) || !(line->special & CeilingModel))
401             goto nopass;   // CeilingModel is "Allow Monsters" if CeilingChange is 0
402         if (!line->tag && ((line->special&6)!=6)) //all non-manual
403           goto nopass;  //generalized types require tag
404         linefunc = EV_DoGenCeiling;
405       }
406       else if ((unsigned)line->special >= GenDoorBase)
407       {
408         if (!thing->player)
409         {
410           if (!(line->special & DoorMonster))
411             goto nopass;  // monsters disallowed from this door
412           if (line->flags & ML_SECRET) // they can't open secret doors either
413             goto nopass;
414         }
415         if (!line->tag && ((line->special&6)!=6)) //all non-manual
416           goto nopass;  //generalized types require tag
417         linefunc = EV_DoGenDoor;
418       }
419       else if ((unsigned)line->special >= GenLockedBase)
420       {
421         if (!thing->player)
422           goto nopass;  // monsters disallowed from unlocking doors
423         if (!P_CanUnlockGenDoor(line,thing->player))
424           goto nopass;
425         if (!line->tag && ((line->special&6)!=6)) //all non-manual
426           goto nopass;  //generalized types require tag
427 
428         linefunc = EV_DoGenLockedDoor;
429       }
430       else if ((unsigned)line->special >= GenLiftBase)
431       {
432         if (!thing->player)
433           if (!(line->special & LiftMonster))
434             goto nopass;  // monsters disallowed
435         if (!line->tag && ((line->special&6)!=6)) //all non-manual
436           goto nopass;  //generalized types require tag
437         linefunc = EV_DoGenLift;
438       }
439       else if ((unsigned)line->special >= GenStairsBase)
440       {
441         if (!thing->player)
442           if (!(line->special & StairMonster))
443             goto nopass;  // monsters disallowed
444         if (!line->tag && ((line->special&6)!=6)) //all non-manual
445           goto nopass;  //generalized types require tag
446         linefunc = EV_DoGenStairs;
447       }
448       else if ((unsigned)line->special >= GenCrusherBase)
449       {
450         if (!thing->player)
451           if (!(line->special & CrusherMonster))
452             goto nopass;  // monsters disallowed
453         if (!line->tag && ((line->special&6)!=6)) //all non-manual
454           goto nopass;  //generalized types require tag
455         linefunc = EV_DoGenCrusher;
456       }
457 
458       if (linefunc)
459       {
460         switch((line->special & TriggerType) >> TriggerTypeShift)
461         {
462           case TRIG_PushOnce:
463             if (!side)
464               if (linefunc(line))
465                 line->special = 0;
466             goto pass;
467           case TRIG_PushMany:
468             if (!side)
469               linefunc(line);
470             goto pass;
471           case TRIG_SwitchOnce:
472             if (linefunc(line))
473               P_ChangeSwitchTexture(line,0);
474             goto pass;
475           case TRIG_SwitchMany:
476             if (linefunc(line))
477               P_ChangeSwitchTexture(line,1);
478             goto pass;
479           default:  // if not a switch/push type, do nothing here
480             goto nopass;
481         }
482       }
483     }
484 
485 
486 
487     // Switches that other things can activate.
488     if (!thing->player)
489     {
490         // monsters never open secret doors
491         if (line->flags & ML_SECRET)
492             goto nopass;
493 
494         // the only doors and switches that monsters can activate
495         switch(line->special)
496         {
497           case 1:       // MANUAL DOOR RAISE
498           case 32:      // MANUAL BLUE
499           case 33:      // MANUAL RED
500           case 34:      // MANUAL YELLOW
501           //SoM: 3/18/2000: add ability to use teleporters for monsters
502           case 195:       // switch teleporters
503           case 174:
504           case 210:       // silent switch teleporters
505           case 209:
506             break;
507 
508           default:
509             goto nopass;  // monsters exit
510         }
511     }
512     // monsters past this point have been checked OK for using the switch
513 
514     if (EN_boom && !P_CheckTag(line))  //disallow zero tag on some types
515       goto nopass;
516 
517     // do something
518     switch (line->special)
519     {
520         // MANUALS
521       case 1:           // Vertical Door
522       case 26:          // Blue Door/Locked
523       case 27:          // Yellow Door /Locked
524       case 28:          // Red Door /Locked
525 
526       case 31:          // Manual door open
527       case 32:          // Blue locked door open
528       case 33:          // Red locked door open
529       case 34:          // Yellow locked door open
530 
531       case 117:         // Blazing door raise
532       case 118:         // Blazing door open
533         EV_VerticalDoor (line, thing);
534         break;
535 
536         //UNUSED - Door Slide Open&Close
537         // case 124:
538         // EV_SlidingDoor (line, thing);
539         // break;
540 
541         // SWITCHES
542       case 7:
543         // Build Stairs
544         if (EV_BuildStairs( line, (EN_heretic)? 8*FRACUNIT : ST_build8))
545             goto switch_1_clear;
546         break;
547 
548       case 107:
549         if( EN_heretic )
550         {
551             if (EV_BuildStairs (line, 16 * FRACUNIT))
552                 goto switch_1_clear;
553         }
554         break;
555 
556       case 9:
557         // Change Donut
558         if (EV_DoDonut(line))
559             goto switch_1_clear;
560         break;
561 
562       case 11:
563         // Exit level
564         if(cv_allowexitlevel.EV)
565         {
566             P_ChangeSwitchTexture(line,0);
567             G_ExitLevel ();
568         }
569         break;
570 
571       case 14:
572         // Raise Floor 32 and change texture
573         if (EV_DoPlat( line, PLATT_raiseAndChange, 32))
574             goto switch_1_clear;
575         break;
576 
577       case 15:
578         // Raise Floor 24 and change texture
579         if (EV_DoPlat( line, PLATT_raiseAndChange, 24))
580             goto switch_1_clear;
581         break;
582 
583       case 18:
584         // Raise Floor to next highest floor
585         if (EV_DoFloor( line, FT_raiseFloorToNearest))
586             goto switch_1_clear;
587         break;
588 
589       case 20:
590         // Raise Plat next highest floor and change texture
591         if (EV_DoPlat( line, PLATT_raiseToNearestAndChange, 0))
592             goto switch_1_clear;
593         break;
594 
595       case 21:
596         // PlatDownWaitUpStay
597         if (EV_DoPlat( line, PLATT_downWaitUpStay, 0))
598             goto switch_1_clear;
599         break;
600 
601       case 23:
602         // Lower Floor to Lowest
603         if (EV_DoFloor( line, FT_lowerFloorToLowest))
604             goto switch_1_clear;
605         break;
606 
607       case 29:
608         // Raise Door
609         if (EV_DoDoor( line, VD_normalDoor, VDOORSPEED))
610             goto switch_1_clear;
611         break;
612 
613       case 41:
614         // Lower Ceiling to Floor
615         if (EV_DoCeiling( line, CT_lowerToFloor))
616             goto switch_1_clear;
617         break;
618 
619       case 71:
620         // Turbo Lower Floor
621         if (EV_DoFloor( line, FT_turboLower))
622             goto switch_1_clear;
623         break;
624 
625       case 49:
626         // Ceiling Crush And Raise
627         if (EV_DoCeiling( line, (EN_heretic)? CT_lowerAndCrush : CT_crushAndRaise))
628             goto switch_1_clear;
629         break;
630 
631       case 50:
632         // Close Door
633         if (EV_DoDoor( line, VD_doorclose, VDOORSPEED))
634             goto switch_1_clear;
635         break;
636 
637       case 51:
638         // Secret EXIT
639         P_ChangeSwitchTexture(line,0);
640         G_SecretExitLevel ();
641         break;
642 
643       case 55:
644         // Raise Floor Crush
645         if (EV_DoFloor( line, FT_raiseFloorCrush))
646             goto switch_1_clear;
647         break;
648 
649       case 101:
650         // Raise Floor
651         if (EV_DoFloor( line, FT_raiseFloor))
652             goto switch_1_clear;
653         break;
654 
655       case 102:
656         // Lower Floor to Surrounding floor height
657         if (EV_DoFloor( line, FT_lowerFloor))
658             goto switch_1_clear;
659         break;
660 
661       case 103:
662         // Open Door
663         if (EV_DoDoor( line, VD_dooropen, VDOORSPEED))
664             goto switch_1_clear;
665         break;
666 
667       case 111:
668         // Blazing Door Raise (faster than TURBO!)
669         if (EV_DoDoor( line, VD_blazeRaise, 4*VDOORSPEED))
670             goto switch_1_clear;
671         break;
672 
673       case 112:
674         // Blazing Door Open (faster than TURBO!)
675         if (EV_DoDoor( line, VD_blazeOpen, 4*VDOORSPEED))
676             goto switch_1_clear;
677         break;
678 
679       case 113:
680         // Blazing Door Close (faster than TURBO!)
681         if (EV_DoDoor( line, VD_blazeClose, 4*VDOORSPEED))
682             goto switch_1_clear;
683         break;
684 
685       case 122:
686         // Blazing PlatDownWaitUpStay
687         if (EV_DoPlat( line, PLATT_blazeDWUS, 0))
688             goto switch_1_clear;
689         break;
690 
691       case 127:
692         // Build Stairs Turbo 16
693         if (EV_BuildStairs( line, ST_turbo16))
694             goto switch_1_clear;
695         break;
696 
697       case 131:
698         // Raise Floor Turbo
699         if (EV_DoFloor( line, FT_raiseFloorTurbo))
700             goto switch_1_clear;
701         break;
702 
703       case 133:
704         // BlzOpenDoor BLUE
705       case 135:
706         // BlzOpenDoor RED
707       case 137:
708         // BlzOpenDoor YELLOW
709         if (EV_DoLockedDoor( line, VD_blazeOpen, thing, 4*VDOORSPEED))
710             goto switch_1_clear;
711         break;
712 
713       case 140:
714         // Raise Floor 512
715         if (EV_DoFloor( line, FT_raiseFloor512))
716             goto switch_1_clear;
717         break;
718 
719       //SoM: FraggleScript!
720       case 276:
721       case 277:
722         T_RunScript(line->tag, thing);
723         if(line->special == 277)
724         {
725           line->special = 0;         // clear tag
726           P_ChangeSwitchTexture(line,0);
727         }
728         else
729           P_ChangeSwitchTexture(line,1);
730         break;
731 
732       default:
733         if (EN_boom)
734         {
735           switch (line->special)
736           {
737             // added linedef types to fill all functions out so that
738             // all possess SR, S1, WR, W1 types
739 
740             case 158:
741               // Raise Floor to shortest lower texture
742               if (EV_DoFloor( line, FT_raiseToTexture))
743                 goto switch_1_clear;
744               break;
745 
746             case 159:
747               // Raise Floor to shortest lower texture
748               if (EV_DoFloor( line, FT_lowerAndChange))
749                 goto switch_1_clear;
750               break;
751 
752             case 160:
753               // Raise Floor 24 and change
754               if (EV_DoFloor( line, FT_raiseFloor24AndChange))
755                 goto switch_1_clear;
756               break;
757 
758             case 161:
759               // Raise Floor 24
760               if (EV_DoFloor( line, FT_raiseFloor24))
761                 goto switch_1_clear;
762               break;
763 
764             case 162:
765               // Moving floor min n to max n
766               if (EV_DoPlat( line, PLATT_perpetualRaise, 0))
767                 goto switch_1_clear;
768               break;
769 
770             case 163:
771               // Stop Moving floor
772               EV_StopPlat(line);
773               goto switch_1_clear;
774 
775             case 164:
776               // Start fast crusher
777               if (EV_DoCeiling( line, CT_fastCrushAndRaise))
778                 goto switch_1_clear;
779               break;
780 
781             case 165:
782               // Start slow silent crusher
783               if (EV_DoCeiling( line, CT_silentCrushAndRaise))
784                 goto switch_1_clear;
785               break;
786 
787             case 166:
788               // Raise ceiling, Lower floor
789               if (EV_DoCeiling( line, CT_raiseToHighest) ||
790                   EV_DoFloor( line, FT_lowerFloorToLowest))
791                 goto switch_1_clear;
792               break;
793 
794             case 167:
795               // Lower floor and Crush
796               if (EV_DoCeiling( line, CT_lowerAndCrush))
797                 goto switch_1_clear;
798               break;
799 
800             case 168:
801               // Stop crusher
802               if (EV_CeilingCrushStop(line))
803                 goto switch_1_clear;
804               break;
805 
806             case 169:
807               // Lights to brightest neighbor sector
808               EV_LightTurnOn(line,0);
809               goto switch_1_clear;
810 
811             case 170:
812               // Lights to near dark
813               EV_LightTurnOn(line,35);
814               goto switch_1_clear;
815 
816             case 171:
817               // Lights on full
818               EV_LightTurnOn(line,255);
819               goto switch_1_clear;
820 
821             case 172:
822               // Start Lights Strobing
823               EV_StartLightStrobing(line);
824               goto switch_1_clear;
825 
826             case 173:
827               // Lights to Dimmest Near
828               EV_TurnTagLightsOff(line);
829               goto switch_1_clear;
830 
831             case 174:
832               // Teleport
833               if (EV_Teleport(line,side,thing))
834                 goto switch_1_clear;
835               break;
836 
837             case 175:
838               // Close Door, Open in 30 secs
839               if (EV_DoDoor( line, VD_close30ThenOpen, VDOORSPEED))
840                 goto switch_1_clear;
841               break;
842 
843             case 189: //create texture change no motion type
844               // Texture Change Only (Trigger)
845               if (EV_DoChange( line, CH_MODEL_trig_only))
846                 goto switch_1_clear;
847               break;
848 
849             case 203:
850               // Lower ceiling to lowest surrounding ceiling
851               if (EV_DoCeiling( line, CT_lowerToLowest))
852                 goto switch_1_clear;
853               break;
854 
855             case 204:
856               // Lower ceiling to highest surrounding floor
857               if (EV_DoCeiling( line, CT_lowerToMaxFloor))
858                 goto switch_1_clear;
859               break;
860 
861             case 209:
862               // killough 1/31/98: silent teleporter
863               if (EV_SilentTeleport(line, side, thing))
864                 goto switch_1_clear;
865               break;
866 
867             case 241: //jff 3/15/98 create texture change no motion type
868               // Texture Change Only (Numeric)
869               if (EV_DoChange( line, CH_MODEL_num_only))
870                 goto switch_1_clear;
871               break;
872 
873             case 221:
874               // Lower floor to next lowest floor
875               if (EV_DoFloor( line, FT_lowerFloorToNearest))
876                 goto switch_1_clear;
877               break;
878 
879             case 229:
880               // Raise elevator next floor
881               if (EV_DoElevator( line, ET_elevateUp))
882                 goto switch_1_clear;
883               break;
884 
885             case 233:
886               // Lower elevator next floor
887               if (EV_DoElevator( line, ET_elevateDown))
888                 goto switch_1_clear;
889               break;
890 
891             case 237:
892               // Elevator to current floor
893               if (EV_DoElevator( line, ET_elevateCurrent))
894                 goto switch_1_clear;
895               break;
896 
897 
898             //end of added S1 linedef types
899 
900             //added linedef types to fill all functions out so that
901             //all possess SR, S1, WR, W1 types
902 
903             case 78:
904               // Texture/type Change Only (Numeric)
905               if (EV_DoChange( line, CH_MODEL_num_only))
906                 goto switch_R;
907               break;
908 
909             case 176:
910               // Raise Floor to shortest lower texture
911               if (EV_DoFloor( line, FT_raiseToTexture))
912                 goto switch_R;
913               break;
914 
915             case 177:
916               // Raise Floor to shortest lower texture
917               if (EV_DoFloor( line, FT_lowerAndChange))
918                 goto switch_R;
919               break;
920 
921             case 178:
922               // Raise Floor 512
923               if (EV_DoFloor( line, FT_raiseFloor512))
924                 goto switch_R;
925               break;
926 
927             case 179:
928               // Raise Floor 24 and change
929               if (EV_DoFloor( line, FT_raiseFloor24AndChange))
930                 goto switch_R;
931               break;
932 
933             case 180:
934               // Raise Floor 24
935               if (EV_DoFloor( line, FT_raiseFloor24))
936                 goto switch_R;
937               break;
938 
939             case 181:
940               // Moving floor min n to max n
941               EV_DoPlat( line, PLATT_perpetualRaise, 0);
942               goto switch_R;
943               break;
944 
945             case 182:
946               // Stop Moving floor
947               EV_StopPlat(line);
948               goto switch_R;
949               break;
950 
951             case 183:
952               // Start fast crusher
953               if (EV_DoCeiling( line, CT_fastCrushAndRaise))
954                 goto switch_R;
955               break;
956 
957             case 184:
958               // Start slow crusher
959               if (EV_DoCeiling( line, CT_crushAndRaise))
960                 goto switch_R;
961               break;
962 
963             case 185:
964               // Start slow silent crusher
965               if (EV_DoCeiling( line, CT_silentCrushAndRaise))
966                 goto switch_R;
967               break;
968 
969             case 186:
970               // Raise ceiling, Lower floor
971               if (EV_DoCeiling( line, CT_raiseToHighest) ||
972                   EV_DoFloor( line, FT_lowerFloorToLowest))
973                 goto switch_R;
974               break;
975 
976             case 187:
977               // Lower floor and Crush
978               if (EV_DoCeiling( line, CT_lowerAndCrush))
979                 goto switch_R;
980               break;
981 
982             case 188:
983               // Stop crusher
984               if (EV_CeilingCrushStop(line))
985                 goto switch_R;
986               break;
987 
988             case 190: //jff 3/15/98 create texture change no motion type
989               // Texture Change Only (Trigger)
990               if (EV_DoChange( line, CH_MODEL_trig_only))
991                 goto switch_R;
992               break;
993 
994             case 191:
995               // Lower Pillar, Raise Donut
996               if (EV_DoDonut(line))
997                 goto switch_R;
998               break;
999 
1000             case 192:
1001               // Lights to brightest neighbor sector
1002               EV_LightTurnOn(line,0);
1003               goto switch_R;
1004               break;
1005 
1006             case 193:
1007               // Start Lights Strobing
1008               EV_StartLightStrobing(line);
1009               goto switch_R;
1010               break;
1011 
1012             case 194:
1013               // Lights to Dimmest Near
1014               EV_TurnTagLightsOff(line);
1015               goto switch_R;
1016               break;
1017 
1018             case 195:
1019               // Teleport
1020               if (EV_Teleport(line,side,thing))
1021                 goto switch_R;
1022               break;
1023 
1024             case 196:
1025               // Close Door, Open in 30 secs
1026               if (EV_DoDoor( line, VD_close30ThenOpen, VDOORSPEED))
1027                 goto switch_R;
1028               break;
1029 
1030             case 205:
1031               // Lower ceiling to lowest surrounding ceiling
1032               if (EV_DoCeiling( line, CT_lowerToLowest))
1033                 goto switch_R;
1034               break;
1035 
1036             case 206:
1037               // Lower ceiling to highest surrounding floor
1038               if (EV_DoCeiling( line, CT_lowerToMaxFloor))
1039                 goto switch_R;
1040               break;
1041 
1042             case 210:
1043               // Silent teleporter
1044               if (EV_SilentTeleport(line, side, thing))
1045                 goto switch_R;
1046               break;
1047 
1048             case 211:
1049               // Toggle Floor Between C and F Instantly
1050               if (EV_DoPlat( line, PLATT_toggleUpDn, 0))
1051                 goto switch_R;
1052               break;
1053 
1054             case 222:
1055               // Lower floor to next lowest floor
1056               if (EV_DoFloor( line, FT_lowerFloorToNearest))
1057                 goto switch_R;
1058               break;
1059 
1060             case 230:
1061               // Raise elevator next floor
1062               if (EV_DoElevator( line, ET_elevateUp))
1063                 goto switch_R;
1064               break;
1065 
1066             case 234:
1067               // Lower elevator next floor
1068               if (EV_DoElevator( line, ET_elevateDown))
1069                 goto switch_R;
1070               break;
1071 
1072             case 238:
1073               // Elevator to current floor
1074               if (EV_DoElevator( line, ET_elevateCurrent))
1075                 goto switch_R;
1076               break;
1077 
1078             case 258:
1079               // Build stairs, step 8
1080               if (EV_BuildStairs( line, ST_build8))
1081                 goto switch_R;
1082               break;
1083 
1084             case 259:
1085               // Build stairs, step 16
1086               if (EV_BuildStairs( line, ST_turbo16))
1087                 goto switch_R;
1088               break;
1089 
1090             // end of added SR linedef types
1091 
1092           }
1093         }
1094         break;
1095 
1096 
1097         // BUTTONS
1098       case 42:
1099         // Close Door
1100         if (EV_DoDoor( line, VD_doorclose, VDOORSPEED))
1101             goto switch_R;
1102         break;
1103 
1104       case 43:
1105         // Lower Ceiling to Floor
1106         if (EV_DoCeiling( line, CT_lowerToFloor))
1107             goto switch_R;
1108         break;
1109 
1110       case 45:
1111         // Lower Floor to Surrounding floor height
1112         if (EV_DoFloor( line, FT_lowerFloor))
1113             goto switch_R;
1114         break;
1115 
1116       case 60:
1117         // Lower Floor to Lowest
1118         if (EV_DoFloor( line, FT_lowerFloorToLowest))
1119             goto switch_R;
1120         break;
1121 
1122       case 61:
1123         // Open Door
1124         if (EV_DoDoor( line, VD_dooropen, VDOORSPEED))
1125             goto switch_R;
1126         break;
1127 
1128       case 62:
1129         // PlatDownWaitUpStay
1130         if (EV_DoPlat( line, PLATT_downWaitUpStay, 1))
1131             goto switch_R;
1132         break;
1133 
1134       case 63:
1135         // Raise Door
1136         if (EV_DoDoor( line, VD_normalDoor, VDOORSPEED))
1137             goto switch_R;
1138         break;
1139 
1140       case 64:
1141         // Raise Floor to ceiling
1142         if (EV_DoFloor( line, FT_raiseFloor))
1143             goto switch_R;
1144         break;
1145 
1146       case 66:
1147         // Raise Floor 24 and change texture
1148         if (EV_DoPlat( line, PLATT_raiseAndChange, 24))
1149             goto switch_R;
1150         break;
1151 
1152       case 67:
1153         // Raise Floor 32 and change texture
1154         if (EV_DoPlat( line, PLATT_raiseAndChange, 32))
1155             goto switch_R;
1156         break;
1157 
1158       case 65:
1159         // Raise Floor Crush
1160         if (EV_DoFloor( line, FT_raiseFloorCrush))
1161             goto switch_R;
1162         break;
1163 
1164       case 68:
1165         // Raise Plat to next highest floor and change texture
1166         if (EV_DoPlat( line, PLATT_raiseToNearestAndChange, 0))
1167             goto switch_R;
1168         break;
1169 
1170       case 69:
1171         // Raise Floor to next highest floor
1172         if (EV_DoFloor( line, FT_raiseFloorToNearest))
1173             goto switch_R;
1174         break;
1175 
1176       case 70:
1177         // Turbo Lower Floor
1178         if (EV_DoFloor( line, FT_turboLower))
1179             goto switch_R;
1180         break;
1181 
1182       case 114:
1183         // Blazing Door Raise (faster than TURBO!)
1184         if (EV_DoDoor( line, VD_blazeRaise, 4*VDOORSPEED))
1185             goto switch_R;
1186         break;
1187 
1188       case 115:
1189         // Blazing Door Open (faster than TURBO!)
1190         if (EV_DoDoor( line, VD_blazeOpen, 4*VDOORSPEED))
1191             goto switch_R;
1192         break;
1193 
1194       case 116:
1195         // Blazing Door Close (faster than TURBO!)
1196         if (EV_DoDoor( line, VD_blazeClose, 4*VDOORSPEED))
1197             goto switch_R;
1198         break;
1199 
1200       case 123:
1201         // Blazing PlatDownWaitUpStay
1202         if (EV_DoPlat( line, PLATT_blazeDWUS, 0))
1203             goto switch_R;
1204         break;
1205 
1206       case 132:
1207         // Raise Floor Turbo
1208         if (EV_DoFloor( line, FT_raiseFloorTurbo))
1209             goto switch_R;
1210         break;
1211 
1212       case 99:
1213         if( EN_heretic ) // used for right scrolling texture
1214             break;
1215         // BlzOpenDoor BLUE
1216       case 134:
1217         // BlzOpenDoor RED
1218       case 136:
1219         // BlzOpenDoor YELLOW
1220         if (EV_DoLockedDoor( line, VD_blazeOpen, thing, 4*VDOORSPEED))
1221             goto switch_R;
1222         break;
1223 
1224       case 138:
1225         // Light Turn On
1226         EV_LightTurnOn(line,255);
1227         goto switch_R;
1228 
1229       case 139:
1230         // Light Turn Off
1231         EV_LightTurnOn(line,35);
1232         goto switch_R;
1233 
1234     }
1235     return true;
1236 
1237 switch_1_clear:
1238     // Clear the special.
1239     P_ChangeSwitchTexture(line, 0);
1240     goto pass;
1241 
1242 
1243 switch_R:
1244     // Allow retrigger.
1245     P_ChangeSwitchTexture(line, 1);
1246 
1247 pass:
1248     // Opened the door, or operated the switch.
1249     return true;
1250 
1251 nopass:
1252     // Blocked due to monster, or wrong side, or illegal tag.
1253     return false;
1254 }
1255