1 //
2 // Copyright(C) 1993-1996 Id Software, Inc.
3 // Copyright(C) 1993-2008 Raven Software
4 // Copyright(C) 2005-2014 Simon Howard
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 
17 // P_Spec.c
18 
19 #include "doomdef.h"
20 #include "deh_str.h"
21 #include "i_system.h"
22 #include "i_timer.h"
23 #include "m_random.h"
24 #include "p_local.h"
25 #include "s_sound.h"
26 #include "v_video.h"
27 
28 // Macros
29 
30 #define MAX_AMBIENT_SFX 8       // Per level
31 
32 // Types
33 
34 typedef enum
35 {
36     afxcmd_play,                // (sound)
37     afxcmd_playabsvol,          // (sound, volume)
38     afxcmd_playrelvol,          // (sound, volume)
39     afxcmd_delay,               // (ticks)
40     afxcmd_delayrand,           // (andbits)
41     afxcmd_end                  // ()
42 } afxcmd_t;
43 
44 // Data
45 
46 int *LevelAmbientSfx[MAX_AMBIENT_SFX];
47 int *AmbSfxPtr;
48 int AmbSfxCount;
49 int AmbSfxTics;
50 int AmbSfxVolume;
51 
52 int AmbSndSeqInit[] = {         // Startup
53     afxcmd_end
54 };
55 int AmbSndSeq1[] = {            // Scream
56     afxcmd_play, sfx_amb1,
57     afxcmd_end
58 };
59 int AmbSndSeq2[] = {            // Squish
60     afxcmd_play, sfx_amb2,
61     afxcmd_end
62 };
63 int AmbSndSeq3[] = {            // Drops
64     afxcmd_play, sfx_amb3,
65     afxcmd_delay, 16,
66     afxcmd_delayrand, 31,
67     afxcmd_play, sfx_amb7,
68     afxcmd_delay, 16,
69     afxcmd_delayrand, 31,
70     afxcmd_play, sfx_amb3,
71     afxcmd_delay, 16,
72     afxcmd_delayrand, 31,
73     afxcmd_play, sfx_amb7,
74     afxcmd_delay, 16,
75     afxcmd_delayrand, 31,
76     afxcmd_play, sfx_amb3,
77     afxcmd_delay, 16,
78     afxcmd_delayrand, 31,
79     afxcmd_play, sfx_amb7,
80     afxcmd_delay, 16,
81     afxcmd_delayrand, 31,
82     afxcmd_end
83 };
84 int AmbSndSeq4[] = {            // SlowFootSteps
85     afxcmd_play, sfx_amb4,
86     afxcmd_delay, 15,
87     afxcmd_playrelvol, sfx_amb11, -3,
88     afxcmd_delay, 15,
89     afxcmd_playrelvol, sfx_amb4, -3,
90     afxcmd_delay, 15,
91     afxcmd_playrelvol, sfx_amb11, -3,
92     afxcmd_delay, 15,
93     afxcmd_playrelvol, sfx_amb4, -3,
94     afxcmd_delay, 15,
95     afxcmd_playrelvol, sfx_amb11, -3,
96     afxcmd_delay, 15,
97     afxcmd_playrelvol, sfx_amb4, -3,
98     afxcmd_delay, 15,
99     afxcmd_playrelvol, sfx_amb11, -3,
100     afxcmd_end
101 };
102 int AmbSndSeq5[] = {            // Heartbeat
103     afxcmd_play, sfx_amb5,
104     afxcmd_delay, 35,
105     afxcmd_play, sfx_amb5,
106     afxcmd_delay, 35,
107     afxcmd_play, sfx_amb5,
108     afxcmd_delay, 35,
109     afxcmd_play, sfx_amb5,
110     afxcmd_end
111 };
112 int AmbSndSeq6[] = {            // Bells
113     afxcmd_play, sfx_amb6,
114     afxcmd_delay, 17,
115     afxcmd_playrelvol, sfx_amb6, -8,
116     afxcmd_delay, 17,
117     afxcmd_playrelvol, sfx_amb6, -8,
118     afxcmd_delay, 17,
119     afxcmd_playrelvol, sfx_amb6, -8,
120     afxcmd_end
121 };
122 int AmbSndSeq7[] = {            // Growl
123     afxcmd_play, sfx_bstsit,
124     afxcmd_end
125 };
126 int AmbSndSeq8[] = {            // Magic
127     afxcmd_play, sfx_amb8,
128     afxcmd_end
129 };
130 int AmbSndSeq9[] = {            // Laughter
131     afxcmd_play, sfx_amb9,
132     afxcmd_delay, 16,
133     afxcmd_playrelvol, sfx_amb9, -4,
134     afxcmd_delay, 16,
135     afxcmd_playrelvol, sfx_amb9, -4,
136     afxcmd_delay, 16,
137     afxcmd_playrelvol, sfx_amb10, -4,
138     afxcmd_delay, 16,
139     afxcmd_playrelvol, sfx_amb10, -4,
140     afxcmd_delay, 16,
141     afxcmd_playrelvol, sfx_amb10, -4,
142     afxcmd_end
143 };
144 int AmbSndSeq10[] = {           // FastFootsteps
145     afxcmd_play, sfx_amb4,
146     afxcmd_delay, 8,
147     afxcmd_playrelvol, sfx_amb11, -3,
148     afxcmd_delay, 8,
149     afxcmd_playrelvol, sfx_amb4, -3,
150     afxcmd_delay, 8,
151     afxcmd_playrelvol, sfx_amb11, -3,
152     afxcmd_delay, 8,
153     afxcmd_playrelvol, sfx_amb4, -3,
154     afxcmd_delay, 8,
155     afxcmd_playrelvol, sfx_amb11, -3,
156     afxcmd_delay, 8,
157     afxcmd_playrelvol, sfx_amb4, -3,
158     afxcmd_delay, 8,
159     afxcmd_playrelvol, sfx_amb11, -3,
160     afxcmd_end
161 };
162 
163 int *AmbientSfx[] = {
164     AmbSndSeq1,                 // Scream
165     AmbSndSeq2,                 // Squish
166     AmbSndSeq3,                 // Drops
167     AmbSndSeq4,                 // SlowFootsteps
168     AmbSndSeq5,                 // Heartbeat
169     AmbSndSeq6,                 // Bells
170     AmbSndSeq7,                 // Growl
171     AmbSndSeq8,                 // Magic
172     AmbSndSeq9,                 // Laughter
173     AmbSndSeq10                 // FastFootsteps
174 };
175 
176 animdef_t animdefs[] = {
177     // false = flat
178     // true = texture
179     {false, "FLTWAWA3", "FLTWAWA1", 8}, // Water
180     {false, "FLTSLUD3", "FLTSLUD1", 8}, // Sludge
181     {false, "FLTTELE4", "FLTTELE1", 6}, // Teleport
182     {false, "FLTFLWW3", "FLTFLWW1", 9}, // River - West
183     {false, "FLTLAVA4", "FLTLAVA1", 8}, // Lava
184     {false, "FLATHUH4", "FLATHUH1", 8}, // Super Lava
185     {true, "LAVAFL3", "LAVAFL1", 6},    // Texture: Lavaflow
186     {true, "WATRWAL3", "WATRWAL1", 4},  // Texture: Waterfall
187     {-1}
188 };
189 
190 anim_t anims[MAXANIMS];
191 anim_t *lastanim;
192 
193 int *TerrainTypes;
194 struct
195 {
196     char *name;
197     int type;
198 } TerrainTypeDefs[] =
199 {
200     { "FLTWAWA1", FLOOR_WATER },
201     { "FLTFLWW1", FLOOR_WATER },
202     { "FLTLAVA1", FLOOR_LAVA },
203     { "FLATHUH1", FLOOR_LAVA },
204     { "FLTSLUD1", FLOOR_SLUDGE },
205     { "END", -1 }
206 };
207 
208 mobj_t LavaInflictor;
209 
210 //----------------------------------------------------------------------------
211 //
212 // PROC P_InitLava
213 //
214 //----------------------------------------------------------------------------
215 
P_InitLava(void)216 void P_InitLava(void)
217 {
218     memset(&LavaInflictor, 0, sizeof(mobj_t));
219     LavaInflictor.type = MT_PHOENIXFX2;
220     LavaInflictor.flags2 = MF2_FIREDAMAGE | MF2_NODMGTHRUST;
221 }
222 
223 //----------------------------------------------------------------------------
224 //
225 // PROC P_InitTerrainTypes
226 //
227 //----------------------------------------------------------------------------
228 
P_InitTerrainTypes(void)229 void P_InitTerrainTypes(void)
230 {
231     int i;
232     int lump;
233     int size;
234 
235     size = (numflats + 1) * sizeof(int);
236     TerrainTypes = Z_Malloc(size, PU_STATIC, 0);
237     memset(TerrainTypes, 0, size);
238     for (i = 0; TerrainTypeDefs[i].type != -1; i++)
239     {
240         lump = W_CheckNumForName(TerrainTypeDefs[i].name);
241         if (lump != -1)
242         {
243             TerrainTypes[lump - firstflat] = TerrainTypeDefs[i].type;
244         }
245     }
246 }
247 
248 //----------------------------------------------------------------------------
249 //
250 // PROC P_InitPicAnims
251 //
252 //----------------------------------------------------------------------------
253 
P_InitPicAnims(void)254 void P_InitPicAnims(void)
255 {
256     char *startname;
257     char *endname;
258     int i;
259 
260     lastanim = anims;
261     for (i = 0; animdefs[i].istexture != -1; i++)
262     {
263         startname = DEH_String(animdefs[i].startname);
264         endname = DEH_String(animdefs[i].endname);
265 
266         if (animdefs[i].istexture)
267         {                       // Texture animation
268             if (R_CheckTextureNumForName(startname) == -1)
269             {                   // Texture doesn't exist
270                 continue;
271             }
272             lastanim->picnum = R_TextureNumForName(endname);
273             lastanim->basepic = R_TextureNumForName(startname);
274         }
275         else
276         {                       // Flat animation
277             if (W_CheckNumForName(startname) == -1)
278             {                   // Flat doesn't exist
279                 continue;
280             }
281             lastanim->picnum = R_FlatNumForName(endname);
282             lastanim->basepic = R_FlatNumForName(startname);
283         }
284         lastanim->istexture = animdefs[i].istexture;
285         lastanim->numpics = lastanim->picnum - lastanim->basepic + 1;
286         if (lastanim->numpics < 2)
287         {
288             I_Error("P_InitPicAnims: bad cycle from %s to %s",
289                     startname, endname);
290         }
291         lastanim->speed = animdefs[i].speed;
292         lastanim++;
293     }
294 }
295 
296 /*
297 ==============================================================================
298 
299 							UTILITIES
300 
301 ==============================================================================
302 */
303 
304 //
305 //      Will return a side_t* given the number of the current sector,
306 //              the line number, and the side (0/1) that you want.
307 //
getSide(int currentSector,int line,int side)308 side_t *getSide(int currentSector, int line, int side)
309 {
310     return &sides[(sectors[currentSector].lines[line])->sidenum[side]];
311 }
312 
313 //
314 //      Will return a sector_t* given the number of the current sector,
315 //              the line number and the side (0/1) that you want.
316 //
getSector(int currentSector,int line,int side)317 sector_t *getSector(int currentSector, int line, int side)
318 {
319     return sides[(sectors[currentSector].lines[line])->sidenum[side]].sector;
320 }
321 
322 //
323 //      Given the sector number and the line number, will tell you whether
324 //              the line is two-sided or not.
325 //
twoSided(int sector,int line)326 int twoSided(int sector, int line)
327 {
328     return (sectors[sector].lines[line])->flags & ML_TWOSIDED;
329 }
330 
331 //==================================================================
332 //
333 //      Return sector_t * of sector next to current. NULL if not two-sided line
334 //
335 //==================================================================
getNextSector(line_t * line,sector_t * sec)336 sector_t *getNextSector(line_t * line, sector_t * sec)
337 {
338     if (!(line->flags & ML_TWOSIDED))
339         return NULL;
340 
341     if (line->frontsector == sec)
342         return line->backsector;
343 
344     return line->frontsector;
345 }
346 
347 //==================================================================
348 //
349 //      FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS
350 //
351 //==================================================================
P_FindLowestFloorSurrounding(sector_t * sec)352 fixed_t P_FindLowestFloorSurrounding(sector_t * sec)
353 {
354     int i;
355     line_t *check;
356     sector_t *other;
357     fixed_t floor = sec->floorheight;
358 
359     for (i = 0; i < sec->linecount; i++)
360     {
361         check = sec->lines[i];
362         other = getNextSector(check, sec);
363         if (!other)
364             continue;
365         if (other->floorheight < floor)
366             floor = other->floorheight;
367     }
368     return floor;
369 }
370 
371 //==================================================================
372 //
373 //      FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS
374 //
375 //==================================================================
P_FindHighestFloorSurrounding(sector_t * sec)376 fixed_t P_FindHighestFloorSurrounding(sector_t * sec)
377 {
378     int i;
379     line_t *check;
380     sector_t *other;
381     fixed_t floor = -500 * FRACUNIT;
382 
383     for (i = 0; i < sec->linecount; i++)
384     {
385         check = sec->lines[i];
386         other = getNextSector(check, sec);
387         if (!other)
388             continue;
389         if (other->floorheight > floor)
390             floor = other->floorheight;
391     }
392     return floor;
393 }
394 
395 //==================================================================
396 //
397 //      FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS
398 //
399 //==================================================================
P_FindNextHighestFloor(sector_t * sec,int currentheight)400 fixed_t P_FindNextHighestFloor(sector_t * sec, int currentheight)
401 {
402     int i;
403     int h;
404     fixed_t min;
405     line_t *check;
406     sector_t *other;
407     fixed_t height = currentheight;
408 
409     min = INT_MAX;
410 
411     for (i = 0, h = 0; i < sec->linecount; i++)
412     {
413         check = sec->lines[i];
414         other = getNextSector(check, sec);
415 
416         if (other != NULL && other->floorheight > height)
417         {
418             if (other->floorheight < min)
419             {
420                 min = other->floorheight;
421             }
422 
423             ++h;
424         }
425     }
426 
427     // Compatibility note, in case of demo desyncs.
428 
429     if (h > 20)
430     {
431         fprintf(stderr, "P_FindNextHighestFloor: exceeded Vanilla limit\n");
432     }
433 
434     return min;
435 }
436 
437 //==================================================================
438 //
439 //      FIND LOWEST CEILING IN THE SURROUNDING SECTORS
440 //
441 //==================================================================
P_FindLowestCeilingSurrounding(sector_t * sec)442 fixed_t P_FindLowestCeilingSurrounding(sector_t * sec)
443 {
444     int i;
445     line_t *check;
446     sector_t *other;
447     fixed_t height = INT_MAX;
448 
449     for (i = 0; i < sec->linecount; i++)
450     {
451         check = sec->lines[i];
452         other = getNextSector(check, sec);
453         if (!other)
454             continue;
455         if (other->ceilingheight < height)
456             height = other->ceilingheight;
457     }
458     return height;
459 }
460 
461 //==================================================================
462 //
463 //      FIND HIGHEST CEILING IN THE SURROUNDING SECTORS
464 //
465 //==================================================================
P_FindHighestCeilingSurrounding(sector_t * sec)466 fixed_t P_FindHighestCeilingSurrounding(sector_t * sec)
467 {
468     int i;
469     line_t *check;
470     sector_t *other;
471     fixed_t height = 0;
472 
473     for (i = 0; i < sec->linecount; i++)
474     {
475         check = sec->lines[i];
476         other = getNextSector(check, sec);
477         if (!other)
478             continue;
479         if (other->ceilingheight > height)
480             height = other->ceilingheight;
481     }
482     return height;
483 }
484 
485 //==================================================================
486 //
487 //      RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
488 //
489 //==================================================================
P_FindSectorFromLineTag(line_t * line,int start)490 int P_FindSectorFromLineTag(line_t * line, int start)
491 {
492     int i;
493 
494     for (i = start + 1; i < numsectors; i++)
495         if (sectors[i].tag == line->tag)
496             return i;
497     return -1;
498 }
499 
500 //==================================================================
501 //
502 //      Find minimum light from an adjacent sector
503 //
504 //==================================================================
P_FindMinSurroundingLight(sector_t * sector,int max)505 int P_FindMinSurroundingLight(sector_t * sector, int max)
506 {
507     int i;
508     int min;
509     line_t *line;
510     sector_t *check;
511 
512     min = max;
513     for (i = 0; i < sector->linecount; i++)
514     {
515         line = sector->lines[i];
516         check = getNextSector(line, sector);
517         if (!check)
518             continue;
519         if (check->lightlevel < min)
520             min = check->lightlevel;
521     }
522     return min;
523 }
524 
525 /*
526 ==============================================================================
527 
528 							EVENTS
529 
530 Events are operations triggered by using, crossing, or shooting special lines, or by timed thinkers
531 
532 ==============================================================================
533 */
534 
535 
536 
537 /*
538 ===============================================================================
539 =
540 = P_CrossSpecialLine - TRIGGER
541 =
542 = Called every time a thing origin is about to cross
543 = a line with a non 0 special
544 =
545 ===============================================================================
546 */
547 
P_CrossSpecialLine(int linenum,int side,mobj_t * thing)548 void P_CrossSpecialLine(int linenum, int side, mobj_t * thing)
549 {
550     line_t *line;
551 
552     line = &lines[linenum];
553     if (!thing->player)
554     {                           // Check if trigger allowed by non-player mobj
555         switch (line->special)
556         {
557             case 39:           // Trigger_TELEPORT
558             case 97:           // Retrigger_TELEPORT
559             case 4:            // Trigger_Raise_Door
560                 //case 10:      // PLAT DOWN-WAIT-UP-STAY TRIGGER
561                 //case 88:      // PLAT DOWN-WAIT-UP-STAY RETRIGGER
562                 break;
563             default:
564                 return;
565                 break;
566         }
567     }
568     switch (line->special)
569     {
570             //====================================================
571             // TRIGGERS
572             //====================================================
573         case 2:                // Open Door
574             EV_DoDoor(line, vld_open, VDOORSPEED);
575             line->special = 0;
576             break;
577         case 3:                // Close Door
578             EV_DoDoor(line, vld_close, VDOORSPEED);
579             line->special = 0;
580             break;
581         case 4:                // Raise Door
582             EV_DoDoor(line, vld_normal, VDOORSPEED);
583             line->special = 0;
584             break;
585         case 5:                // Raise Floor
586             EV_DoFloor(line, raiseFloor);
587             line->special = 0;
588             break;
589         case 6:                // Fast Ceiling Crush & Raise
590             EV_DoCeiling(line, fastCrushAndRaise);
591             line->special = 0;
592             break;
593         case 8:                // Trigger_Build_Stairs (8 pixel steps)
594             EV_BuildStairs(line, 8 * FRACUNIT);
595             line->special = 0;
596             break;
597         case 106:              // Trigger_Build_Stairs_16 (16 pixel steps)
598             EV_BuildStairs(line, 16 * FRACUNIT);
599             line->special = 0;
600             break;
601         case 10:               // PlatDownWaitUp
602             EV_DoPlat(line, downWaitUpStay, 0);
603             line->special = 0;
604             break;
605         case 12:               // Light Turn On - brightest near
606             EV_LightTurnOn(line, 0);
607             line->special = 0;
608             break;
609         case 13:               // Light Turn On 255
610             EV_LightTurnOn(line, 255);
611             line->special = 0;
612             break;
613         case 16:               // Close Door 30
614             EV_DoDoor(line, vld_close30ThenOpen, VDOORSPEED);
615             line->special = 0;
616             break;
617         case 17:               // Start Light Strobing
618             EV_StartLightStrobing(line);
619             line->special = 0;
620             break;
621         case 19:               // Lower Floor
622             EV_DoFloor(line, lowerFloor);
623             line->special = 0;
624             break;
625         case 22:               // Raise floor to nearest height and change texture
626             EV_DoPlat(line, raiseToNearestAndChange, 0);
627             line->special = 0;
628             break;
629         case 25:               // Ceiling Crush and Raise
630             EV_DoCeiling(line, crushAndRaise);
631             line->special = 0;
632             break;
633         case 30:               // Raise floor to shortest texture height
634             // on either side of lines
635             EV_DoFloor(line, raiseToTexture);
636             line->special = 0;
637             break;
638         case 35:               // Lights Very Dark
639             EV_LightTurnOn(line, 35);
640             line->special = 0;
641             break;
642         case 36:               // Lower Floor (TURBO)
643             EV_DoFloor(line, turboLower);
644             line->special = 0;
645             break;
646         case 37:               // LowerAndChange
647             EV_DoFloor(line, lowerAndChange);
648             line->special = 0;
649             break;
650         case 38:               // Lower Floor To Lowest
651             EV_DoFloor(line, lowerFloorToLowest);
652             line->special = 0;
653             break;
654         case 39:               // TELEPORT!
655             EV_Teleport(line, side, thing);
656             line->special = 0;
657             break;
658         case 40:               // RaiseCeilingLowerFloor
659             EV_DoCeiling(line, raiseToHighest);
660             EV_DoFloor(line, lowerFloorToLowest);
661             line->special = 0;
662             break;
663         case 44:               // Ceiling Crush
664             EV_DoCeiling(line, lowerAndCrush);
665             line->special = 0;
666             break;
667         case 52:               // EXIT!
668             G_ExitLevel();
669             line->special = 0;
670             break;
671         case 53:               // Perpetual Platform Raise
672             EV_DoPlat(line, perpetualRaise, 0);
673             line->special = 0;
674             break;
675         case 54:               // Platform Stop
676             EV_StopPlat(line);
677             line->special = 0;
678             break;
679         case 56:               // Raise Floor Crush
680             EV_DoFloor(line, raiseFloorCrush);
681             line->special = 0;
682             break;
683         case 57:               // Ceiling Crush Stop
684             EV_CeilingCrushStop(line);
685             line->special = 0;
686             break;
687         case 58:               // Raise Floor 24
688             EV_DoFloor(line, raiseFloor24);
689             line->special = 0;
690             break;
691         case 59:               // Raise Floor 24 And Change
692             EV_DoFloor(line, raiseFloor24AndChange);
693             line->special = 0;
694             break;
695         case 104:              // Turn lights off in sector(tag)
696             EV_TurnTagLightsOff(line);
697             line->special = 0;
698             break;
699         case 105:              // Trigger_SecretExit
700             G_SecretExitLevel();
701             line->special = 0;
702             break;
703 
704             //====================================================
705             // RE-DOABLE TRIGGERS
706             //====================================================
707 
708         case 72:               // Ceiling Crush
709             EV_DoCeiling(line, lowerAndCrush);
710             break;
711         case 73:               // Ceiling Crush and Raise
712             EV_DoCeiling(line, crushAndRaise);
713             break;
714         case 74:               // Ceiling Crush Stop
715             EV_CeilingCrushStop(line);
716             break;
717         case 75:               // Close Door
718             EV_DoDoor(line, vld_close, VDOORSPEED);
719             break;
720         case 76:               // Close Door 30
721             EV_DoDoor(line, vld_close30ThenOpen, VDOORSPEED);
722             break;
723         case 77:               // Fast Ceiling Crush & Raise
724             EV_DoCeiling(line, fastCrushAndRaise);
725             break;
726         case 79:               // Lights Very Dark
727             EV_LightTurnOn(line, 35);
728             break;
729         case 80:               // Light Turn On - brightest near
730             EV_LightTurnOn(line, 0);
731             break;
732         case 81:               // Light Turn On 255
733             EV_LightTurnOn(line, 255);
734             break;
735         case 82:               // Lower Floor To Lowest
736             EV_DoFloor(line, lowerFloorToLowest);
737             break;
738         case 83:               // Lower Floor
739             EV_DoFloor(line, lowerFloor);
740             break;
741         case 84:               // LowerAndChange
742             EV_DoFloor(line, lowerAndChange);
743             break;
744         case 86:               // Open Door
745             EV_DoDoor(line, vld_open, VDOORSPEED);
746             break;
747         case 87:               // Perpetual Platform Raise
748             EV_DoPlat(line, perpetualRaise, 0);
749             break;
750         case 88:               // PlatDownWaitUp
751             EV_DoPlat(line, downWaitUpStay, 0);
752             break;
753         case 89:               // Platform Stop
754             EV_StopPlat(line);
755             break;
756         case 90:               // Raise Door
757             EV_DoDoor(line, vld_normal, VDOORSPEED);
758             break;
759         case 100:              // Retrigger_Raise_Door_Turbo
760             EV_DoDoor(line, vld_normal, VDOORSPEED * 3);
761             break;
762         case 91:               // Raise Floor
763             EV_DoFloor(line, raiseFloor);
764             break;
765         case 92:               // Raise Floor 24
766             EV_DoFloor(line, raiseFloor24);
767             break;
768         case 93:               // Raise Floor 24 And Change
769             EV_DoFloor(line, raiseFloor24AndChange);
770             break;
771         case 94:               // Raise Floor Crush
772             EV_DoFloor(line, raiseFloorCrush);
773             break;
774         case 95:               // Raise floor to nearest height and change texture
775             EV_DoPlat(line, raiseToNearestAndChange, 0);
776             break;
777         case 96:               // Raise floor to shortest texture height
778             // on either side of lines
779             EV_DoFloor(line, raiseToTexture);
780             break;
781         case 97:               // TELEPORT!
782             EV_Teleport(line, side, thing);
783             break;
784         case 98:               // Lower Floor (TURBO)
785             EV_DoFloor(line, turboLower);
786             break;
787     }
788 }
789 
790 //----------------------------------------------------------------------------
791 //
792 // PROC P_ShootSpecialLine
793 //
794 // Called when a thing shoots a special line.
795 //
796 //----------------------------------------------------------------------------
797 
P_ShootSpecialLine(mobj_t * thing,line_t * line)798 void P_ShootSpecialLine(mobj_t * thing, line_t * line)
799 {
800     if (!thing->player)
801     {                           // Check if trigger allowed by non-player mobj
802         switch (line->special)
803         {
804             case 46:           // Impact_OpenDoor
805                 break;
806             default:
807                 return;
808                 break;
809         }
810     }
811     switch (line->special)
812     {
813         case 24:               // Impact_RaiseFloor
814             EV_DoFloor(line, raiseFloor);
815             P_ChangeSwitchTexture(line, 0);
816             break;
817         case 46:               // Impact_OpenDoor
818             EV_DoDoor(line, vld_open, VDOORSPEED);
819             P_ChangeSwitchTexture(line, 1);
820             break;
821         case 47:               // Impact_RaiseFloorNear&Change
822             EV_DoPlat(line, raiseToNearestAndChange, 0);
823             P_ChangeSwitchTexture(line, 0);
824             break;
825     }
826 }
827 
828 //----------------------------------------------------------------------------
829 //
830 // PROC P_PlayerInSpecialSector
831 //
832 // Called every tic frame that the player origin is in a special sector.
833 //
834 //----------------------------------------------------------------------------
835 
P_PlayerInSpecialSector(player_t * player)836 void P_PlayerInSpecialSector(player_t * player)
837 {
838     sector_t *sector;
839     static int pushTab[5] = {
840         2048 * 5,
841         2048 * 10,
842         2048 * 25,
843         2048 * 30,
844         2048 * 35
845     };
846 
847     sector = player->mo->subsector->sector;
848     if (player->mo->z != sector->floorheight)
849     {                           // Player is not touching the floor
850         return;
851     }
852     switch (sector->special)
853     {
854         case 7:                // Damage_Sludge
855             if (!(leveltime & 31))
856             {
857                 P_DamageMobj(player->mo, NULL, NULL, 4);
858             }
859             break;
860         case 5:                // Damage_LavaWimpy
861             if (!(leveltime & 15))
862             {
863                 P_DamageMobj(player->mo, &LavaInflictor, NULL, 5);
864                 P_HitFloor(player->mo);
865             }
866             break;
867         case 16:               // Damage_LavaHefty
868             if (!(leveltime & 15))
869             {
870                 P_DamageMobj(player->mo, &LavaInflictor, NULL, 8);
871                 P_HitFloor(player->mo);
872             }
873             break;
874         case 4:                // Scroll_EastLavaDamage
875             P_Thrust(player, 0, 2048 * 28);
876             if (!(leveltime & 15))
877             {
878                 P_DamageMobj(player->mo, &LavaInflictor, NULL, 5);
879                 P_HitFloor(player->mo);
880             }
881             break;
882         case 9:                // SecretArea
883             player->secretcount++;
884             sector->special = 0;
885             break;
886         case 11:               // Exit_SuperDamage (DOOM E1M8 finale)
887             /*
888                player->cheats &= ~CF_GODMODE;
889                if(!(leveltime&0x1f))
890                {
891                P_DamageMobj(player->mo, NULL, NULL, 20);
892                }
893                if(player->health <= 10)
894                {
895                G_ExitLevel();
896                }
897              */
898             break;
899 
900         case 25:
901         case 26:
902         case 27:
903         case 28:
904         case 29:               // Scroll_North
905             P_Thrust(player, ANG90, pushTab[sector->special - 25]);
906             break;
907         case 20:
908         case 21:
909         case 22:
910         case 23:
911         case 24:               // Scroll_East
912             P_Thrust(player, 0, pushTab[sector->special - 20]);
913             break;
914         case 30:
915         case 31:
916         case 32:
917         case 33:
918         case 34:               // Scroll_South
919             P_Thrust(player, ANG270, pushTab[sector->special - 30]);
920             break;
921         case 35:
922         case 36:
923         case 37:
924         case 38:
925         case 39:               // Scroll_West
926             P_Thrust(player, ANG180, pushTab[sector->special - 35]);
927             break;
928 
929         case 40:
930         case 41:
931         case 42:
932         case 43:
933         case 44:
934         case 45:
935         case 46:
936         case 47:
937         case 48:
938         case 49:
939         case 50:
940         case 51:
941             // Wind specials are handled in (P_mobj):P_XYMovement
942             break;
943 
944         case 15:               // Friction_Low
945             // Only used in (P_mobj):P_XYMovement and (P_user):P_Thrust
946             break;
947 
948         default:
949             I_Error("P_PlayerInSpecialSector: "
950                     "unknown special %i", sector->special);
951     }
952 }
953 
954 //----------------------------------------------------------------------------
955 //
956 // PROC P_UpdateSpecials
957 //
958 // Animate planes, scroll walls, etc.
959 //
960 //----------------------------------------------------------------------------
961 
P_UpdateSpecials(void)962 void P_UpdateSpecials(void)
963 {
964     int i;
965     int pic;
966     anim_t *anim;
967     line_t *line;
968 
969     // Animate flats and textures
970     for (anim = anims; anim < lastanim; anim++)
971     {
972         for (i = anim->basepic; i < anim->basepic + anim->numpics; i++)
973         {
974             pic =
975                 anim->basepic +
976                 ((leveltime / anim->speed + i) % anim->numpics);
977             if (anim->istexture)
978             {
979                 texturetranslation[i] = pic;
980             }
981             else
982             {
983                 flattranslation[i] = pic;
984             }
985         }
986     }
987     // Update scrolling texture offsets
988     for (i = 0; i < numlinespecials; i++)
989     {
990         line = linespeciallist[i];
991         switch (line->special)
992         {
993             case 48:           // Effect_Scroll_Left
994                 sides[line->sidenum[0]].textureoffset += FRACUNIT;
995                 break;
996             case 99:           // Effect_Scroll_Right
997                 sides[line->sidenum[0]].textureoffset -= FRACUNIT;
998                 break;
999         }
1000     }
1001     // Handle buttons
1002     for (i = 0; i < MAXBUTTONS; i++)
1003     {
1004         if (buttonlist[i].btimer)
1005         {
1006             buttonlist[i].btimer--;
1007             if (!buttonlist[i].btimer)
1008             {
1009                 switch (buttonlist[i].where)
1010                 {
1011                     case top:
1012                         sides[buttonlist[i].line->sidenum[0]].toptexture =
1013                             buttonlist[i].btexture;
1014                         break;
1015                     case middle:
1016                         sides[buttonlist[i].line->sidenum[0]].midtexture =
1017                             buttonlist[i].btexture;
1018                         break;
1019                     case bottom:
1020                         sides[buttonlist[i].line->sidenum[0]].bottomtexture =
1021                             buttonlist[i].btexture;
1022                         break;
1023                 }
1024                 S_StartSound(buttonlist[i].soundorg, sfx_switch);
1025                 memset(&buttonlist[i], 0, sizeof(button_t));
1026             }
1027         }
1028     }
1029 }
1030 
1031 //============================================================
1032 //
1033 //      Special Stuff that can't be categorized
1034 //
1035 //============================================================
EV_DoDonut(line_t * line)1036 int EV_DoDonut(line_t * line)
1037 {
1038     sector_t *s1;
1039     sector_t *s2;
1040     sector_t *s3;
1041     int secnum;
1042     int rtn;
1043     int i;
1044     floormove_t *floor;
1045 
1046     secnum = -1;
1047     rtn = 0;
1048     while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0)
1049     {
1050         s1 = &sectors[secnum];
1051 
1052         //      ALREADY MOVING?  IF SO, KEEP GOING...
1053         if (s1->specialdata)
1054             continue;
1055 
1056         rtn = 1;
1057         s2 = getNextSector(s1->lines[0], s1);
1058         for (i = 0; i < s2->linecount; i++)
1059         {
1060             // Note: This was originally part of the following test:
1061             //   (!s2->lines[i]->flags & ML_TWOSIDED) ||
1062             // Due to the apparent mistaken formatting, this can never be
1063             // true.
1064 
1065             if (s2->lines[i]->backsector == s1)
1066                 continue;
1067             s3 = s2->lines[i]->backsector;
1068 
1069             //
1070             //      Spawn rising slime
1071             //
1072             floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0);
1073             P_AddThinker(&floor->thinker);
1074             s2->specialdata = floor;
1075             floor->thinker.function = T_MoveFloor;
1076             floor->type = donutRaise;
1077             floor->crush = false;
1078             floor->direction = 1;
1079             floor->sector = s2;
1080             floor->speed = FLOORSPEED / 2;
1081             floor->texture = s3->floorpic;
1082             floor->newspecial = 0;
1083             floor->floordestheight = s3->floorheight;
1084 
1085             //
1086             //      Spawn lowering donut-hole
1087             //
1088             floor = Z_Malloc(sizeof(*floor), PU_LEVSPEC, 0);
1089             P_AddThinker(&floor->thinker);
1090             s1->specialdata = floor;
1091             floor->thinker.function = T_MoveFloor;
1092             floor->type = lowerFloor;
1093             floor->crush = false;
1094             floor->direction = -1;
1095             floor->sector = s1;
1096             floor->speed = FLOORSPEED / 2;
1097             floor->floordestheight = s3->floorheight;
1098             break;
1099         }
1100     }
1101     return rtn;
1102 }
1103 
1104 /*
1105 ==============================================================================
1106 
1107 							SPECIAL SPAWNING
1108 
1109 ==============================================================================
1110 */
1111 /*
1112 ================================================================================
1113 = P_SpawnSpecials
1114 =
1115 = After the map has been loaded, scan for specials that
1116 = spawn thinkers
1117 =
1118 ===============================================================================
1119 */
1120 
1121 short numlinespecials;
1122 line_t *linespeciallist[MAXLINEANIMS];
1123 
P_SpawnSpecials(void)1124 void P_SpawnSpecials(void)
1125 {
1126     sector_t *sector;
1127     int i;
1128 
1129     //
1130     //      Init special SECTORs
1131     //
1132     sector = sectors;
1133     for (i = 0; i < numsectors; i++, sector++)
1134     {
1135         if (!sector->special)
1136             continue;
1137         switch (sector->special)
1138         {
1139             case 1:            // FLICKERING LIGHTS
1140                 P_SpawnLightFlash(sector);
1141                 break;
1142             case 2:            // STROBE FAST
1143                 P_SpawnStrobeFlash(sector, FASTDARK, 0);
1144                 break;
1145             case 3:            // STROBE SLOW
1146                 P_SpawnStrobeFlash(sector, SLOWDARK, 0);
1147                 break;
1148             case 4:            // STROBE FAST/DEATH SLIME
1149                 P_SpawnStrobeFlash(sector, FASTDARK, 0);
1150                 sector->special = 4;
1151                 break;
1152             case 8:            // GLOWING LIGHT
1153                 P_SpawnGlowingLight(sector);
1154                 break;
1155             case 9:            // SECRET SECTOR
1156                 totalsecret++;
1157                 break;
1158             case 10:           // DOOR CLOSE IN 30 SECONDS
1159                 P_SpawnDoorCloseIn30(sector);
1160                 break;
1161             case 12:           // SYNC STROBE SLOW
1162                 P_SpawnStrobeFlash(sector, SLOWDARK, 1);
1163                 break;
1164             case 13:           // SYNC STROBE FAST
1165                 P_SpawnStrobeFlash(sector, FASTDARK, 1);
1166                 break;
1167             case 14:           // DOOR RAISE IN 5 MINUTES
1168                 P_SpawnDoorRaiseIn5Mins(sector, i);
1169                 break;
1170         }
1171     }
1172 
1173 
1174     //
1175     //      Init line EFFECTs
1176     //
1177     numlinespecials = 0;
1178     for (i = 0; i < numlines; i++)
1179         switch (lines[i].special)
1180         {
1181             case 48:           // Effect_Scroll_Left
1182             case 99:           // Effect_Scroll_Right
1183                 linespeciallist[numlinespecials] = &lines[i];
1184                 numlinespecials++;
1185                 break;
1186         }
1187 
1188     //
1189     //      Init other misc stuff
1190     //
1191     for (i = 0; i < MAXCEILINGS; i++)
1192         activeceilings[i] = NULL;
1193     for (i = 0; i < MAXPLATS; i++)
1194         activeplats[i] = NULL;
1195     for (i = 0; i < MAXBUTTONS; i++)
1196         memset(&buttonlist[i], 0, sizeof(button_t));
1197 }
1198 
1199 //----------------------------------------------------------------------------
1200 //
1201 // PROC P_InitAmbientSound
1202 //
1203 //----------------------------------------------------------------------------
1204 
P_InitAmbientSound(void)1205 void P_InitAmbientSound(void)
1206 {
1207     AmbSfxCount = 0;
1208     AmbSfxVolume = 0;
1209     AmbSfxTics = 10 * TICRATE;
1210     AmbSfxPtr = AmbSndSeqInit;
1211 }
1212 
1213 //----------------------------------------------------------------------------
1214 //
1215 // PROC P_AddAmbientSfx
1216 //
1217 // Called by (P_mobj):P_SpawnMapThing during (P_setup):P_SetupLevel.
1218 //
1219 //----------------------------------------------------------------------------
1220 
P_AddAmbientSfx(int sequence)1221 void P_AddAmbientSfx(int sequence)
1222 {
1223     if (AmbSfxCount == MAX_AMBIENT_SFX)
1224     {
1225         I_Error("Too many ambient sound sequences");
1226     }
1227     LevelAmbientSfx[AmbSfxCount++] = AmbientSfx[sequence];
1228 }
1229 
1230 //----------------------------------------------------------------------------
1231 //
1232 // PROC P_AmbientSound
1233 //
1234 // Called every tic by (P_tick):P_Ticker.
1235 //
1236 //----------------------------------------------------------------------------
1237 
P_AmbientSound(void)1238 void P_AmbientSound(void)
1239 {
1240     afxcmd_t cmd;
1241     int sound;
1242     boolean done;
1243 
1244     if (!AmbSfxCount)
1245     {                           // No ambient sound sequences on current level
1246         return;
1247     }
1248     if (--AmbSfxTics)
1249     {
1250         return;
1251     }
1252     done = false;
1253     do
1254     {
1255         cmd = *AmbSfxPtr++;
1256         switch (cmd)
1257         {
1258             case afxcmd_play:
1259                 AmbSfxVolume = P_Random() >> 2;
1260                 S_StartSoundAtVolume(NULL, *AmbSfxPtr++, AmbSfxVolume);
1261                 break;
1262             case afxcmd_playabsvol:
1263                 sound = *AmbSfxPtr++;
1264                 AmbSfxVolume = *AmbSfxPtr++;
1265                 S_StartSoundAtVolume(NULL, sound, AmbSfxVolume);
1266                 break;
1267             case afxcmd_playrelvol:
1268                 sound = *AmbSfxPtr++;
1269                 AmbSfxVolume += *AmbSfxPtr++;
1270                 if (AmbSfxVolume < 0)
1271                 {
1272                     AmbSfxVolume = 0;
1273                 }
1274                 else if (AmbSfxVolume > 127)
1275                 {
1276                     AmbSfxVolume = 127;
1277                 }
1278                 S_StartSoundAtVolume(NULL, sound, AmbSfxVolume);
1279                 break;
1280             case afxcmd_delay:
1281                 AmbSfxTics = *AmbSfxPtr++;
1282                 done = true;
1283                 break;
1284             case afxcmd_delayrand:
1285                 AmbSfxTics = P_Random() & (*AmbSfxPtr++);
1286                 done = true;
1287                 break;
1288             case afxcmd_end:
1289                 AmbSfxTics = 6 * TICRATE + P_Random();
1290                 AmbSfxPtr = LevelAmbientSfx[P_Random() % AmbSfxCount];
1291                 done = true;
1292                 break;
1293             default:
1294                 I_Error("P_AmbientSound: Unknown afxcmd %d", cmd);
1295                 break;
1296         }
1297     }
1298     while (done == false);
1299 }
1300