1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 * -Loads and initializes texture and flat animation sequences
29 * -Implements utility functions for all linedef/sector special handlers
30 * -Dispatches walkover and gun line triggers
31 * -Initializes and implements special sector types
32 * -Implements donut linedef triggers
33 * -Initializes and implements BOOM linedef triggers for
38 *-----------------------------------------------------------------------------*/
56 #include "m_bbox.h" // phares 3/20/98
60 #include "rockmacros.h"
62 // Animating textures and planes
63 // There is another anim_t used in wi_stuff, unrelated.
76 // source animation definition
79 #ifdef _MSC_VER // proff: This is the same as __attribute__ ((packed)) in GNUC
84 #if defined(__MWERKS__)
85 #pragma options align=packed
90 signed char istexture
; //jff 3/23/98 make char for comparison // cph - make signed
91 char endname
[9]; // if false, it is a flat
94 } PACKEDATTR animdef_t
; //jff 3/23/98 pack to read from memory
96 #define MAXANIMS 32 // no longer a strict limit -- killough
99 anim_t
* anims
; // new structure w/o limits -- killough
100 static size_t maxanims
;
102 // killough 3/7/98: Initialize generalized scrolling
103 static void P_SpawnScrollers(void);
105 static void P_SpawnFriction(void); // phares 3/16/98
106 static void P_SpawnPushers(void); // phares 3/20/98
108 extern int allow_pushers
;
109 extern int variable_friction
; // phares 3/20/98
114 // Load the table of animation definitions, checking for existence of
115 // the start and end of each frame. If the start doesn't exist the sequence
116 // is skipped, if the last doesn't exist, BOOM exits.
118 // Wall/Flat animation sequences, defined by name of first and last frame,
119 // The full animation sequence is given using all lumps between the start
120 // and end entry, in the order found in the WAD file.
122 // This routine modified to read its data from a predefined lump or
123 // PWAD lump called ANIMATED rather than a static table in this module to
124 // allow wad designers to insert or modify animation sequences.
126 // Lump format is an array of byte packed animdef_t structures, terminated
127 // by a structure with istexture == -1. The lump can be generated from a
128 // text source file using SWANTBLS.EXE, distributed with the BOOM utils.
129 // The standard list of switches and animations is contained in the example
130 // source text file DEFSWANI.DAT also in the BOOM util distribution.
133 void P_InitPicAnims (void)
136 const animdef_t
*animdefs
; //jff 3/23/98 pointer to animation lump
137 int lump
= W_GetNumForName("ANIMATED"); // cph - new wad lump handling
140 //jff 3/23/98 read from predefined or wad lump instead of table
141 animdefs
= (const animdef_t
*)W_CacheLumpNum(lump
);
144 for (i
=0 ; animdefs
[i
].istexture
!= -1 ; i
++)
146 // 1/11/98 killough -- removed limit by array-doubling
147 if (lastanim
>= anims
+ maxanims
)
149 size_t newmax
= maxanims
? maxanims
*2 : MAXANIMS
;
150 anims
= realloc(anims
, newmax
*sizeof(*anims
)); // killough
151 lastanim
= anims
+ maxanims
;
155 if (animdefs
[i
].istexture
)
157 // different episode ?
158 if (R_CheckTextureNumForName(animdefs
[i
].startname
) == -1)
161 lastanim
->picnum
= R_TextureNumForName (animdefs
[i
].endname
);
162 lastanim
->basepic
= R_TextureNumForName (animdefs
[i
].startname
);
166 if ((W_CheckNumForName
)(animdefs
[i
].startname
, ns_flats
) == -1) // killough 4/17/98
169 lastanim
->picnum
= R_FlatNumForName (animdefs
[i
].endname
);
170 lastanim
->basepic
= R_FlatNumForName (animdefs
[i
].startname
);
173 lastanim
->istexture
= animdefs
[i
].istexture
;
174 lastanim
->numpics
= lastanim
->picnum
- lastanim
->basepic
+ 1;
176 if (lastanim
->numpics
< 2)
177 I_Error ("P_InitPicAnims: bad cycle from %s to %s",
178 animdefs
[i
].startname
,
179 animdefs
[i
].endname
);
181 lastanim
->speed
= LONG(animdefs
[i
].speed
); // killough 5/5/98: add LONG()
184 W_UnlockLumpNum(lump
);
187 ///////////////////////////////////////////////////////////////
189 // Linedef and Sector Special Implementation Utility Functions
191 ///////////////////////////////////////////////////////////////
196 // Will return a side_t*
197 // given the number of the current sector,
198 // the line number, and the side (0/1) that you want.
200 // Note: if side=1 is specified, it must exist or results undefined
207 return &sides
[ (sectors
[currentSector
].lines
[line
])->sidenum
[side
] ];
214 // Will return a sector_t*
215 // given the number of the current sector,
216 // the line number and the side (0/1) that you want.
218 // Note: if side=1 is specified, it must exist or results undefined
225 return sides
[ (sectors
[currentSector
].lines
[line
])->sidenum
[side
] ].sector
;
232 // Given the sector number and the line number,
233 // it will tell you whether the line is two-sided or not.
235 // modified to return actual two-sidedness rather than presence
236 // of 2S flag unless compatibility optioned
242 //jff 1/26/98 return what is actually needed, whether the line
243 //has two sidedefs, rather than whether the 2S flag is set
245 return comp
[comp_model
] ?
246 (sectors
[sector
].lines
[line
])->flags
& ML_TWOSIDED
248 (sectors
[sector
].lines
[line
])->sidenum
[1] != -1;
255 // Return sector_t * of sector next to current across line.
257 // Note: returns NULL if not two-sided line, or both sides refer to sector
259 sector_t
* getNextSector
263 //jff 1/26/98 check unneeded since line->backsector already
264 //returns NULL if the line is not two sided, and does so from
265 //the actual two-sidedness of the line, rather than its 2S flag
267 if (comp
[comp_model
])
269 if (!(line
->flags
& ML_TWOSIDED
))
273 if (line
->frontsector
== sec
) {
274 if (comp
[comp_model
] || line
->backsector
!=sec
)
275 return line
->backsector
; //jff 5/3/98 don't retn sec unless compatibility
276 else // fixes an intra-sector line breaking functions
277 return NULL
; // like floor->highest floor
279 return line
->frontsector
;
284 // P_FindLowestFloorSurrounding()
286 // Returns the fixed point value of the lowest floor height
287 // in the sector passed or its surrounding sectors.
289 fixed_t
P_FindLowestFloorSurrounding(sector_t
* sec
)
294 fixed_t floor
= sec
->floorheight
;
296 for (i
=0 ;i
< sec
->linecount
; i
++)
298 check
= sec
->lines
[i
];
299 other
= getNextSector(check
,sec
);
304 if (other
->floorheight
< floor
)
305 floor
= other
->floorheight
;
312 // P_FindHighestFloorSurrounding()
314 // Passed a sector, returns the fixed point value of the largest
315 // floor height in the surrounding sectors, not including that passed
317 // NOTE: if no surrounding sector exists -32000*FRACUINT is returned
318 // if compatibility then -500*FRACUNIT is the smallest return possible
320 fixed_t
P_FindHighestFloorSurrounding(sector_t
*sec
)
325 fixed_t floor
= -500*FRACUNIT
;
327 //jff 1/26/98 Fix initial value for floor to not act differently
328 //in sections of wad that are below -500 units
329 if (!comp
[comp_model
]) /* jff 3/12/98 avoid ovf */
330 floor
= -32000*FRACUNIT
; // in height calculations
332 for (i
=0 ;i
< sec
->linecount
; i
++)
334 check
= sec
->lines
[i
];
335 other
= getNextSector(check
,sec
);
340 if (other
->floorheight
> floor
)
341 floor
= other
->floorheight
;
348 // P_FindNextHighestFloor()
350 // Passed a sector and a floor height, returns the fixed point value
351 // of the smallest floor height in a surrounding sector larger than
352 // the floor height passed. If no such height exists the floorheight
353 // passed is returned.
355 // Rewritten by Lee Killough to avoid fixed array and to be faster
357 fixed_t
P_FindNextHighestFloor(sector_t
*sec
, int currentheight
)
362 for (i
=0 ;i
< sec
->linecount
; i
++)
363 if ((other
= getNextSector(sec
->lines
[i
],sec
)) &&
364 other
->floorheight
> currentheight
)
366 int height
= other
->floorheight
;
367 while (++i
< sec
->linecount
)
368 if ((other
= getNextSector(sec
->lines
[i
],sec
)) &&
369 other
->floorheight
< height
&&
370 other
->floorheight
> currentheight
)
371 height
= other
->floorheight
;
374 return currentheight
;
379 // P_FindNextLowestFloor()
381 // Passed a sector and a floor height, returns the fixed point value
382 // of the largest floor height in a surrounding sector smaller than
383 // the floor height passed. If no such height exists the floorheight
384 // passed is returned.
386 // jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this
388 fixed_t
P_FindNextLowestFloor(sector_t
*sec
, int currentheight
)
393 for (i
=0 ;i
< sec
->linecount
; i
++)
394 if ((other
= getNextSector(sec
->lines
[i
],sec
)) &&
395 other
->floorheight
< currentheight
)
397 int height
= other
->floorheight
;
398 while (++i
< sec
->linecount
)
399 if ((other
= getNextSector(sec
->lines
[i
],sec
)) &&
400 other
->floorheight
> height
&&
401 other
->floorheight
< currentheight
)
402 height
= other
->floorheight
;
405 return currentheight
;
410 // P_FindNextLowestCeiling()
412 // Passed a sector and a ceiling height, returns the fixed point value
413 // of the largest ceiling height in a surrounding sector smaller than
414 // the ceiling height passed. If no such height exists the ceiling height
415 // passed is returned.
417 // jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this
419 fixed_t
P_FindNextLowestCeiling(sector_t
*sec
, int currentheight
)
424 for (i
=0 ;i
< sec
->linecount
; i
++)
425 if ((other
= getNextSector(sec
->lines
[i
],sec
)) &&
426 other
->ceilingheight
< currentheight
)
428 int height
= other
->ceilingheight
;
429 while (++i
< sec
->linecount
)
430 if ((other
= getNextSector(sec
->lines
[i
],sec
)) &&
431 other
->ceilingheight
> height
&&
432 other
->ceilingheight
< currentheight
)
433 height
= other
->ceilingheight
;
436 return currentheight
;
441 // P_FindNextHighestCeiling()
443 // Passed a sector and a ceiling height, returns the fixed point value
444 // of the smallest ceiling height in a surrounding sector larger than
445 // the ceiling height passed. If no such height exists the ceiling height
446 // passed is returned.
448 // jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this
450 fixed_t
P_FindNextHighestCeiling(sector_t
*sec
, int currentheight
)
455 for (i
=0 ;i
< sec
->linecount
; i
++)
456 if ((other
= getNextSector(sec
->lines
[i
],sec
)) &&
457 other
->ceilingheight
> currentheight
)
459 int height
= other
->ceilingheight
;
460 while (++i
< sec
->linecount
)
461 if ((other
= getNextSector(sec
->lines
[i
],sec
)) &&
462 other
->ceilingheight
< height
&&
463 other
->ceilingheight
> currentheight
)
464 height
= other
->ceilingheight
;
467 return currentheight
;
472 // P_FindLowestCeilingSurrounding()
474 // Passed a sector, returns the fixed point value of the smallest
475 // ceiling height in the surrounding sectors, not including that passed
477 // NOTE: if no surrounding sector exists 32000*FRACUINT is returned
478 // but if compatibility then INT_MAX is the return
480 fixed_t
P_FindLowestCeilingSurrounding(sector_t
* sec
)
485 fixed_t height
= INT_MAX
;
487 /* jff 3/12/98 avoid ovf in height calculations */
488 if (!comp
[comp_model
]) height
= 32000*FRACUNIT
;
490 for (i
=0 ;i
< sec
->linecount
; i
++)
492 check
= sec
->lines
[i
];
493 other
= getNextSector(check
,sec
);
498 if (other
->ceilingheight
< height
)
499 height
= other
->ceilingheight
;
506 // P_FindHighestCeilingSurrounding()
508 // Passed a sector, returns the fixed point value of the largest
509 // ceiling height in the surrounding sectors, not including that passed
511 // NOTE: if no surrounding sector exists -32000*FRACUINT is returned
512 // but if compatibility then 0 is the smallest return possible
514 fixed_t
P_FindHighestCeilingSurrounding(sector_t
* sec
)
521 /* jff 1/26/98 Fix initial value for floor to not act differently
522 * in sections of wad that are below 0 units
523 * jff 3/12/98 avoid ovf in height calculations */
524 if (!comp
[comp_model
]) height
= -32000*FRACUNIT
;
526 for (i
=0 ;i
< sec
->linecount
; i
++)
528 check
= sec
->lines
[i
];
529 other
= getNextSector(check
,sec
);
534 if (other
->ceilingheight
> height
)
535 height
= other
->ceilingheight
;
542 // P_FindShortestTextureAround()
544 // Passed a sector number, returns the shortest lower texture on a
545 // linedef bounding the sector.
547 // Note: If no lower texture exists 32000*FRACUNIT is returned.
548 // but if compatibility then INT_MAX is returned
550 // jff 02/03/98 Add routine to find shortest lower texture
552 fixed_t
P_FindShortestTextureAround(int secnum
)
554 int minsize
= INT_MAX
;
557 sector_t
*sec
= §ors
[secnum
];
559 if (!comp
[comp_model
])
560 minsize
= 32000<<FRACBITS
; //jff 3/13/98 prevent overflow in height calcs
562 for (i
= 0; i
< sec
->linecount
; i
++)
564 if (twoSided(secnum
, i
))
566 side
= getSide(secnum
,i
,0);
567 if (side
->bottomtexture
> 0) //jff 8/14/98 texture 0 is a placeholder
568 if (textureheight
[side
->bottomtexture
] < minsize
)
569 minsize
= textureheight
[side
->bottomtexture
];
570 side
= getSide(secnum
,i
,1);
571 if (side
->bottomtexture
> 0) //jff 8/14/98 texture 0 is a placeholder
572 if (textureheight
[side
->bottomtexture
] < minsize
)
573 minsize
= textureheight
[side
->bottomtexture
];
581 // P_FindShortestUpperAround()
583 // Passed a sector number, returns the shortest upper texture on a
584 // linedef bounding the sector.
586 // Note: If no upper texture exists 32000*FRACUNIT is returned.
587 // but if compatibility then INT_MAX is returned
589 // jff 03/20/98 Add routine to find shortest upper texture
591 fixed_t
P_FindShortestUpperAround(int secnum
)
593 int minsize
= INT_MAX
;
596 sector_t
*sec
= §ors
[secnum
];
598 if (!comp
[comp_model
])
599 minsize
= 32000<<FRACBITS
; //jff 3/13/98 prevent overflow
601 for (i
= 0; i
< sec
->linecount
; i
++)
603 if (twoSided(secnum
, i
))
605 side
= getSide(secnum
,i
,0);
606 if (side
->toptexture
> 0) //jff 8/14/98 texture 0 is a placeholder
607 if (textureheight
[side
->toptexture
] < minsize
)
608 minsize
= textureheight
[side
->toptexture
];
609 side
= getSide(secnum
,i
,1);
610 if (side
->toptexture
> 0) //jff 8/14/98 texture 0 is a placeholder
611 if (textureheight
[side
->toptexture
] < minsize
)
612 minsize
= textureheight
[side
->toptexture
];
620 // P_FindModelFloorSector()
622 // Passed a floor height and a sector number, return a pointer to a
623 // a sector with that floor height across the lowest numbered two sided
624 // line surrounding the sector.
626 // Note: If no sector at that height bounds the sector passed, return NULL
628 // jff 02/03/98 Add routine to find numeric model floor
629 // around a sector specified by sector number
630 // jff 3/14/98 change first parameter to plain height to allow call
631 // from routine not using floormove_t
633 sector_t
*P_FindModelFloorSector(fixed_t floordestheight
,int secnum
)
639 sec
= §ors
[secnum
]; //jff 3/2/98 woops! better do this
640 //jff 5/23/98 don't disturb sec->linecount while searching
641 // but allow early exit in old demos
642 linecount
= sec
->linecount
;
643 for (i
= 0; i
< (demo_compatibility
&& sec
->linecount
<linecount
?
644 sec
->linecount
: linecount
); i
++)
646 if ( twoSided(secnum
, i
) )
648 if (getSide(secnum
,i
,0)->sector
-sectors
== secnum
)
649 sec
= getSector(secnum
,i
,1);
651 sec
= getSector(secnum
,i
,0);
653 if (sec
->floorheight
== floordestheight
)
662 // P_FindModelCeilingSector()
664 // Passed a ceiling height and a sector number, return a pointer to a
665 // a sector with that ceiling height across the lowest numbered two sided
666 // line surrounding the sector.
668 // Note: If no sector at that height bounds the sector passed, return NULL
670 // jff 02/03/98 Add routine to find numeric model ceiling
671 // around a sector specified by sector number
672 // used only from generalized ceiling types
673 // jff 3/14/98 change first parameter to plain height to allow call
674 // from routine not using ceiling_t
676 sector_t
*P_FindModelCeilingSector(fixed_t ceildestheight
,int secnum
)
682 sec
= §ors
[secnum
]; //jff 3/2/98 woops! better do this
683 //jff 5/23/98 don't disturb sec->linecount while searching
684 // but allow early exit in old demos
685 linecount
= sec
->linecount
;
686 for (i
= 0; i
< (demo_compatibility
&& sec
->linecount
<linecount
?
687 sec
->linecount
: linecount
); i
++)
689 if ( twoSided(secnum
, i
) )
691 if (getSide(secnum
,i
,0)->sector
-sectors
== secnum
)
692 sec
= getSector(secnum
,i
,1);
694 sec
= getSector(secnum
,i
,0);
696 if (sec
->ceilingheight
== ceildestheight
)
704 // RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
707 // Find the next sector with the same tag as a linedef.
708 // Rewritten by Lee Killough to use chained hashing to improve speed
710 int P_FindSectorFromLineTag(const line_t
*line
, int start
)
712 start
= start
>= 0 ? sectors
[start
].nexttag
:
713 sectors
[(unsigned) line
->tag
% (unsigned) numsectors
].firsttag
;
714 while (start
>= 0 && sectors
[start
].tag
!= line
->tag
)
715 start
= sectors
[start
].nexttag
;
719 // killough 4/16/98: Same thing, only for linedefs
721 int P_FindLineFromLineTag(const line_t
*line
, int start
)
723 start
= start
>= 0 ? lines
[start
].nexttag
:
724 lines
[(unsigned) line
->tag
% (unsigned) numlines
].firsttag
;
725 while (start
>= 0 && lines
[start
].tag
!= line
->tag
)
726 start
= lines
[start
].nexttag
;
730 // Hash the sector tags across the sectors and linedefs.
731 static void P_InitTagLists(void)
735 for (i
=numsectors
; --i
>=0; ) // Initially make all slots empty.
736 sectors
[i
].firsttag
= -1;
737 for (i
=numsectors
; --i
>=0; ) // Proceed from last to first sector
738 { // so that lower sectors appear first
739 int j
= (unsigned) sectors
[i
].tag
% (unsigned) numsectors
; // Hash func
740 sectors
[i
].nexttag
= sectors
[j
].firsttag
; // Prepend sector to chain
741 sectors
[j
].firsttag
= i
;
744 // killough 4/17/98: same thing, only for linedefs
746 for (i
=numlines
; --i
>=0; ) // Initially make all slots empty.
747 lines
[i
].firsttag
= -1;
748 for (i
=numlines
; --i
>=0; ) // Proceed from last to first linedef
749 { // so that lower linedefs appear first
750 int j
= (unsigned) lines
[i
].tag
% (unsigned) numlines
; // Hash func
751 lines
[i
].nexttag
= lines
[j
].firsttag
; // Prepend linedef to chain
752 lines
[j
].firsttag
= i
;
757 // P_FindMinSurroundingLight()
759 // Passed a sector and a light level, returns the smallest light level
760 // in a surrounding sector less than that passed. If no smaller light
761 // level exists, the light level passed is returned.
763 int P_FindMinSurroundingLight
773 for (i
=0 ; i
< sector
->linecount
; i
++)
775 line
= sector
->lines
[i
];
776 check
= getNextSector(line
,sector
);
781 if (check
->lightlevel
< min
)
782 min
= check
->lightlevel
;
789 // P_CanUnlockGenDoor()
791 // Passed a generalized locked door linedef and a player, returns whether
792 // the player has the keys necessary to unlock that door.
794 // Note: The linedef passed MUST be a generalized locked door type
795 // or results are undefined.
797 // jff 02/05/98 routine added to test for unlockability of
798 // generalized locked doors
800 boolean P_CanUnlockGenDoor
804 // does this line special distinguish between skulls and keys?
805 int skulliscard
= (line
->special
& LockedNKeys
)>>LockedNKeysShift
;
807 // determine for each case of lock type if player's keys are adequate
808 switch((line
->special
& LockedKey
)>>LockedKeyShift
)
813 !player
->cards
[it_redcard
] &&
814 !player
->cards
[it_redskull
] &&
815 !player
->cards
[it_bluecard
] &&
816 !player
->cards
[it_blueskull
] &&
817 !player
->cards
[it_yellowcard
] &&
818 !player
->cards
[it_yellowskull
]
821 player
->message
= s_PD_ANY
; // Ty 03/27/98 - externalized
822 S_StartSound(player
->mo
,sfx_oof
); // killough 3/20/98
829 !player
->cards
[it_redcard
] &&
830 (!skulliscard
|| !player
->cards
[it_redskull
])
833 player
->message
= skulliscard
? s_PD_REDK
: s_PD_REDC
; // Ty 03/27/98 - externalized
834 S_StartSound(player
->mo
,sfx_oof
); // killough 3/20/98
841 !player
->cards
[it_bluecard
] &&
842 (!skulliscard
|| !player
->cards
[it_blueskull
])
845 player
->message
= skulliscard
? s_PD_BLUEK
: s_PD_BLUEC
; // Ty 03/27/98 - externalized
846 S_StartSound(player
->mo
,sfx_oof
); // killough 3/20/98
853 !player
->cards
[it_yellowcard
] &&
854 (!skulliscard
|| !player
->cards
[it_yellowskull
])
857 player
->message
= skulliscard
? s_PD_YELLOWK
: s_PD_YELLOWC
; // Ty 03/27/98 - externalized
858 S_StartSound(player
->mo
,sfx_oof
); // killough 3/20/98
865 !player
->cards
[it_redskull
] &&
866 (!skulliscard
|| !player
->cards
[it_redcard
])
869 player
->message
= skulliscard
? s_PD_REDK
: s_PD_REDS
; // Ty 03/27/98 - externalized
870 S_StartSound(player
->mo
,sfx_oof
); // killough 3/20/98
877 !player
->cards
[it_blueskull
] &&
878 (!skulliscard
|| !player
->cards
[it_bluecard
])
881 player
->message
= skulliscard
? s_PD_BLUEK
: s_PD_BLUES
; // Ty 03/27/98 - externalized
882 S_StartSound(player
->mo
,sfx_oof
); // killough 3/20/98
889 !player
->cards
[it_yellowskull
] &&
890 (!skulliscard
|| !player
->cards
[it_yellowcard
])
893 player
->message
= skulliscard
? s_PD_YELLOWK
: s_PD_YELLOWS
; // Ty 03/27/98 - externalized
894 S_StartSound(player
->mo
,sfx_oof
); // killough 3/20/98
903 !player
->cards
[it_redcard
] ||
904 !player
->cards
[it_redskull
] ||
905 !player
->cards
[it_bluecard
] ||
906 !player
->cards
[it_blueskull
] ||
907 !player
->cards
[it_yellowcard
] ||
908 !player
->cards
[it_yellowskull
]
912 player
->message
= s_PD_ALL6
; // Ty 03/27/98 - externalized
913 S_StartSound(player
->mo
,sfx_oof
); // killough 3/20/98
920 (!player
->cards
[it_redcard
] &&
921 !player
->cards
[it_redskull
]) ||
922 (!player
->cards
[it_bluecard
] &&
923 !player
->cards
[it_blueskull
]) ||
924 (!player
->cards
[it_yellowcard
] &&
925 !player
->cards
[it_yellowskull
])
929 player
->message
= s_PD_ALL3
; // Ty 03/27/98 - externalized
930 S_StartSound(player
->mo
,sfx_oof
); // killough 3/20/98
942 // Passed a linedef special class (floor, ceiling, lighting) and a sector
943 // returns whether the sector is already busy with a linedef special of the
944 // same class. If old demo compatibility true, all linedef special classes
947 // jff 2/23/98 added to prevent old demos from
948 // succeeding in starting multiple specials on one sector
950 boolean
P_SectorActive(special_e t
,sector_t
*sec
)
952 if (demo_compatibility
) // return whether any thinker is active
953 return sec
->floordata
|| sec
->ceilingdata
|| sec
->lightingdata
;
955 switch (t
) // return whether thinker of same type is active
958 return (sec
->floordata
!=NULL
);
959 case ceiling_special
:
960 return (sec
->ceilingdata
!=NULL
);
961 case lighting_special
:
962 return (sec
->lightingdata
!=NULL
);
964 return true; // don't know which special, must be active, shouldn't be here
971 // Passed a line, returns true if the tag is non-zero or the line special
972 // allows no tag without harm. If compatibility, all linedef specials are
973 // allowed to have zero tag.
975 // Note: Only line specials activated by walkover, pushing, or shooting are
976 // checked by this routine.
978 // jff 2/27/98 Added to check for zero tag allowed for regular special types
980 int P_CheckTag(line_t
*line
)
982 /* tag not zero, allowed, or
983 * killough 11/98: compatibility option */
984 if (comp
[comp_zerotags
] || line
->tag
)
987 switch(line
->special
)
989 case 1: // Manual door specials
1000 case 139: // Lighting specials
1021 case 195: // Thing teleporters
1039 case 48: // Scrolling walls
1041 return 1; // zero tag allowed
1046 return 0; // zero tag not allowed
1053 // Passed a sector, returns if the sector secret type is still active, i.e.
1054 // secret type is set and the secret has not yet been obtained.
1056 // jff 3/14/98 added to simplify checks for whether sector is secret
1057 // in automap and other places
1059 boolean
P_IsSecret(sector_t
*sec
)
1061 return (sec
->special
==9 || (sec
->special
&SECRET_MASK
));
1068 // Passed a sector, returns if the sector secret type is was active, i.e.
1069 // secret type was set and the secret has been obtained already.
1071 // jff 3/14/98 added to simplify checks for whether sector is secret
1072 // in automap and other places
1074 boolean
P_WasSecret(sector_t
*sec
)
1076 return (sec
->oldspecial
==9 || (sec
->oldspecial
&SECRET_MASK
));
1080 //////////////////////////////////////////////////////////////////////////
1084 // Events are operations triggered by using, crossing,
1085 // or shooting special lines, or by timed thinkers.
1087 /////////////////////////////////////////////////////////////////////////
1090 // P_CrossSpecialLine - Walkover Trigger Dispatcher
1092 // Called every time a thing origin is about
1093 // to cross a line with a non 0 special, whether a walkover type or not.
1095 // jff 02/12/98 all W1 lines were fixed to check the result from the EV_
1096 // function before clearing the special. This avoids losing the function
1097 // of the line, should the sector already be active when the line is
1098 // crossed. Change is qualified by demo_compatibility.
1100 // CPhipps - take a line_t pointer instead of a line number, as in MBF
1101 void P_CrossSpecialLine(line_t
*line
, int side
, mobj_t
*thing
)
1105 // Things that should never trigger lines
1108 // Things that should NOT trigger specials...
1116 case MT_BRUISERSHOT
:
1124 //jff 02/04/98 add check here for generalized lindef types
1125 if (!demo_compatibility
) // generalized types not recognized if old demo
1127 // pointer to line function is NULL by default, set non-null if
1128 // line special is walkover generalized linedef type
1129 int (*linefunc
)(line_t
*line
)=NULL
;
1131 // check each range of generalized linedefs
1132 if ((unsigned)line
->special
>= GenEnd
)
1134 // Out of range for GenFloors
1136 else if ((unsigned)line
->special
>= GenFloorBase
)
1139 if ((line
->special
& FloorChange
) || !(line
->special
& FloorModel
))
1140 return; // FloorModel is "Allow Monsters" if FloorChange is 0
1141 if (!line
->tag
) //jff 2/27/98 all walk generalized types require tag
1143 linefunc
= EV_DoGenFloor
;
1145 else if ((unsigned)line
->special
>= GenCeilingBase
)
1148 if ((line
->special
& CeilingChange
) || !(line
->special
& CeilingModel
))
1149 return; // CeilingModel is "Allow Monsters" if CeilingChange is 0
1150 if (!line
->tag
) //jff 2/27/98 all walk generalized types require tag
1152 linefunc
= EV_DoGenCeiling
;
1154 else if ((unsigned)line
->special
>= GenDoorBase
)
1158 if (!(line
->special
& DoorMonster
))
1159 return; // monsters disallowed from this door
1160 if (line
->flags
& ML_SECRET
) // they can't open secret doors either
1163 if (!line
->tag
) //3/2/98 move outside the monster check
1165 linefunc
= EV_DoGenDoor
;
1167 else if ((unsigned)line
->special
>= GenLockedBase
)
1170 return; // monsters disallowed from unlocking doors
1171 if (((line
->special
&TriggerType
)==WalkOnce
) || ((line
->special
&TriggerType
)==WalkMany
))
1172 { //jff 4/1/98 check for being a walk type before reporting door type
1173 if (!P_CanUnlockGenDoor(line
,thing
->player
))
1178 linefunc
= EV_DoGenLockedDoor
;
1180 else if ((unsigned)line
->special
>= GenLiftBase
)
1183 if (!(line
->special
& LiftMonster
))
1184 return; // monsters disallowed
1185 if (!line
->tag
) //jff 2/27/98 all walk generalized types require tag
1187 linefunc
= EV_DoGenLift
;
1189 else if ((unsigned)line
->special
>= GenStairsBase
)
1192 if (!(line
->special
& StairMonster
))
1193 return; // monsters disallowed
1194 if (!line
->tag
) //jff 2/27/98 all walk generalized types require tag
1196 linefunc
= EV_DoGenStairs
;
1199 if (linefunc
) // if it was a valid generalized type
1200 switch((line
->special
& TriggerType
) >> TriggerTypeShift
)
1204 line
->special
= 0; // clear special if a walk once type
1209 default: // if not a walk type, do nothing here
1217 switch(line
->special
)
1219 case 39: // teleport trigger
1220 case 97: // teleport retrigger
1221 case 125: // teleport monsteronly trigger
1222 case 126: // teleport monsteronly retrigger
1223 case 4: // raise door
1224 case 10: // plat down-wait-up-stay trigger
1225 case 88: // plat down-wait-up-stay retrigger
1226 //jff 3/5/98 add ability of monsters etc. to use teleporters
1227 case 208: //silent thing teleporters
1229 case 243: //silent line-line teleporter
1230 case 244: //jff 3/6/98 make fit within DCK's 256 linedef types
1231 case 262: //jff 4/14/98 add monster only
1232 case 263: //jff 4/14/98 silent thing,line,line rev types
1233 case 264: //jff 4/14/98 plus player/monster silent line
1234 case 265: // reversed types
1246 if (!P_CheckTag(line
)) //jff 2/27/98 disallow zero tag on some types
1249 // Dispatch on the line special value to the line's action routine
1250 // If a once only function, and successful, clear the line special
1252 switch (line
->special
)
1254 // Regular walk once triggers
1258 if (EV_DoDoor(line
,p_open
) || demo_compatibility
)
1264 if (EV_DoDoor(line
,p_close
) || demo_compatibility
)
1270 if (EV_DoDoor(line
,normal
) || demo_compatibility
)
1276 if (EV_DoFloor(line
,raiseFloor
) || demo_compatibility
)
1281 // Fast Ceiling Crush & Raise
1282 if (EV_DoCeiling(line
,fastCrushAndRaise
) || demo_compatibility
)
1288 if (EV_BuildStairs(line
,build8
) || demo_compatibility
)
1294 if (EV_DoPlat(line
,downWaitUpStay
,0) || demo_compatibility
)
1299 // Light Turn On - brightest near
1300 if (EV_LightTurnOn(line
,0) || demo_compatibility
)
1305 // Light Turn On 255
1306 if (EV_LightTurnOn(line
,255) || demo_compatibility
)
1312 if (EV_DoDoor(line
,close30ThenOpen
) || demo_compatibility
)
1317 // Start Light Strobing
1318 if (EV_StartLightStrobing(line
) || demo_compatibility
)
1324 if (EV_DoFloor(line
,lowerFloor
) || demo_compatibility
)
1329 // Raise floor to nearest height and change texture
1330 if (EV_DoPlat(line
,raiseToNearestAndChange
,0) || demo_compatibility
)
1335 // Ceiling Crush and Raise
1336 if (EV_DoCeiling(line
,crushAndRaise
) || demo_compatibility
)
1341 // Raise floor to shortest texture height
1342 // on either side of lines.
1343 if (EV_DoFloor(line
,raiseToTexture
) || demo_compatibility
)
1349 if (EV_LightTurnOn(line
,35) || demo_compatibility
)
1354 // Lower Floor (TURBO)
1355 if (EV_DoFloor(line
,turboLower
) || demo_compatibility
)
1361 if (EV_DoFloor(line
,lowerAndChange
) || demo_compatibility
)
1366 // Lower Floor To Lowest
1367 if (EV_DoFloor(line
, lowerFloorToLowest
) || demo_compatibility
)
1372 // TELEPORT! //jff 02/09/98 fix using up with wrong side crossing
1373 if (EV_Teleport(line
, side
, thing
) || demo_compatibility
)
1378 // RaiseCeilingLowerFloor
1379 if (demo_compatibility
)
1381 EV_DoCeiling( line
, raiseToHighest
);
1382 EV_DoFloor( line
, lowerFloorToLowest
); //jff 02/12/98 doesn't work
1386 if (EV_DoCeiling(line
, raiseToHighest
))
1392 if (EV_DoCeiling(line
, lowerAndCrush
) || demo_compatibility
)
1398 // killough 10/98: prevent zombies from exiting levels
1399 if (!(thing
->player
&& thing
->player
->health
<= 0 && !comp
[comp_zombie
]))
1404 // Perpetual Platform Raise
1405 if (EV_DoPlat(line
,perpetualRaise
,0) || demo_compatibility
)
1411 if (EV_StopPlat(line
) || demo_compatibility
)
1416 // Raise Floor Crush
1417 if (EV_DoFloor(line
,raiseFloorCrush
) || demo_compatibility
)
1422 // Ceiling Crush Stop
1423 if (EV_CeilingCrushStop(line
) || demo_compatibility
)
1429 if (EV_DoFloor(line
,raiseFloor24
) || demo_compatibility
)
1434 // Raise Floor 24 And Change
1435 if (EV_DoFloor(line
,raiseFloor24AndChange
) || demo_compatibility
)
1440 // Build Stairs Turbo 16
1441 if (EV_BuildStairs(line
,turbo16
) || demo_compatibility
)
1446 // Turn lights off in sector(tag)
1447 if (EV_TurnTagLightsOff(line
) || demo_compatibility
)
1452 // Blazing Door Raise (faster than TURBO!)
1453 if (EV_DoDoor(line
,blazeRaise
) || demo_compatibility
)
1458 // Blazing Door Open (faster than TURBO!)
1459 if (EV_DoDoor (line
,blazeOpen
) || demo_compatibility
)
1464 // Blazing Door Close (faster than TURBO!)
1465 if (EV_DoDoor (line
,blazeClose
) || demo_compatibility
)
1470 // Raise floor to nearest surr. floor
1471 if (EV_DoFloor(line
,raiseFloorToNearest
) || demo_compatibility
)
1476 // Blazing PlatDownWaitUpStay
1477 if (EV_DoPlat(line
,blazeDWUS
,0) || demo_compatibility
)
1483 // killough 10/98: prevent zombies from exiting levels
1484 // CPhipps - change for lxdoom's compatibility handling
1485 if (!(thing
->player
&& thing
->player
->health
<= 0 && !comp
[comp_zombie
]))
1486 G_SecretExitLevel ();
1490 // TELEPORT MonsterONLY
1491 if (!thing
->player
&&
1492 (EV_Teleport(line
, side
, thing
) || demo_compatibility
))
1497 // Raise Floor Turbo
1498 if (EV_DoFloor(line
,raiseFloorTurbo
) || demo_compatibility
)
1503 // Silent Ceiling Crush & Raise
1504 if (EV_DoCeiling(line
,silentCrushAndRaise
) || demo_compatibility
)
1508 // Regular walk many retriggerable
1512 EV_DoCeiling( line
, lowerAndCrush
);
1516 // Ceiling Crush and Raise
1517 EV_DoCeiling(line
,crushAndRaise
);
1521 // Ceiling Crush Stop
1522 EV_CeilingCrushStop(line
);
1527 EV_DoDoor(line
,p_close
);
1532 EV_DoDoor(line
,close30ThenOpen
);
1536 // Fast Ceiling Crush & Raise
1537 EV_DoCeiling(line
,fastCrushAndRaise
);
1542 EV_LightTurnOn(line
,35);
1546 // Light Turn On - brightest near
1547 EV_LightTurnOn(line
,0);
1551 // Light Turn On 255
1552 EV_LightTurnOn(line
,255);
1556 // Lower Floor To Lowest
1557 EV_DoFloor( line
, lowerFloorToLowest
);
1562 EV_DoFloor(line
,lowerFloor
);
1567 EV_DoFloor(line
,lowerAndChange
);
1572 EV_DoDoor(line
,p_open
);
1576 // Perpetual Platform Raise
1577 EV_DoPlat(line
,perpetualRaise
,0);
1582 EV_DoPlat(line
,downWaitUpStay
,0);
1592 EV_DoDoor(line
,normal
);
1597 EV_DoFloor(line
,raiseFloor
);
1602 EV_DoFloor(line
,raiseFloor24
);
1606 // Raise Floor 24 And Change
1607 EV_DoFloor(line
,raiseFloor24AndChange
);
1611 // Raise Floor Crush
1612 EV_DoFloor(line
,raiseFloorCrush
);
1616 // Raise floor to nearest height
1617 // and change texture.
1618 EV_DoPlat(line
,raiseToNearestAndChange
,0);
1622 // Raise floor to shortest texture height
1623 // on either side of lines.
1624 EV_DoFloor(line
,raiseToTexture
);
1629 EV_Teleport( line
, side
, thing
);
1633 // Lower Floor (TURBO)
1634 EV_DoFloor(line
,turboLower
);
1638 // Blazing Door Raise (faster than TURBO!)
1639 EV_DoDoor (line
,blazeRaise
);
1643 // Blazing Door Open (faster than TURBO!)
1644 EV_DoDoor (line
,blazeOpen
);
1648 // Blazing Door Close (faster than TURBO!)
1649 EV_DoDoor (line
,blazeClose
);
1653 // Blazing PlatDownWaitUpStay.
1654 EV_DoPlat(line
,blazeDWUS
,0);
1658 // TELEPORT MonsterONLY.
1660 EV_Teleport( line
, side
, thing
);
1664 // Raise To Nearest Floor
1665 EV_DoFloor(line
,raiseFloorToNearest
);
1669 // Raise Floor Turbo
1670 EV_DoFloor(line
,raiseFloorTurbo
);
1673 // Extended walk triggers
1675 // jff 1/29/98 added new linedef types to fill all functions out so that
1676 // all have varieties SR, S1, WR, W1
1678 // killough 1/31/98: "factor out" compatibility test, by
1679 // adding inner switch qualified by compatibility flag.
1680 // relax test to demo_compatibility
1682 // killough 2/16/98: Fix problems with W1 types being cleared too early
1685 if (!demo_compatibility
)
1686 switch (line
->special
)
1688 // Extended walk once triggers
1692 // 142 W1 EV_DoFloor(raiseFloor512)
1693 if (EV_DoFloor(line
,raiseFloor512
))
1698 // Raise Floor 24 and change
1699 // 143 W1 EV_DoPlat(raiseAndChange,24)
1700 if (EV_DoPlat(line
,raiseAndChange
,24))
1705 // Raise Floor 32 and change
1706 // 144 W1 EV_DoPlat(raiseAndChange,32)
1707 if (EV_DoPlat(line
,raiseAndChange
,32))
1712 // Lower Ceiling to Floor
1713 // 145 W1 EV_DoCeiling(lowerToFloor)
1714 if (EV_DoCeiling( line
, lowerToFloor
))
1719 // Lower Pillar, Raise Donut
1720 // 146 W1 EV_DoDonut()
1721 if (EV_DoDonut(line
))
1726 // Lower ceiling to lowest surrounding ceiling
1727 // 199 W1 EV_DoCeiling(lowerToLowest)
1728 if (EV_DoCeiling(line
,lowerToLowest
))
1733 // Lower ceiling to highest surrounding floor
1734 // 200 W1 EV_DoCeiling(lowerToMaxFloor)
1735 if (EV_DoCeiling(line
,lowerToMaxFloor
))
1740 // killough 2/16/98: W1 silent teleporter (normal kind)
1741 if (EV_SilentTeleport(line
, side
, thing
))
1745 //jff 3/16/98 renumber 215->153
1746 case 153: //jff 3/15/98 create texture change no motion type
1747 // Texture/Type Change Only (Trig)
1748 // 153 W1 Change Texture/Type Only
1749 if (EV_DoChange(line
,trigChangeOnly
))
1753 case 239: //jff 3/15/98 create texture change no motion type
1754 // Texture/Type Change Only (Numeric)
1755 // 239 W1 Change Texture/Type Only
1756 if (EV_DoChange(line
,numChangeOnly
))
1761 // Lower floor to next lower neighbor
1762 // 219 W1 Lower Floor Next Lower Neighbor
1763 if (EV_DoFloor(line
,lowerFloorToNearest
))
1768 // Raise elevator next floor
1769 // 227 W1 Raise Elevator next floor
1770 if (EV_DoElevator(line
,elevateUp
))
1775 // Lower elevator next floor
1776 // 231 W1 Lower Elevator next floor
1777 if (EV_DoElevator(line
,elevateDown
))
1782 // Elevator to current floor
1783 // 235 W1 Elevator to current floor
1784 if (EV_DoElevator(line
,elevateCurrent
))
1788 case 243: //jff 3/6/98 make fit within DCK's 256 linedef types
1789 // killough 2/16/98: W1 silent teleporter (linedef-linedef kind)
1790 if (EV_SilentLineTeleport(line
, side
, thing
, false))
1794 case 262: //jff 4/14/98 add silent line-line reversed
1795 if (EV_SilentLineTeleport(line
, side
, thing
, true))
1799 case 264: //jff 4/14/98 add monster-only silent line-line reversed
1800 if (!thing
->player
&&
1801 EV_SilentLineTeleport(line
, side
, thing
, true))
1805 case 266: //jff 4/14/98 add monster-only silent line-line
1806 if (!thing
->player
&&
1807 EV_SilentLineTeleport(line
, side
, thing
, false))
1811 case 268: //jff 4/14/98 add monster-only silent
1812 if (!thing
->player
&& EV_SilentTeleport(line
, side
, thing
))
1816 //jff 1/29/98 end of added W1 linedef types
1818 // Extended walk many retriggerable
1820 //jff 1/29/98 added new linedef types to fill all functions
1821 //out so that all have varieties SR, S1, WR, W1
1825 // 147 WR EV_DoFloor(raiseFloor512)
1826 EV_DoFloor(line
,raiseFloor512
);
1830 // Raise Floor 24 and Change
1831 // 148 WR EV_DoPlat(raiseAndChange,24)
1832 EV_DoPlat(line
,raiseAndChange
,24);
1836 // Raise Floor 32 and Change
1837 // 149 WR EV_DoPlat(raiseAndChange,32)
1838 EV_DoPlat(line
,raiseAndChange
,32);
1842 // Start slow silent crusher
1843 // 150 WR EV_DoCeiling(silentCrushAndRaise)
1844 EV_DoCeiling(line
,silentCrushAndRaise
);
1848 // RaiseCeilingLowerFloor
1849 // 151 WR EV_DoCeiling(raiseToHighest),
1850 // EV_DoFloor(lowerFloortoLowest)
1851 EV_DoCeiling( line
, raiseToHighest
);
1852 EV_DoFloor( line
, lowerFloorToLowest
);
1856 // Lower Ceiling to Floor
1857 // 152 WR EV_DoCeiling(lowerToFloor)
1858 EV_DoCeiling( line
, lowerToFloor
);
1861 //jff 3/16/98 renumber 153->256
1863 // Build stairs, step 8
1864 // 256 WR EV_BuildStairs(build8)
1865 EV_BuildStairs(line
,build8
);
1868 //jff 3/16/98 renumber 154->257
1870 // Build stairs, step 16
1871 // 257 WR EV_BuildStairs(turbo16)
1872 EV_BuildStairs(line
,turbo16
);
1876 // Lower Pillar, Raise Donut
1877 // 155 WR EV_DoDonut()
1882 // Start lights strobing
1883 // 156 WR Lights EV_StartLightStrobing()
1884 EV_StartLightStrobing(line
);
1888 // Lights to dimmest near
1889 // 157 WR Lights EV_TurnTagLightsOff()
1890 EV_TurnTagLightsOff(line
);
1894 // Lower ceiling to lowest surrounding ceiling
1895 // 201 WR EV_DoCeiling(lowerToLowest)
1896 EV_DoCeiling(line
,lowerToLowest
);
1900 // Lower ceiling to highest surrounding floor
1901 // 202 WR EV_DoCeiling(lowerToMaxFloor)
1902 EV_DoCeiling(line
,lowerToMaxFloor
);
1906 // killough 2/16/98: WR silent teleporter (normal kind)
1907 EV_SilentTeleport(line
, side
, thing
);
1910 case 212: //jff 3/14/98 create instant toggle floor type
1911 // Toggle floor between C and F instantly
1912 // 212 WR Instant Toggle Floor
1913 EV_DoPlat(line
,toggleUpDn
,0);
1916 //jff 3/16/98 renumber 216->154
1917 case 154: //jff 3/15/98 create texture change no motion type
1918 // Texture/Type Change Only (Trigger)
1919 // 154 WR Change Texture/Type Only
1920 EV_DoChange(line
,trigChangeOnly
);
1923 case 240: //jff 3/15/98 create texture change no motion type
1924 // Texture/Type Change Only (Numeric)
1925 // 240 WR Change Texture/Type Only
1926 EV_DoChange(line
,numChangeOnly
);
1930 // Lower floor to next lower neighbor
1931 // 220 WR Lower Floor Next Lower Neighbor
1932 EV_DoFloor(line
,lowerFloorToNearest
);
1936 // Raise elevator next floor
1937 // 228 WR Raise Elevator next floor
1938 EV_DoElevator(line
,elevateUp
);
1942 // Lower elevator next floor
1943 // 232 WR Lower Elevator next floor
1944 EV_DoElevator(line
,elevateDown
);
1948 // Elevator to current floor
1949 // 236 WR Elevator to current floor
1950 EV_DoElevator(line
,elevateCurrent
);
1953 case 244: //jff 3/6/98 make fit within DCK's 256 linedef types
1954 // killough 2/16/98: WR silent teleporter (linedef-linedef kind)
1955 EV_SilentLineTeleport(line
, side
, thing
, false);
1958 case 263: //jff 4/14/98 add silent line-line reversed
1959 EV_SilentLineTeleport(line
, side
, thing
, true);
1962 case 265: //jff 4/14/98 add monster-only silent line-line reversed
1964 EV_SilentLineTeleport(line
, side
, thing
, true);
1967 case 267: //jff 4/14/98 add monster-only silent line-line
1969 EV_SilentLineTeleport(line
, side
, thing
, false);
1972 case 269: //jff 4/14/98 add monster-only silent
1974 EV_SilentTeleport(line
, side
, thing
);
1977 //jff 1/29/98 end of added WR linedef types
1984 // P_ShootSpecialLine - Gun trigger special dispatcher
1986 // Called when a thing shoots a special line with bullet, shell, saw, or fist.
1988 // jff 02/12/98 all G1 lines were fixed to check the result from the EV_
1989 // function before clearing the special. This avoids losing the function
1990 // of the line, should the sector already be in motion when the line is
1991 // impacted. Change is qualified by demo_compatibility.
1993 void P_ShootSpecialLine
1997 //jff 02/04/98 add check here for generalized linedef
1998 if (!demo_compatibility
)
2000 // pointer to line function is NULL by default, set non-null if
2001 // line special is gun triggered generalized linedef type
2002 int (*linefunc
)(line_t
*line
)=NULL
;
2004 // check each range of generalized linedefs
2005 if ((unsigned)line
->special
>= GenEnd
)
2007 // Out of range for GenFloors
2009 else if ((unsigned)line
->special
>= GenFloorBase
)
2012 if ((line
->special
& FloorChange
) || !(line
->special
& FloorModel
))
2013 return; // FloorModel is "Allow Monsters" if FloorChange is 0
2014 if (!line
->tag
) //jff 2/27/98 all gun generalized types require tag
2017 linefunc
= EV_DoGenFloor
;
2019 else if ((unsigned)line
->special
>= GenCeilingBase
)
2022 if ((line
->special
& CeilingChange
) || !(line
->special
& CeilingModel
))
2023 return; // CeilingModel is "Allow Monsters" if CeilingChange is 0
2024 if (!line
->tag
) //jff 2/27/98 all gun generalized types require tag
2026 linefunc
= EV_DoGenCeiling
;
2028 else if ((unsigned)line
->special
>= GenDoorBase
)
2032 if (!(line
->special
& DoorMonster
))
2033 return; // monsters disallowed from this door
2034 if (line
->flags
& ML_SECRET
) // they can't open secret doors either
2037 if (!line
->tag
) //jff 3/2/98 all gun generalized types require tag
2039 linefunc
= EV_DoGenDoor
;
2041 else if ((unsigned)line
->special
>= GenLockedBase
)
2044 return; // monsters disallowed from unlocking doors
2045 if (((line
->special
&TriggerType
)==GunOnce
) || ((line
->special
&TriggerType
)==GunMany
))
2046 { //jff 4/1/98 check for being a gun type before reporting door type
2047 if (!P_CanUnlockGenDoor(line
,thing
->player
))
2052 if (!line
->tag
) //jff 2/27/98 all gun generalized types require tag
2055 linefunc
= EV_DoGenLockedDoor
;
2057 else if ((unsigned)line
->special
>= GenLiftBase
)
2060 if (!(line
->special
& LiftMonster
))
2061 return; // monsters disallowed
2062 linefunc
= EV_DoGenLift
;
2064 else if ((unsigned)line
->special
>= GenStairsBase
)
2067 if (!(line
->special
& StairMonster
))
2068 return; // monsters disallowed
2069 if (!line
->tag
) //jff 2/27/98 all gun generalized types require tag
2071 linefunc
= EV_DoGenStairs
;
2073 else if ((unsigned)line
->special
>= GenCrusherBase
)
2076 if (!(line
->special
& StairMonster
))
2077 return; // monsters disallowed
2078 if (!line
->tag
) //jff 2/27/98 all gun generalized types require tag
2080 linefunc
= EV_DoGenCrusher
;
2084 switch((line
->special
& TriggerType
) >> TriggerTypeShift
)
2088 P_ChangeSwitchTexture(line
,0);
2092 P_ChangeSwitchTexture(line
,1);
2094 default: // if not a gun type, do nothing here
2099 // Impacts that other things can activate.
2103 switch(line
->special
)
2106 // 46 GR Open door on impact weapon is monster activatable
2114 if (!P_CheckTag(line
)) //jff 2/27/98 disallow zero tag on some types
2117 switch(line
->special
)
2120 // 24 G1 raise floor to highest adjacent
2121 if (EV_DoFloor(line
,raiseFloor
) || demo_compatibility
)
2122 P_ChangeSwitchTexture(line
,0);
2126 // 46 GR open door, stay open
2127 EV_DoDoor(line
,p_open
);
2128 P_ChangeSwitchTexture(line
,1);
2132 // 47 G1 raise floor to nearest and change texture and type
2133 if (EV_DoPlat(line
,raiseToNearestAndChange
,0) || demo_compatibility
)
2134 P_ChangeSwitchTexture(line
,0);
2137 //jff 1/30/98 added new gun linedefs here
2138 // killough 1/31/98: added demo_compatibility check, added inner switch
2141 if (!demo_compatibility
)
2142 switch (line
->special
)
2145 // Exit to next level
2146 // killough 10/98: prevent zombies from exiting levels
2147 if(thing
->player
&& thing
->player
->health
<=0 && !comp
[comp_zombie
])
2149 P_ChangeSwitchTexture(line
,0);
2154 // Exit to secret level
2155 // killough 10/98: prevent zombies from exiting levels
2156 if(thing
->player
&& thing
->player
->health
<=0 && !comp
[comp_zombie
])
2158 P_ChangeSwitchTexture(line
,0);
2159 G_SecretExitLevel();
2161 //jff end addition of new gun linedefs
2169 // P_PlayerInSpecialSector()
2171 // Called every tick frame
2172 // that the player origin is in a special sector
2174 // Changed to ignore sector types the engine does not recognize
2176 void P_PlayerInSpecialSector (player_t
* player
)
2180 sector
= player
->mo
->subsector
->sector
;
2182 // Falling, not all the way down yet?
2183 // Sector specials don't apply in mid-air
2184 if (player
->mo
->z
!= sector
->floorheight
)
2188 //jff add if to handle old vs generalized types
2189 if (sector
->special
<32) // regular sector specials
2191 switch (sector
->special
)
2194 // 5/10 unit damage per 31 ticks
2195 if (!player
->powers
[pw_ironfeet
])
2196 if (!(leveltime
&0x1f))
2197 P_DamageMobj (player
->mo
, NULL
, NULL
, 10);
2201 // 2/5 unit damage per 31 ticks
2202 if (!player
->powers
[pw_ironfeet
])
2203 if (!(leveltime
&0x1f))
2204 P_DamageMobj (player
->mo
, NULL
, NULL
, 5);
2208 // 10/20 unit damage per 31 ticks
2210 // 10/20 unit damage plus blinking light (light already spawned)
2211 if (!player
->powers
[pw_ironfeet
]
2212 || (P_Random(pr_slimehurt
)<5) ) // even with suit, take damage
2214 if (!(leveltime
&0x1f))
2215 P_DamageMobj (player
->mo
, NULL
, NULL
, 20);
2220 // Tally player in secret sector, clear secret special
2221 player
->secretcount
++;
2222 sector
->special
= 0;
2226 // Exit on health < 11, take 10/20 damage per 31 ticks
2227 if (comp
[comp_god
]) /* killough 2/21/98: add compatibility switch */
2228 player
->cheats
&= ~CF_GODMODE
; // on godmode cheat clearing
2229 // does not affect invulnerability
2230 if (!(leveltime
&0x1f))
2231 P_DamageMobj (player
->mo
, NULL
, NULL
, 20);
2233 if (player
->health
<= 10)
2238 //jff 1/24/98 Don't exit as DOOM2 did, just ignore
2242 else //jff 3/14/98 handle extended sector types for secrets and damage
2244 switch ((sector
->special
&DAMAGE_MASK
)>>DAMAGE_SHIFT
)
2246 case 0: // no damage
2248 case 1: // 2/5 damage per 31 ticks
2249 if (!player
->powers
[pw_ironfeet
])
2250 if (!(leveltime
&0x1f))
2251 P_DamageMobj (player
->mo
, NULL
, NULL
, 5);
2253 case 2: // 5/10 damage per 31 ticks
2254 if (!player
->powers
[pw_ironfeet
])
2255 if (!(leveltime
&0x1f))
2256 P_DamageMobj (player
->mo
, NULL
, NULL
, 10);
2258 case 3: // 10/20 damage per 31 ticks
2259 if (!player
->powers
[pw_ironfeet
]
2260 || (P_Random(pr_slimehurt
)<5)) // take damage even with suit
2262 if (!(leveltime
&0x1f))
2263 P_DamageMobj (player
->mo
, NULL
, NULL
, 20);
2267 if (sector
->special
&SECRET_MASK
)
2269 player
->secretcount
++;
2270 sector
->special
&= ~SECRET_MASK
;
2271 if (sector
->special
<32) // if all extended bits clear,
2272 sector
->special
=0; // sector is not special anymore
2277 // If FRICTION_MASK or PUSH_MASK is set, we don't care at this
2278 // point, since the code to deal with those situations is
2279 // handled by Thinkers.
2285 // P_UpdateSpecials()
2287 // Check level timer, frag counter,
2288 // animate flats, scroll walls,
2289 // change button textures
2291 // Reads and modifies globals:
2292 // levelTimer, levelTimeCount,
2293 // levelFragLimit, levelFragLimitCount
2298 boolean levelFragLimit
; // Ty 03/18/98 Added -frags support
2299 int levelFragLimitCount
; // Ty 03/18/98 Added -frags support
2301 void P_UpdateSpecials (void)
2307 // Downcount level timer, exit level if elapsed
2308 if (levelTimer
== true)
2311 if (!levelTimeCount
)
2315 // Check frag counters, if frag limit reached, exit level // Ty 03/18/98
2316 // Seems like the total frags should be kept in a simple
2317 // array somewhere, but until they are...
2318 if (levelFragLimit
== true) // we used -frags so compare count
2320 int k
,m
,fragcount
,exitflag
=false;
2321 for (k
=0;k
<MAXPLAYERS
;k
++)
2323 if (!playeringame
[k
]) continue;
2325 for (m
=0;m
<MAXPLAYERS
;m
++)
2327 if (!playeringame
[m
]) continue;
2328 fragcount
+= (m
!=k
)? players
[k
].frags
[m
] : -players
[k
].frags
[m
];
2330 if (fragcount
>= levelFragLimitCount
) exitflag
= true;
2331 if (exitflag
== true) break; // skip out of the loop--we're done
2333 if (exitflag
== true)
2337 // Animate flats and textures globally
2338 for (anim
= anims
; anim
< lastanim
; anim
++)
2340 for (i
=anim
->basepic
; i
<anim
->basepic
+anim
->numpics
; i
++)
2342 pic
= anim
->basepic
+ ( (leveltime
/anim
->speed
+ i
)%anim
->numpics
);
2343 if (anim
->istexture
)
2344 texturetranslation
[i
] = pic
;
2346 flattranslation
[i
] = pic
;
2350 // Check buttons (retriggerable switches) and change texture on timeout
2351 for (i
= 0; i
< MAXBUTTONS
; i
++)
2352 if (buttonlist
[i
].btimer
)
2354 buttonlist
[i
].btimer
--;
2355 if (!buttonlist
[i
].btimer
)
2357 switch(buttonlist
[i
].where
)
2360 sides
[buttonlist
[i
].line
->sidenum
[0]].toptexture
=
2361 buttonlist
[i
].btexture
;
2365 sides
[buttonlist
[i
].line
->sidenum
[0]].midtexture
=
2366 buttonlist
[i
].btexture
;
2370 sides
[buttonlist
[i
].line
->sidenum
[0]].bottomtexture
=
2371 buttonlist
[i
].btexture
;
2374 S_StartSound((mobj_t
*)&buttonlist
[i
].soundorg
,sfx_swtchn
);
2375 memset(&buttonlist
[i
],0,sizeof(button_t
));
2380 //////////////////////////////////////////////////////////////////////
2382 // Sector and Line special thinker spawning at level startup
2384 //////////////////////////////////////////////////////////////////////
2388 // After the map has been loaded,
2389 // scan for specials that spawn thinkers
2392 // Parses command line parameters.
2393 void P_SpawnSpecials (void)
2398 // See if -timer needs to be used.
2401 i
= M_CheckParm("-avg"); // Austin Virtual Gaming 20 min timer on DM play
2402 if (i
&& deathmatch
)
2405 levelTimeCount
= 20 * 60 * TICRATE
;
2408 i
= M_CheckParm("-timer"); // user defined timer on game play
2409 if (i
&& deathmatch
)
2412 time
= atoi(myargv
[i
+1]) * 60 * TICRATE
;
2414 levelTimeCount
= time
;
2417 // See if -frags has been used
2418 levelFragLimit
= false;
2419 i
= M_CheckParm("-frags"); // Ty 03/18/98 Added -frags support
2420 if (i
&& deathmatch
)
2423 frags
= atoi(myargv
[i
+1]);
2424 if (frags
<= 0) frags
= 10; // default 10 if no count provided
2425 levelFragLimit
= true;
2426 levelFragLimitCount
= frags
;
2430 // Init special sectors.
2432 for (i
=0 ; i
<numsectors
; i
++, sector
++)
2434 if (!sector
->special
)
2437 if (sector
->special
&SECRET_MASK
) //jff 3/15/98 count extended
2438 totalsecret
++; // secret sectors too
2440 switch (sector
->special
&31)
2444 P_SpawnLightFlash (sector
);
2449 P_SpawnStrobeFlash(sector
,FASTDARK
,0);
2454 P_SpawnStrobeFlash(sector
,SLOWDARK
,0);
2458 // strobe fast/death slime
2459 P_SpawnStrobeFlash(sector
,FASTDARK
,0);
2460 sector
->special
|= 3<<DAMAGE_SHIFT
; //jff 3/14/98 put damage bits in
2465 P_SpawnGlowingLight(sector
);
2469 if (sector
->special
<32) //jff 3/14/98 bits don't count unless not
2470 totalsecret
++; // a generalized sector type
2474 // door close in 30 seconds
2475 P_SpawnDoorCloseIn30 (sector
);
2480 P_SpawnStrobeFlash (sector
, SLOWDARK
, 1);
2485 P_SpawnStrobeFlash (sector
, FASTDARK
, 1);
2489 // door raise in 5 minutes
2490 P_SpawnDoorRaiseIn5Mins (sector
, i
);
2495 P_SpawnFireFlicker(sector
);
2500 P_RemoveAllActiveCeilings(); // jff 2/22/98 use killough's scheme
2502 P_RemoveAllActivePlats(); // killough
2504 for (i
= 0;i
< MAXBUTTONS
;i
++)
2505 memset(&buttonlist
[i
],0,sizeof(button_t
));
2507 // P_InitTagLists() must be called before P_FindSectorFromLineTag()
2508 // or P_FindLineFromLineTag() can be called.
2510 P_InitTagLists(); // killough 1/30/98: Create xref tables for tags
2512 P_SpawnScrollers(); // killough 3/7/98: Add generalized scrollers
2514 P_SpawnFriction(); // phares 3/12/98: New friction model using linedefs
2516 P_SpawnPushers(); // phares 3/20/98: New pusher model using linedefs
2518 for (i
=0; i
<numlines
; i
++)
2519 switch (lines
[i
].special
)
2524 // support for drawn heights coming from different sector
2526 sec
= sides
[*lines
[i
].sidenum
].sector
-sectors
;
2527 for (s
= -1; (s
= P_FindSectorFromLineTag(lines
+i
,s
)) >= 0;)
2528 sectors
[s
].heightsec
= sec
;
2531 // killough 3/16/98: Add support for setting
2532 // floor lighting independently (e.g. lava)
2534 sec
= sides
[*lines
[i
].sidenum
].sector
-sectors
;
2535 for (s
= -1; (s
= P_FindSectorFromLineTag(lines
+i
,s
)) >= 0;)
2536 sectors
[s
].floorlightsec
= sec
;
2539 // killough 4/11/98: Add support for setting
2540 // ceiling lighting independently
2542 sec
= sides
[*lines
[i
].sidenum
].sector
-sectors
;
2543 for (s
= -1; (s
= P_FindSectorFromLineTag(lines
+i
,s
)) >= 0;)
2544 sectors
[s
].ceilinglightsec
= sec
;
2549 // Support for sky textures being transferred from sidedefs.
2550 // Allows scrolling and other effects (but if scrolling is
2551 // used, then the same sector tag needs to be used for the
2552 // sky sector, the sky-transfer linedef, and the scroll-effect
2553 // linedef). Still requires user to use F_SKY1 for the floor
2554 // or ceiling texture, to distinguish floor and ceiling sky.
2556 case 271: // Regular sky
2557 case 272: // Same, only flipped
2558 for (s
= -1; (s
= P_FindSectorFromLineTag(lines
+i
,s
)) >= 0;)
2559 sectors
[s
].sky
= i
| PL_SKYFLAT
;
2564 // killough 2/28/98:
2566 // This function, with the help of r_plane.c and r_bsp.c, supports generalized
2567 // scrolling floors and walls, with optional mobj-carrying properties, e.g.
2568 // conveyor belts, rivers, etc. A linedef with a special type affects all
2569 // tagged sectors the same way, by creating scrolling and/or object-carrying
2570 // properties. Multiple linedefs may be used on the same sector and are
2571 // cumulative, although the special case of scrolling a floor and carrying
2572 // things on it, requires only one linedef. The linedef's direction determines
2573 // the scrolling direction, and the linedef's length determines the scrolling
2574 // speed. This was designed so that an edge around the sector could be used to
2575 // control the direction of the sector's scrolling, which is usually what is
2578 // Process the active scrollers.
2580 // This is the main scrolling code
2583 void T_Scroll(scroll_t
*s
)
2585 fixed_t dx
= s
->dx
, dy
= s
->dy
;
2587 if (s
->control
!= -1)
2588 { // compute scroll amounts based on a sector's height changes
2589 fixed_t height
= sectors
[s
->control
].floorheight
+
2590 sectors
[s
->control
].ceilingheight
;
2591 fixed_t delta
= height
- s
->last_height
;
2592 s
->last_height
= height
;
2593 dx
= FixedMul(dx
, delta
);
2594 dy
= FixedMul(dy
, delta
);
2597 // killough 3/14/98: Add acceleration
2600 s
->vdx
= dx
+= s
->vdx
;
2601 s
->vdy
= dy
+= s
->vdy
;
2604 if (!(dx
| dy
)) // no-op if both (x,y) offsets 0
2611 fixed_t height
, waterheight
; // killough 4/4/98: add waterheight
2615 case sc_side
: // killough 3/7/98: Scroll wall texture
2616 side
= sides
+ s
->affectee
;
2617 side
->textureoffset
+= dx
;
2618 side
->rowoffset
+= dy
;
2621 case sc_floor
: // killough 3/7/98: Scroll floor texture
2622 sec
= sectors
+ s
->affectee
;
2623 sec
->floor_xoffs
+= dx
;
2624 sec
->floor_yoffs
+= dy
;
2627 case sc_ceiling
: // killough 3/7/98: Scroll ceiling texture
2628 sec
= sectors
+ s
->affectee
;
2629 sec
->ceiling_xoffs
+= dx
;
2630 sec
->ceiling_yoffs
+= dy
;
2635 // killough 3/7/98: Carry things on floor
2636 // killough 3/20/98: use new sector list which reflects true members
2637 // killough 3/27/98: fix carrier bug
2638 // killough 4/4/98: Underwater, carry things even w/o gravity
2640 sec
= sectors
+ s
->affectee
;
2641 height
= sec
->floorheight
;
2642 waterheight
= sec
->heightsec
!= -1 &&
2643 sectors
[sec
->heightsec
].floorheight
> height
?
2644 sectors
[sec
->heightsec
].floorheight
: INT_MIN
;
2646 for (node
= sec
->touching_thinglist
; node
; node
= node
->m_snext
)
2647 if (!((thing
= node
->m_thing
)->flags
& MF_NOCLIP
) &&
2648 (!(thing
->flags
& MF_NOGRAVITY
|| thing
->z
> height
) ||
2649 thing
->z
< waterheight
))
2651 // Move objects only if on floor or underwater,
2652 // non-floating, and clipped.
2658 case sc_carry_ceiling
: // to be added later
2666 // Add a generalized scroller to the thinker list.
2668 // type: the enumerated type of scrolling: floor, ceiling, floor carrier,
2669 // wall, floor carrier & scroller
2671 // (dx,dy): the direction and speed of the scrolling or its acceleration
2673 // control: the sector whose heights control this scroller's effect
2674 // remotely, or -1 if no control sector
2676 // affectee: the index of the affected object (sector or sidedef)
2678 // accel: non-zero if this is an accelerative effect
2681 static void Add_Scroller(int type
, fixed_t dx
, fixed_t dy
,
2682 int control
, int affectee
, int accel
)
2684 scroll_t
*s
= Z_Malloc(sizeof *s
, PU_LEVSPEC
, 0);
2685 s
->thinker
.function
= T_Scroll
;
2690 s
->vdx
= s
->vdy
= 0;
2691 if ((s
->control
= control
) != -1)
2693 sectors
[control
].floorheight
+ sectors
[control
].ceilingheight
;
2694 s
->affectee
= affectee
;
2695 P_AddThinker(&s
->thinker
);
2698 // Adds wall scroller. Scroll amount is rotated with respect to wall's
2699 // linedef first, so that scrolling towards the wall in a perpendicular
2700 // direction is translated into vertical motion, while scrolling along
2701 // the wall in a parallel direction is translated into horizontal motion.
2703 // killough 5/25/98: cleaned up arithmetic to avoid drift due to roundoff
2706 // fix scrolling aliasing problems, caused by long linedefs causing overflowing
2708 static void Add_WallScroller(fixed_t dx
, fixed_t dy
, const line_t
*l
,
2709 int control
, int accel
)
2711 fixed_t x
= D_abs(l
->dx
), y
= D_abs(l
->dy
), d
;
2713 d
= x
, x
= y
, y
= d
;
2714 d
= FixedDiv(x
, finesine
[(tantoangle
[FixedDiv(y
,x
) >> DBITS
] + ANG90
)
2715 >> ANGLETOFINESHIFT
]);
2717 // CPhipps - Import scroller calc overflow fix, compatibility optioned
2718 if (compatibility_level
>= lxdoom_1_compatibility
) {
2719 x
= (fixed_t
)(((int_64_t
)dy
* -(int_64_t
)l
->dy
- (int_64_t
)dx
* (int_64_t
)l
->dx
) / (int_64_t
)d
); // killough 10/98:
2720 y
= (fixed_t
)(((int_64_t
)dy
* (int_64_t
)l
->dx
- (int_64_t
)dx
* (int_64_t
)l
->dy
) / (int_64_t
)d
); // Use long long arithmetic
2722 x
= -FixedDiv(FixedMul(dy
, l
->dy
) + FixedMul(dx
, l
->dx
), d
);
2723 y
= -FixedDiv(FixedMul(dx
, l
->dy
) - FixedMul(dy
, l
->dx
), d
);
2725 Add_Scroller(sc_side
, x
, y
, control
, *l
->sidenum
, accel
);
2728 // Amount (dx,dy) vector linedef is shifted right to get scroll amount
2729 #define SCROLL_SHIFT 5
2731 // Factor to scale scrolling effect into mobj-carrying properties = 3/32.
2732 // (This is so scrolling floors and objects on them can move at same speed.)
2733 #define CARRYFACTOR ((fixed_t)(FRACUNIT*.09375))
2735 // Initialize the scrollers
2736 static void P_SpawnScrollers(void)
2741 for (i
=0;i
<numlines
;i
++,l
++)
2743 fixed_t dx
= l
->dx
>> SCROLL_SHIFT
; // direction and speed of scrolling
2744 fixed_t dy
= l
->dy
>> SCROLL_SHIFT
;
2745 int control
= -1, accel
= 0; // no control sector or acceleration
2746 int special
= l
->special
;
2748 // killough 3/7/98: Types 245-249 are same as 250-254 except that the
2749 // first side's sector's heights cause scrolling when they change, and
2750 // this linedef controls the direction and speed of the scrolling. The
2751 // most complicated linedef since donuts, but powerful :)
2753 // killough 3/15/98: Add acceleration. Types 214-218 are the same but
2754 // are accelerative.
2756 if (special
>= 245 && special
<= 249) // displacement scrollers
2759 control
= sides
[*l
->sidenum
].sector
- sectors
;
2762 if (special
>= 214 && special
<= 218) // accelerative scrollers
2766 control
= sides
[*l
->sidenum
].sector
- sectors
;
2773 case 250: // scroll effect ceiling
2774 for (s
=-1; (s
= P_FindSectorFromLineTag(l
,s
)) >= 0;)
2775 Add_Scroller(sc_ceiling
, -dx
, dy
, control
, s
, accel
);
2778 case 251: // scroll effect floor
2779 case 253: // scroll and carry objects on floor
2780 for (s
=-1; (s
= P_FindSectorFromLineTag(l
,s
)) >= 0;)
2781 Add_Scroller(sc_floor
, -dx
, dy
, control
, s
, accel
);
2785 case 252: // carry objects on floor
2786 dx
= FixedMul(dx
,CARRYFACTOR
);
2787 dy
= FixedMul(dy
,CARRYFACTOR
);
2788 for (s
=-1; (s
= P_FindSectorFromLineTag(l
,s
)) >= 0;)
2789 Add_Scroller(sc_carry
, dx
, dy
, control
, s
, accel
);
2792 // killough 3/1/98: scroll wall according to linedef
2793 // (same direction and speed as scrolling floors)
2795 for (s
=-1; (s
= P_FindLineFromLineTag(l
,s
)) >= 0;)
2797 Add_WallScroller(dx
, dy
, lines
+s
, control
, accel
);
2800 case 255: // killough 3/2/98: scroll according to sidedef offsets
2801 s
= lines
[i
].sidenum
[0];
2802 Add_Scroller(sc_side
, -sides
[s
].textureoffset
,
2803 sides
[s
].rowoffset
, -1, s
, accel
);
2806 case 48: // scroll first side
2807 Add_Scroller(sc_side
, FRACUNIT
, 0, -1, lines
[i
].sidenum
[0], accel
);
2810 case 85: // jff 1/30/98 2-way scroll
2811 Add_Scroller(sc_side
, -FRACUNIT
, 0, -1, lines
[i
].sidenum
[0], accel
);
2817 // killough 3/7/98 -- end generalized scroll effects
2819 ////////////////////////////////////////////////////////////////////////////
2823 // phares 3/12/98: Start of friction effects
2825 // As the player moves, friction is applied by decreasing the x and y
2826 // momentum values on each tic. By varying the percentage of decrease,
2827 // we can simulate muddy or icy conditions. In mud, the player slows
2828 // down faster. In ice, the player slows down more slowly.
2830 // The amount of friction change is controlled by the length of a linedef
2831 // with type 223. A length < 100 gives you mud. A length > 100 gives you ice.
2833 // Also, each sector where these effects are to take place is given a
2834 // new special type _______. Changing the type value at runtime allows
2835 // these effects to be turned on or off.
2837 // Sector boundaries present problems. The player should experience these
2838 // friction changes only when his feet are touching the sector floor. At
2839 // sector boundaries where floor height changes, the player can find
2840 // himself still 'in' one sector, but with his feet at the floor level
2841 // of the next sector (steps up or down). To handle this, Thinkers are used
2842 // in icy/muddy sectors. These thinkers examine each object that is touching
2843 // their sectors, looking for players whose feet are at the same level as
2844 // their floors. Players satisfying this condition are given new friction
2845 // values that are applied by the player movement code later.
2847 // killough 8/28/98:
2849 // Completely redid code, which did not need thinkers, and which put a heavy
2850 // drag on CPU. Friction is now a property of sectors, NOT objects inside
2851 // them. All objects, not just players, are affected by it, if they touch
2852 // the sector's floor. Code simpler and faster, only calling on friction
2853 // calculations when an object needs friction considered, instead of doing
2854 // friction calculations on every sector during every tic.
2856 // Although this -might- ruin Boom demo sync involving friction, it's the only
2857 // way, short of code explosion, to fix the original design bug. Fixing the
2858 // design bug in Boom's original friction code, while maintaining demo sync
2859 // under every conceivable circumstance, would double or triple code size, and
2860 // would require maintenance of buggy legacy code which is only useful for old
2861 // demos. Doom demos, which are more important IMO, are not affected by this
2864 /////////////////////////////
2866 // Initialize the sectors where friction is increased or decreased
2868 static void P_SpawnFriction(void)
2873 // killough 8/28/98: initialize all sectors to normal friction first
2874 for (i
= 0; i
< numsectors
; i
++)
2876 sectors
[i
].friction
= ORIG_FRICTION
;
2877 sectors
[i
].movefactor
= ORIG_FRICTION_FACTOR
;
2880 for (i
= 0 ; i
< numlines
; i
++,l
++)
2881 if (l
->special
== 223)
2883 int length
= P_AproxDistance(l
->dx
,l
->dy
)>>FRACBITS
;
2884 int friction
= (0x1EB8*length
)/0x80 + 0xD000;
2887 // The following check might seem odd. At the time of movement,
2888 // the move distance is multiplied by 'friction/0x10000', so a
2889 // higher friction value actually means 'less friction'.
2891 if (friction
> ORIG_FRICTION
) // ice
2892 movefactor
= ((0x10092 - friction
)*(0x70))/0x158;
2894 movefactor
= ((friction
- 0xDB34)*(0xA))/0x80;
2897 { // killough 8/28/98: prevent odd situations
2898 if (friction
> FRACUNIT
)
2899 friction
= FRACUNIT
;
2902 if (movefactor
< 32)
2906 for (s
= -1; (s
= P_FindSectorFromLineTag(l
,s
)) >= 0 ; )
2908 // killough 8/28/98:
2910 // Instead of spawning thinkers, which are slow and expensive,
2911 // modify the sector's own friction values. Friction should be
2912 // a property of sectors, not objects which reside inside them.
2913 // Original code scanned every object in every friction sector
2914 // on every tic, adjusting its friction, putting unnecessary
2915 // drag on CPU. New code adjusts friction of sector only once
2916 // at level startup, and then uses this friction value.
2918 sectors
[s
].friction
= friction
;
2919 sectors
[s
].movefactor
= movefactor
;
2925 // phares 3/12/98: End of friction effects
2927 ////////////////////////////////////////////////////////////////////////////
2929 ////////////////////////////////////////////////////////////////////////////
2933 // phares 3/20/98: Start of push/pull effects
2935 // This is where push/pull effects are applied to objects in the sectors.
2937 // There are four kinds of push effects
2941 // Pushes you away from a point source defined by the location of an
2942 // MT_PUSH Thing. The force decreases linearly with distance from the
2943 // source. This force crosses sector boundaries and is felt w/in a circle
2944 // whose center is at the MT_PUSH. The force is felt only if the point
2945 // MT_PUSH can see the target object.
2947 // 2) Pulling toward
2949 // Same as Pushing Away except you're pulled toward an MT_PULL point
2950 // source. This force crosses sector boundaries and is felt w/in a circle
2951 // whose center is at the MT_PULL. The force is felt only if the point
2952 // MT_PULL can see the target object.
2956 // Pushes you in a constant direction. Full force above ground, half
2957 // force on the ground, nothing if you're below it (water).
2961 // Pushes you in a constant direction. No force above ground, full
2962 // force if on the ground or below it (water).
2964 // The magnitude of the force is controlled by the length of a controlling
2965 // linedef. The force vector for types 3 & 4 is determined by the angle
2966 // of the linedef, and is constant.
2968 // For each sector where these effects occur, the sector special type has
2969 // to have the PUSH_MASK bit set. If this bit is turned off by a switch
2970 // at run-time, the effect will not occur. The controlling sector for
2971 // types 1 & 2 is the sector containing the MT_PUSH/MT_PULL Thing.
2974 #define PUSH_FACTOR 7
2976 /////////////////////////////
2978 // Add a push thinker to the thinker list
2980 static void Add_Pusher(int type
, int x_mag
, int y_mag
, mobj_t
* source
, int affectee
)
2982 pusher_t
*p
= Z_Malloc(sizeof *p
, PU_LEVSPEC
, 0);
2984 p
->thinker
.function
= T_Pusher
;
2987 p
->x_mag
= x_mag
>>FRACBITS
;
2988 p
->y_mag
= y_mag
>>FRACBITS
;
2989 p
->magnitude
= P_AproxDistance(p
->x_mag
,p
->y_mag
);
2990 if (source
) // point source exist?
2992 p
->radius
= (p
->magnitude
)<<(FRACBITS
+1); // where force goes to zero
2993 p
->x
= p
->source
->x
;
2994 p
->y
= p
->source
->y
;
2996 p
->affectee
= affectee
;
2997 P_AddThinker(&p
->thinker
);
3000 /////////////////////////////
3002 // PIT_PushThing determines the angle and magnitude of the effect.
3003 // The object's x and y momentum values are changed.
3005 // tmpusher belongs to the point source (MT_PUSH/MT_PULL).
3007 // killough 10/98: allow to affect things besides players
3009 pusher_t
* tmpusher
; // pusher structure for blockmap searches
3011 boolean
PIT_PushThing(mobj_t
* thing
)
3013 /* killough 10/98: made more general */
3015 thing
->player
&& !(thing
->flags
& (MF_NOCLIP
| MF_NOGRAVITY
)) :
3016 (sentient(thing
) || thing
->flags
& MF_SHOOTABLE
) &&
3017 !(thing
->flags
& MF_NOCLIP
))
3021 fixed_t sx
= tmpusher
->x
;
3022 fixed_t sy
= tmpusher
->y
;
3024 speed
= (tmpusher
->magnitude
-
3025 ((P_AproxDistance(thing
->x
- sx
,thing
->y
- sy
)
3026 >>FRACBITS
)>>1))<<(FRACBITS
-PUSH_FACTOR
-1);
3028 // killough 10/98: make magnitude decrease with square
3029 // of distance, making it more in line with real nature,
3030 // so long as it's still in range with original formula.
3032 // Removes angular distortion, and makes effort required
3033 // to stay close to source, grow increasingly hard as you
3034 // get closer, as expected. Still, it doesn't consider z :(
3036 if (speed
> 0 && mbf_features
)
3038 int x
= (thing
->x
-sx
) >> FRACBITS
;
3039 int y
= (thing
->y
-sy
) >> FRACBITS
;
3040 speed
= (int)(((uint_64_t
) tmpusher
->magnitude
<< 23) / (x
*x
+y
*y
+1));
3043 // If speed <= 0, you're outside the effective radius. You also have
3044 // to be able to see the push/pull source point.
3046 if (speed
> 0 && P_CheckSight(thing
,tmpusher
->source
))
3048 pushangle
= R_PointToAngle2(thing
->x
,thing
->y
,sx
,sy
);
3049 if (tmpusher
->source
->type
== MT_PUSH
)
3050 pushangle
+= ANG180
; // away
3051 pushangle
>>= ANGLETOFINESHIFT
;
3052 thing
->momx
+= FixedMul(speed
,finecosine
[pushangle
]);
3053 thing
->momy
+= FixedMul(speed
,finesine
[pushangle
]);
3059 /////////////////////////////
3061 // T_Pusher looks for all objects that are inside the radius of
3065 void T_Pusher(pusher_t
*p
)
3071 int xl
,xh
,yl
,yh
,bx
,by
;
3078 sec
= sectors
+ p
->affectee
;
3080 // Be sure the special sector type is still turned on. If so, proceed.
3081 // Else, bail out; the sector type has been changed on us.
3083 if (!(sec
->special
& PUSH_MASK
))
3086 // For constant pushers (wind/current) there are 3 situations:
3088 // 1) Affected Thing is above the floor.
3090 // Apply the full force if wind, no force if current.
3092 // 2) Affected Thing is on the ground.
3094 // Apply half force if wind, full force if current.
3096 // 3) Affected Thing is below the ground (underwater effect).
3098 // Apply no force if wind, full force if current.
3100 if (p
->type
== p_push
)
3103 // Seek out all pushable things within the force radius of this
3104 // point pusher. Crosses sectors, so use blockmap.
3106 tmpusher
= p
; // MT_PUSH/MT_PULL point source
3107 radius
= p
->radius
; // where force goes to zero
3108 tmbbox
[BOXTOP
] = p
->y
+ radius
;
3109 tmbbox
[BOXBOTTOM
] = p
->y
- radius
;
3110 tmbbox
[BOXRIGHT
] = p
->x
+ radius
;
3111 tmbbox
[BOXLEFT
] = p
->x
- radius
;
3113 xl
= (tmbbox
[BOXLEFT
] - bmaporgx
- MAXRADIUS
)>>MAPBLOCKSHIFT
;
3114 xh
= (tmbbox
[BOXRIGHT
] - bmaporgx
+ MAXRADIUS
)>>MAPBLOCKSHIFT
;
3115 yl
= (tmbbox
[BOXBOTTOM
] - bmaporgy
- MAXRADIUS
)>>MAPBLOCKSHIFT
;
3116 yh
= (tmbbox
[BOXTOP
] - bmaporgy
+ MAXRADIUS
)>>MAPBLOCKSHIFT
;
3117 for (bx
=xl
; bx
<=xh
; bx
++)
3118 for (by
=yl
; by
<=yh
; by
++)
3119 P_BlockThingsIterator(bx
,by
,PIT_PushThing
);
3123 // constant pushers p_wind and p_current
3125 if (sec
->heightsec
!= -1) // special water sector?
3126 ht
= sectors
[sec
->heightsec
].floorheight
;
3127 node
= sec
->touching_thinglist
; // things touching this sector
3128 for ( ; node
; node
= node
->m_snext
)
3130 thing
= node
->m_thing
;
3131 if (!thing
->player
|| (thing
->flags
& (MF_NOGRAVITY
| MF_NOCLIP
)))
3133 if (p
->type
== p_wind
)
3135 if (sec
->heightsec
== -1) // NOT special water sector
3136 if (thing
->z
> thing
->floorz
) // above ground
3138 xspeed
= p
->x_mag
; // full force
3143 xspeed
= (p
->x_mag
)>>1; // half force
3144 yspeed
= (p
->y_mag
)>>1;
3146 else // special water sector
3148 if (thing
->z
> ht
) // above ground
3150 xspeed
= p
->x_mag
; // full force
3153 else if (thing
->player
->viewz
< ht
) // underwater
3154 xspeed
= yspeed
= 0; // no force
3155 else // wading in water
3157 xspeed
= (p
->x_mag
)>>1; // half force
3158 yspeed
= (p
->y_mag
)>>1;
3164 if (sec
->heightsec
== -1) // NOT special water sector
3165 if (thing
->z
> sec
->floorheight
) // above ground
3166 xspeed
= yspeed
= 0; // no force
3169 xspeed
= p
->x_mag
; // full force
3172 else // special water sector
3173 if (thing
->z
> ht
) // above ground
3174 xspeed
= yspeed
= 0; // no force
3177 xspeed
= p
->x_mag
; // full force
3181 thing
->momx
+= xspeed
<<(FRACBITS
-PUSH_FACTOR
);
3182 thing
->momy
+= yspeed
<<(FRACBITS
-PUSH_FACTOR
);
3186 /////////////////////////////
3188 // P_GetPushThing() returns a pointer to an MT_PUSH or MT_PULL thing,
3191 mobj_t
* P_GetPushThing(int s
)
3197 thing
= sec
->thinglist
;
3208 thing
= thing
->snext
;
3213 /////////////////////////////
3215 // Initialize the sectors where pushers are present
3218 static void P_SpawnPushers(void)
3225 for (i
= 0 ; i
< numlines
; i
++,l
++)
3229 for (s
= -1; (s
= P_FindSectorFromLineTag(l
,s
)) >= 0 ; )
3230 Add_Pusher(p_wind
,l
->dx
,l
->dy
,NULL
,s
);
3232 case 225: // current
3233 for (s
= -1; (s
= P_FindSectorFromLineTag(l
,s
)) >= 0 ; )
3234 Add_Pusher(p_current
,l
->dx
,l
->dy
,NULL
,s
);
3236 case 226: // push/pull
3237 for (s
= -1; (s
= P_FindSectorFromLineTag(l
,s
)) >= 0 ; )
3239 thing
= P_GetPushThing(s
);
3240 if (thing
) // No MT_P* means no effect
3241 Add_Pusher(p_push
,l
->dx
,l
->dy
,thing
,s
);
3248 // phares 3/20/98: End of Pusher effects
3250 ////////////////////////////////////////////////////////////////////////////