# Correct the needed linklibs in curl-config also.
[AROS-Contrib.git] / Games / Doom / p_spec.c
blob9b3f234fcefaf761e4c5275ae8fdf925b83b56a5
1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id$
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 //
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15 // for more details.
17 // $Log$
18 // Revision 1.1 2000/02/29 18:21:05 stegerg
19 // Doom port based on ADoomPPC. Read README.AROS!
22 // DESCRIPTION:
23 // Implements special effects:
24 // Texture animation, height or lighting changes
25 // according to adjacent sectors, respective
26 // utility functions, etc.
27 // Line Tag handling. Line and Sector triggers.
29 //-----------------------------------------------------------------------------
31 static const char
32 rcsid[] = "$Id$";
34 #include <stdlib.h>
36 #include "doomdef.h"
37 #include "doomstat.h"
39 #include "i_system.h"
40 #include "z_zone.h"
41 #include "m_argv.h"
42 #include "m_random.h"
43 #include "w_wad.h"
45 #include "r_local.h"
46 #include "p_local.h"
48 #include "g_game.h"
50 #include "s_sound.h"
52 // State.
53 #include "r_state.h"
55 // Data.
56 #include "sounds.h"
60 // Animating textures and planes
61 // There is another anim_t used in wi_stuff, unrelated.
63 typedef struct
65 boolean istexture;
66 int picnum;
67 int basepic;
68 int numpics;
69 int speed;
71 } anim_t;
74 // source animation definition
76 typedef struct
78 boolean istexture; // if false, it is a flat
79 char endname[9];
80 char startname[9];
81 int speed;
82 } animdef_t;
86 #define MAXANIMS 32
88 extern anim_t anims[MAXANIMS];
89 extern anim_t* lastanim;
92 // P_InitPicAnims
95 // Floor/ceiling animation sequences,
96 // defined by first and last frame,
97 // i.e. the flat (64x64 tile) name to
98 // be used.
99 // The full animation sequence is given
100 // using all the flats between the start
101 // and end entry, in the order found in
102 // the WAD file.
104 animdef_t animdefs[] =
106 {false, "NUKAGE3", "NUKAGE1", 8},
107 {false, "FWATER4", "FWATER1", 8},
108 {false, "SWATER4", "SWATER1", 8},
109 {false, "LAVA4", "LAVA1", 8},
110 {false, "BLOOD3", "BLOOD1", 8},
112 // DOOM II flat animations.
113 {false, "RROCK08", "RROCK05", 8},
114 {false, "SLIME04", "SLIME01", 8},
115 {false, "SLIME08", "SLIME05", 8},
116 {false, "SLIME12", "SLIME09", 8},
118 {true, "BLODGR4", "BLODGR1", 8},
119 {true, "SLADRIP3", "SLADRIP1", 8},
121 {true, "BLODRIP4", "BLODRIP1", 8},
122 {true, "FIREWALL", "FIREWALA", 8},
123 {true, "GSTFONT3", "GSTFONT1", 8},
124 {true, "FIRELAVA", "FIRELAV3", 8},
125 {true, "FIREMAG3", "FIREMAG1", 8},
126 {true, "FIREBLU2", "FIREBLU1", 8},
127 {true, "ROCKRED3", "ROCKRED1", 8},
129 {true, "BFALL4", "BFALL1", 8},
130 {true, "SFALL4", "SFALL1", 8},
131 {true, "WFALL4", "WFALL1", 8},
132 {true, "DBRAIN4", "DBRAIN1", 8},
134 {-1}
137 anim_t anims[MAXANIMS];
138 anim_t* lastanim;
142 // Animating line specials
144 #define MAXLINEANIMS 64
146 extern short numlinespecials;
147 extern line_t* linespeciallist[MAXLINEANIMS];
151 void P_InitPicAnims (void)
153 int i;
156 // Init animation
157 lastanim = anims;
158 for (i=0 ; animdefs[i].istexture != -1 ; i++)
160 if (animdefs[i].istexture)
162 // different episode ?
163 if (R_CheckTextureNumForName(animdefs[i].startname) == -1)
164 continue;
166 lastanim->picnum = R_TextureNumForName (animdefs[i].endname);
167 lastanim->basepic = R_TextureNumForName (animdefs[i].startname);
169 else
171 if (W_CheckNumForName(animdefs[i].startname) == -1)
172 continue;
174 lastanim->picnum = R_FlatNumForName (animdefs[i].endname);
175 lastanim->basepic = R_FlatNumForName (animdefs[i].startname);
178 lastanim->istexture = animdefs[i].istexture;
179 lastanim->numpics = lastanim->picnum - lastanim->basepic + 1;
181 if (lastanim->numpics < 2)
182 I_Error ("P_InitPicAnims: bad cycle from %s to %s",
183 animdefs[i].startname,
184 animdefs[i].endname);
186 lastanim->speed = animdefs[i].speed;
187 lastanim++;
195 // UTILITIES
201 // getSide()
202 // Will return a side_t*
203 // given the number of the current sector,
204 // the line number, and the side (0/1) that you want.
206 side_t*
207 getSide
208 ( int currentSector,
209 int line,
210 int side )
212 return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ];
217 // getSector()
218 // Will return a sector_t*
219 // given the number of the current sector,
220 // the line number and the side (0/1) that you want.
222 sector_t*
223 getSector
224 ( int currentSector,
225 int line,
226 int side )
228 return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector;
233 // twoSided()
234 // Given the sector number and the line number,
235 // it will tell you whether the line is two-sided or not.
238 twoSided
239 ( int sector,
240 int line )
242 return (sectors[sector].lines[line])->flags & ML_TWOSIDED;
249 // getNextSector()
250 // Return sector_t * of sector next to current.
251 // NULL if not two-sided line
253 sector_t*
254 getNextSector
255 ( line_t* line,
256 sector_t* sec )
258 if (!(line->flags & ML_TWOSIDED))
259 return NULL;
261 if (line->frontsector == sec)
262 return line->backsector;
264 return line->frontsector;
270 // P_FindLowestFloorSurrounding()
271 // FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS
273 fixed_t P_FindLowestFloorSurrounding(sector_t* sec)
275 int i;
276 line_t* check;
277 sector_t* other;
278 fixed_t floor = sec->floorheight;
280 for (i=0 ;i < sec->linecount ; i++)
282 check = sec->lines[i];
283 other = getNextSector(check,sec);
285 if (!other)
286 continue;
288 if (other->floorheight < floor)
289 floor = other->floorheight;
291 return floor;
297 // P_FindHighestFloorSurrounding()
298 // FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS
300 fixed_t P_FindHighestFloorSurrounding(sector_t *sec)
302 int i;
303 line_t* check;
304 sector_t* other;
305 fixed_t floor = -500*FRACUNIT;
307 for (i=0 ;i < sec->linecount ; i++)
309 check = sec->lines[i];
310 other = getNextSector(check,sec);
312 if (!other)
313 continue;
315 if (other->floorheight > floor)
316 floor = other->floorheight;
318 return floor;
324 // P_FindNextHighestFloor
325 // FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS
326 // Note: this should be doable w/o a fixed array.
328 // 20 adjoining sectors max!
329 #define MAX_ADJOINING_SECTORS 20
331 fixed_t
332 P_FindNextHighestFloor
333 ( sector_t* sec,
334 int currentheight )
336 int i;
337 int h;
338 int min;
339 line_t* check;
340 sector_t* other;
341 fixed_t height = currentheight;
344 fixed_t heightlist[MAX_ADJOINING_SECTORS];
346 for (i=0, h=0 ;i < sec->linecount ; i++)
348 check = sec->lines[i];
349 other = getNextSector(check,sec);
351 if (!other)
352 continue;
354 if (other->floorheight > height)
355 heightlist[h++] = other->floorheight;
357 // Check for overflow. Exit.
358 if ( h >= MAX_ADJOINING_SECTORS )
360 fprintf( stderr,
361 "Sector with more than 20 adjoining sectors\n" );
362 break;
366 // Find lowest height in list
367 if (!h)
368 return currentheight;
370 min = heightlist[0];
372 // Range checking?
373 for (i = 1;i < h;i++)
374 if (heightlist[i] < min)
375 min = heightlist[i];
377 return min;
382 // FIND LOWEST CEILING IN THE SURROUNDING SECTORS
384 fixed_t
385 P_FindLowestCeilingSurrounding(sector_t* sec)
387 int i;
388 line_t* check;
389 sector_t* other;
390 fixed_t height = MAXINT;
392 for (i=0 ;i < sec->linecount ; i++)
394 check = sec->lines[i];
395 other = getNextSector(check,sec);
397 if (!other)
398 continue;
400 if (other->ceilingheight < height)
401 height = other->ceilingheight;
403 return height;
408 // FIND HIGHEST CEILING IN THE SURROUNDING SECTORS
410 fixed_t P_FindHighestCeilingSurrounding(sector_t* sec)
412 int i;
413 line_t* check;
414 sector_t* other;
415 fixed_t height = 0;
417 for (i=0 ;i < sec->linecount ; i++)
419 check = sec->lines[i];
420 other = getNextSector(check,sec);
422 if (!other)
423 continue;
425 if (other->ceilingheight > height)
426 height = other->ceilingheight;
428 return height;
434 // RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
437 P_FindSectorFromLineTag
438 ( line_t* line,
439 int start )
441 int i;
443 for (i=start+1;i<numsectors;i++)
444 if (sectors[i].tag == line->tag)
445 return i;
447 return -1;
454 // Find minimum light from an adjacent sector
457 P_FindMinSurroundingLight
458 ( sector_t* sector,
459 int max )
461 int i;
462 int min;
463 line_t* line;
464 sector_t* check;
466 min = max;
467 for (i=0 ; i < sector->linecount ; i++)
469 line = sector->lines[i];
470 check = getNextSector(line,sector);
472 if (!check)
473 continue;
475 if (check->lightlevel < min)
476 min = check->lightlevel;
478 return min;
484 // EVENTS
485 // Events are operations triggered by using, crossing,
486 // or shooting special lines, or by timed thinkers.
490 // P_CrossSpecialLine - TRIGGER
491 // Called every time a thing origin is about
492 // to cross a line with a non 0 special.
494 void
495 P_CrossSpecialLine
496 ( int linenum,
497 int side,
498 mobj_t* thing )
500 line_t* line;
501 int ok;
503 line = &lines[linenum];
505 // Triggers that other things can activate
506 if (!thing->player)
508 // Things that should NOT trigger specials...
509 switch(thing->type)
511 case MT_ROCKET:
512 case MT_PLASMA:
513 case MT_BFG:
514 case MT_TROOPSHOT:
515 case MT_HEADSHOT:
516 case MT_BRUISERSHOT:
517 return;
518 break;
520 default: break;
523 ok = 0;
524 switch(line->special)
526 case 39: // TELEPORT TRIGGER
527 case 97: // TELEPORT RETRIGGER
528 case 125: // TELEPORT MONSTERONLY TRIGGER
529 case 126: // TELEPORT MONSTERONLY RETRIGGER
530 case 4: // RAISE DOOR
531 case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER
532 case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER
533 ok = 1;
534 break;
536 if (!ok)
537 return;
541 // Note: could use some const's here.
542 switch (line->special)
544 // TRIGGERS.
545 // All from here to RETRIGGERS.
546 case 2:
547 // Open Door
548 EV_DoDoor(line,open);
549 line->special = 0;
550 break;
552 case 3:
553 // Close Door
554 EV_DoDoor(line,close);
555 line->special = 0;
556 break;
558 case 4:
559 // Raise Door
560 EV_DoDoor(line,normal);
561 line->special = 0;
562 break;
564 case 5:
565 // Raise Floor
566 EV_DoFloor(line,raiseFloor);
567 line->special = 0;
568 break;
570 case 6:
571 // Fast Ceiling Crush & Raise
572 EV_DoCeiling(line,fastCrushAndRaise);
573 line->special = 0;
574 break;
576 case 8:
577 // Build Stairs
578 EV_BuildStairs(line,build8);
579 line->special = 0;
580 break;
582 case 10:
583 // PlatDownWaitUp
584 EV_DoPlat(line,downWaitUpStay,0);
585 line->special = 0;
586 break;
588 case 12:
589 // Light Turn On - brightest near
590 EV_LightTurnOn(line,0);
591 line->special = 0;
592 break;
594 case 13:
595 // Light Turn On 255
596 EV_LightTurnOn(line,255);
597 line->special = 0;
598 break;
600 case 16:
601 // Close Door 30
602 EV_DoDoor(line,close30ThenOpen);
603 line->special = 0;
604 break;
606 case 17:
607 // Start Light Strobing
608 EV_StartLightStrobing(line);
609 line->special = 0;
610 break;
612 case 19:
613 // Lower Floor
614 EV_DoFloor(line,lowerFloor);
615 line->special = 0;
616 break;
618 case 22:
619 // Raise floor to nearest height and change texture
620 EV_DoPlat(line,raiseToNearestAndChange,0);
621 line->special = 0;
622 break;
624 case 25:
625 // Ceiling Crush and Raise
626 EV_DoCeiling(line,crushAndRaise);
627 line->special = 0;
628 break;
630 case 30:
631 // Raise floor to shortest texture height
632 // on either side of lines.
633 EV_DoFloor(line,raiseToTexture);
634 line->special = 0;
635 break;
637 case 35:
638 // Lights Very Dark
639 EV_LightTurnOn(line,35);
640 line->special = 0;
641 break;
643 case 36:
644 // Lower Floor (TURBO)
645 EV_DoFloor(line,turboLower);
646 line->special = 0;
647 break;
649 case 37:
650 // LowerAndChange
651 EV_DoFloor(line,lowerAndChange);
652 line->special = 0;
653 break;
655 case 38:
656 // Lower Floor To Lowest
657 EV_DoFloor( line, lowerFloorToLowest );
658 line->special = 0;
659 break;
661 case 39:
662 // TELEPORT!
663 EV_Teleport( line, side, thing );
664 line->special = 0;
665 break;
667 case 40:
668 // RaiseCeilingLowerFloor
669 EV_DoCeiling( line, raiseToHighest );
670 EV_DoFloor( line, lowerFloorToLowest );
671 line->special = 0;
672 break;
674 case 44:
675 // Ceiling Crush
676 EV_DoCeiling( line, lowerAndCrush );
677 line->special = 0;
678 break;
680 case 52:
681 // EXIT!
682 G_ExitLevel ();
683 break;
685 case 53:
686 // Perpetual Platform Raise
687 EV_DoPlat(line,perpetualRaise,0);
688 line->special = 0;
689 break;
691 case 54:
692 // Platform Stop
693 EV_StopPlat(line);
694 line->special = 0;
695 break;
697 case 56:
698 // Raise Floor Crush
699 EV_DoFloor(line,raiseFloorCrush);
700 line->special = 0;
701 break;
703 case 57:
704 // Ceiling Crush Stop
705 EV_CeilingCrushStop(line);
706 line->special = 0;
707 break;
709 case 58:
710 // Raise Floor 24
711 EV_DoFloor(line,raiseFloor24);
712 line->special = 0;
713 break;
715 case 59:
716 // Raise Floor 24 And Change
717 EV_DoFloor(line,raiseFloor24AndChange);
718 line->special = 0;
719 break;
721 case 104:
722 // Turn lights off in sector(tag)
723 EV_TurnTagLightsOff(line);
724 line->special = 0;
725 break;
727 case 108:
728 // Blazing Door Raise (faster than TURBO!)
729 EV_DoDoor (line,blazeRaise);
730 line->special = 0;
731 break;
733 case 109:
734 // Blazing Door Open (faster than TURBO!)
735 EV_DoDoor (line,blazeOpen);
736 line->special = 0;
737 break;
739 case 100:
740 // Build Stairs Turbo 16
741 EV_BuildStairs(line,turbo16);
742 line->special = 0;
743 break;
745 case 110:
746 // Blazing Door Close (faster than TURBO!)
747 EV_DoDoor (line,blazeClose);
748 line->special = 0;
749 break;
751 case 119:
752 // Raise floor to nearest surr. floor
753 EV_DoFloor(line,raiseFloorToNearest);
754 line->special = 0;
755 break;
757 case 121:
758 // Blazing PlatDownWaitUpStay
759 EV_DoPlat(line,blazeDWUS,0);
760 line->special = 0;
761 break;
763 case 124:
764 // Secret EXIT
765 G_SecretExitLevel ();
766 break;
768 case 125:
769 // TELEPORT MonsterONLY
770 if (!thing->player)
772 EV_Teleport( line, side, thing );
773 line->special = 0;
775 break;
777 case 130:
778 // Raise Floor Turbo
779 EV_DoFloor(line,raiseFloorTurbo);
780 line->special = 0;
781 break;
783 case 141:
784 // Silent Ceiling Crush & Raise
785 EV_DoCeiling(line,silentCrushAndRaise);
786 line->special = 0;
787 break;
789 // RETRIGGERS. All from here till end.
790 case 72:
791 // Ceiling Crush
792 EV_DoCeiling( line, lowerAndCrush );
793 break;
795 case 73:
796 // Ceiling Crush and Raise
797 EV_DoCeiling(line,crushAndRaise);
798 break;
800 case 74:
801 // Ceiling Crush Stop
802 EV_CeilingCrushStop(line);
803 break;
805 case 75:
806 // Close Door
807 EV_DoDoor(line,close);
808 break;
810 case 76:
811 // Close Door 30
812 EV_DoDoor(line,close30ThenOpen);
813 break;
815 case 77:
816 // Fast Ceiling Crush & Raise
817 EV_DoCeiling(line,fastCrushAndRaise);
818 break;
820 case 79:
821 // Lights Very Dark
822 EV_LightTurnOn(line,35);
823 break;
825 case 80:
826 // Light Turn On - brightest near
827 EV_LightTurnOn(line,0);
828 break;
830 case 81:
831 // Light Turn On 255
832 EV_LightTurnOn(line,255);
833 break;
835 case 82:
836 // Lower Floor To Lowest
837 EV_DoFloor( line, lowerFloorToLowest );
838 break;
840 case 83:
841 // Lower Floor
842 EV_DoFloor(line,lowerFloor);
843 break;
845 case 84:
846 // LowerAndChange
847 EV_DoFloor(line,lowerAndChange);
848 break;
850 case 86:
851 // Open Door
852 EV_DoDoor(line,open);
853 break;
855 case 87:
856 // Perpetual Platform Raise
857 EV_DoPlat(line,perpetualRaise,0);
858 break;
860 case 88:
861 // PlatDownWaitUp
862 EV_DoPlat(line,downWaitUpStay,0);
863 break;
865 case 89:
866 // Platform Stop
867 EV_StopPlat(line);
868 break;
870 case 90:
871 // Raise Door
872 EV_DoDoor(line,normal);
873 break;
875 case 91:
876 // Raise Floor
877 EV_DoFloor(line,raiseFloor);
878 break;
880 case 92:
881 // Raise Floor 24
882 EV_DoFloor(line,raiseFloor24);
883 break;
885 case 93:
886 // Raise Floor 24 And Change
887 EV_DoFloor(line,raiseFloor24AndChange);
888 break;
890 case 94:
891 // Raise Floor Crush
892 EV_DoFloor(line,raiseFloorCrush);
893 break;
895 case 95:
896 // Raise floor to nearest height
897 // and change texture.
898 EV_DoPlat(line,raiseToNearestAndChange,0);
899 break;
901 case 96:
902 // Raise floor to shortest texture height
903 // on either side of lines.
904 EV_DoFloor(line,raiseToTexture);
905 break;
907 case 97:
908 // TELEPORT!
909 EV_Teleport( line, side, thing );
910 break;
912 case 98:
913 // Lower Floor (TURBO)
914 EV_DoFloor(line,turboLower);
915 break;
917 case 105:
918 // Blazing Door Raise (faster than TURBO!)
919 EV_DoDoor (line,blazeRaise);
920 break;
922 case 106:
923 // Blazing Door Open (faster than TURBO!)
924 EV_DoDoor (line,blazeOpen);
925 break;
927 case 107:
928 // Blazing Door Close (faster than TURBO!)
929 EV_DoDoor (line,blazeClose);
930 break;
932 case 120:
933 // Blazing PlatDownWaitUpStay.
934 EV_DoPlat(line,blazeDWUS,0);
935 break;
937 case 126:
938 // TELEPORT MonsterONLY.
939 if (!thing->player)
940 EV_Teleport( line, side, thing );
941 break;
943 case 128:
944 // Raise To Nearest Floor
945 EV_DoFloor(line,raiseFloorToNearest);
946 break;
948 case 129:
949 // Raise Floor Turbo
950 EV_DoFloor(line,raiseFloorTurbo);
951 break;
958 // P_ShootSpecialLine - IMPACT SPECIALS
959 // Called when a thing shoots a special line.
961 void
962 P_ShootSpecialLine
963 ( mobj_t* thing,
964 line_t* line )
966 int ok;
968 // Impacts that other things can activate.
969 if (!thing->player)
971 ok = 0;
972 switch(line->special)
974 case 46:
975 // OPEN DOOR IMPACT
976 ok = 1;
977 break;
979 if (!ok)
980 return;
983 switch(line->special)
985 case 24:
986 // RAISE FLOOR
987 EV_DoFloor(line,raiseFloor);
988 P_ChangeSwitchTexture(line,0);
989 break;
991 case 46:
992 // OPEN DOOR
993 EV_DoDoor(line,open);
994 P_ChangeSwitchTexture(line,1);
995 break;
997 case 47:
998 // RAISE FLOOR NEAR AND CHANGE
999 EV_DoPlat(line,raiseToNearestAndChange,0);
1000 P_ChangeSwitchTexture(line,0);
1001 break;
1008 // P_PlayerInSpecialSector
1009 // Called every tic frame
1010 // that the player origin is in a special sector
1012 void P_PlayerInSpecialSector (player_t* player)
1014 sector_t* sector;
1016 sector = player->mo->subsector->sector;
1018 // Falling, not all the way down yet?
1019 if (player->mo->z != sector->floorheight)
1020 return;
1022 // Has hitten ground.
1023 switch (sector->special)
1025 case 5:
1026 // HELLSLIME DAMAGE
1027 if (!player->powers[pw_ironfeet])
1028 if (!(leveltime&0x1f))
1029 P_DamageMobj (player->mo, NULL, NULL, 10);
1030 break;
1032 case 7:
1033 // NUKAGE DAMAGE
1034 if (!player->powers[pw_ironfeet])
1035 if (!(leveltime&0x1f))
1036 P_DamageMobj (player->mo, NULL, NULL, 5);
1037 break;
1039 case 16:
1040 // SUPER HELLSLIME DAMAGE
1041 case 4:
1042 // STROBE HURT
1043 if (!player->powers[pw_ironfeet]
1044 || (P_Random()<5) )
1046 if (!(leveltime&0x1f))
1047 P_DamageMobj (player->mo, NULL, NULL, 20);
1049 break;
1051 case 9:
1052 // SECRET SECTOR
1053 player->secretcount++;
1054 sector->special = 0;
1055 break;
1057 case 11:
1058 // EXIT SUPER DAMAGE! (for E1M8 finale)
1059 player->cheats &= ~CF_GODMODE;
1061 if (!(leveltime&0x1f))
1062 P_DamageMobj (player->mo, NULL, NULL, 20);
1064 if (player->health <= 10)
1065 G_ExitLevel();
1066 break;
1068 default:
1069 I_Error ("P_PlayerInSpecialSector: "
1070 "unknown special %i",
1071 sector->special);
1072 break;
1080 // P_UpdateSpecials
1081 // Animate planes, scroll walls, etc.
1083 boolean levelTimer;
1084 int levelTimeCount;
1086 void P_UpdateSpecials (void)
1088 anim_t* anim;
1089 int pic;
1090 int i;
1091 line_t* line;
1094 // LEVEL TIMER
1095 if (levelTimer == true)
1097 levelTimeCount--;
1098 if (!levelTimeCount)
1099 G_ExitLevel();
1102 // ANIMATE FLATS AND TEXTURES GLOBALLY
1103 for (anim = anims ; anim < lastanim ; anim++)
1105 for (i=anim->basepic ; i<anim->basepic+anim->numpics ; i++)
1107 pic = anim->basepic + ( (leveltime/anim->speed + i)%anim->numpics );
1108 if (anim->istexture)
1109 texturetranslation[i] = pic;
1110 else
1111 flattranslation[i] = pic;
1116 // ANIMATE LINE SPECIALS
1117 for (i = 0; i < numlinespecials; i++)
1119 line = linespeciallist[i];
1120 switch(line->special)
1122 case 48:
1123 // EFFECT FIRSTCOL SCROLL +
1124 sides[line->sidenum[0]].textureoffset += FRACUNIT;
1125 break;
1130 // DO BUTTONS
1131 for (i = 0; i < MAXBUTTONS; i++)
1132 if (buttonlist[i].btimer)
1134 buttonlist[i].btimer--;
1135 if (!buttonlist[i].btimer)
1137 switch(buttonlist[i].where)
1139 case top:
1140 sides[buttonlist[i].line->sidenum[0]].toptexture =
1141 buttonlist[i].btexture;
1142 break;
1144 case middle:
1145 sides[buttonlist[i].line->sidenum[0]].midtexture =
1146 buttonlist[i].btexture;
1147 break;
1149 case bottom:
1150 sides[buttonlist[i].line->sidenum[0]].bottomtexture =
1151 buttonlist[i].btexture;
1152 break;
1154 S_StartSound((mobj_t *)&buttonlist[i].soundorg,sfx_swtchn);
1155 memset(&buttonlist[i],0,sizeof(button_t));
1164 // Special Stuff that can not be categorized
1166 int EV_DoDonut(line_t* line)
1168 sector_t* s1;
1169 sector_t* s2;
1170 sector_t* s3;
1171 int secnum;
1172 int rtn;
1173 int i;
1174 floormove_t* floor;
1176 secnum = -1;
1177 rtn = 0;
1178 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
1180 s1 = &sectors[secnum];
1182 // ALREADY MOVING? IF SO, KEEP GOING...
1183 if (s1->specialdata)
1184 continue;
1186 rtn = 1;
1187 s2 = getNextSector(s1->lines[0],s1);
1188 for (i = 0;i < s2->linecount;i++)
1190 if ((!(s2->lines[i]->flags & ML_TWOSIDED)) ||
1191 (s2->lines[i]->backsector == s1))
1192 continue;
1193 s3 = s2->lines[i]->backsector;
1195 // Spawn rising slime
1196 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
1197 P_AddThinker (&floor->thinker);
1198 s2->specialdata = floor;
1199 floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
1200 floor->type = donutRaise;
1201 floor->crush = false;
1202 floor->direction = 1;
1203 floor->sector = s2;
1204 floor->speed = FLOORSPEED / 2;
1205 floor->texture = s3->floorpic;
1206 floor->newspecial = 0;
1207 floor->floordestheight = s3->floorheight;
1209 // Spawn lowering donut-hole
1210 floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
1211 P_AddThinker (&floor->thinker);
1212 s1->specialdata = floor;
1213 floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
1214 floor->type = lowerFloor;
1215 floor->crush = false;
1216 floor->direction = -1;
1217 floor->sector = s1;
1218 floor->speed = FLOORSPEED / 2;
1219 floor->floordestheight = s3->floorheight;
1220 break;
1223 return rtn;
1229 // SPECIAL SPAWNING
1233 // P_SpawnSpecials
1234 // After the map has been loaded, scan for specials
1235 // that spawn thinkers
1237 short numlinespecials;
1238 line_t* linespeciallist[MAXLINEANIMS];
1241 // Parses command line parameters.
1242 void P_SpawnSpecials (void)
1244 sector_t* sector;
1245 int i;
1246 int episode;
1248 episode = 1;
1249 if (W_CheckNumForName("texture2") >= 0)
1250 episode = 2;
1253 // See if -TIMER needs to be used.
1254 levelTimer = false;
1256 i = M_CheckParm("-avg");
1257 if (i && deathmatch)
1259 levelTimer = true;
1260 levelTimeCount = 20 * 60 * 35;
1263 i = M_CheckParm("-timer");
1264 if (i && deathmatch)
1266 int time;
1267 time = atoi(myargv[i+1]) * 60 * 35;
1268 levelTimer = true;
1269 levelTimeCount = time;
1272 // Init special SECTORs.
1273 sector = sectors;
1274 for (i=0 ; i<numsectors ; i++, sector++)
1276 if (!sector->special)
1277 continue;
1279 switch (sector->special)
1281 case 1:
1282 // FLICKERING LIGHTS
1283 P_SpawnLightFlash (sector);
1284 break;
1286 case 2:
1287 // STROBE FAST
1288 P_SpawnStrobeFlash(sector,FASTDARK,0);
1289 break;
1291 case 3:
1292 // STROBE SLOW
1293 P_SpawnStrobeFlash(sector,SLOWDARK,0);
1294 break;
1296 case 4:
1297 // STROBE FAST/DEATH SLIME
1298 P_SpawnStrobeFlash(sector,FASTDARK,0);
1299 sector->special = 4;
1300 break;
1302 case 8:
1303 // GLOWING LIGHT
1304 P_SpawnGlowingLight(sector);
1305 break;
1306 case 9:
1307 // SECRET SECTOR
1308 totalsecret++;
1309 break;
1311 case 10:
1312 // DOOR CLOSE IN 30 SECONDS
1313 P_SpawnDoorCloseIn30 (sector);
1314 break;
1316 case 12:
1317 // SYNC STROBE SLOW
1318 P_SpawnStrobeFlash (sector, SLOWDARK, 1);
1319 break;
1321 case 13:
1322 // SYNC STROBE FAST
1323 P_SpawnStrobeFlash (sector, FASTDARK, 1);
1324 break;
1326 case 14:
1327 // DOOR RAISE IN 5 MINUTES
1328 P_SpawnDoorRaiseIn5Mins (sector, i);
1329 break;
1331 case 17:
1332 P_SpawnFireFlicker(sector);
1333 break;
1338 // Init line EFFECTs
1339 numlinespecials = 0;
1340 for (i = 0;i < numlines; i++)
1342 switch(lines[i].special)
1344 case 48:
1345 // EFFECT FIRSTCOL SCROLL+
1346 linespeciallist[numlinespecials] = &lines[i];
1347 numlinespecials++;
1348 break;
1353 // Init other misc stuff
1354 for (i = 0;i < MAXCEILINGS;i++)
1355 activeceilings[i] = NULL;
1357 for (i = 0;i < MAXPLATS;i++)
1358 activeplats[i] = NULL;
1360 for (i = 0;i < MAXBUTTONS;i++)
1361 memset(&buttonlist[i],0,sizeof(button_t));
1363 // UNUSED: no horizonal sliders.
1364 // P_InitSlidingDoorFrames();