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