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 = §ors[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