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.
11 //
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.
16 //
17 // DESCRIPTION:  none
18 //		Implements special effects:
19 //		Texture animation, height or lighting changes
20 //		 according to adjacent sectors, respective
21 //		 utility functions, etc.
22 //
23 //-----------------------------------------------------------------------------
24 
25 #ifndef __P_SPEC__
26 #define __P_SPEC__
27 
28 #include "dsectoreffect.h"
29 #include "doomdata.h"
30 #include "r_state.h"
31 
32 class FScanner;
33 struct level_info_t;
34 
35 //jff 2/23/98 identify the special classes that can share sectors
36 
37 typedef enum
38 {
39 	floor_special,
40 	ceiling_special,
41 	lighting_special,
42 } special_e;
43 
44 // killough 3/7/98: Add generalized scroll effects
45 
46 class DScroller : public DThinker
47 {
48 	DECLARE_CLASS (DScroller, DThinker)
49 	HAS_OBJECT_POINTERS
50 public:
51 	enum EScrollType
52 	{
53 		sc_side,
54 		sc_floor,
55 		sc_ceiling,
56 		sc_carry,
57 		sc_carry_ceiling,	// killough 4/11/98: carry objects hanging on ceilings
58 	};
59 	enum EScrollPos
60 	{
61 		scw_top=1,
62 		scw_mid=2,
63 		scw_bottom=4,
64 		scw_all=7,
65 	};
66 
67 	DScroller (EScrollType type, fixed_t dx, fixed_t dy, int control, int affectee, int accel, int scrollpos = scw_all);
68 	DScroller (fixed_t dx, fixed_t dy, const line_t *l, int control, int accel, int scrollpos = scw_all);
69 	void Destroy();
70 
71 	void Serialize (FArchive &arc);
72 	void Tick ();
73 
AffectsWall(int wallnum)74 	bool AffectsWall (int wallnum) const { return m_Type == sc_side && m_Affectee == wallnum; }
GetWallNum()75 	int GetWallNum () const { return m_Type == sc_side ? m_Affectee : -1; }
SetRate(fixed_t dx,fixed_t dy)76 	void SetRate (fixed_t dx, fixed_t dy) { m_dx = dx; m_dy = dy; }
IsType(EScrollType type)77 	bool IsType (EScrollType type) const { return type == m_Type; }
GetAffectee()78 	int GetAffectee () const { return m_Affectee; }
GetScrollParts()79 	int GetScrollParts() const { return m_Parts; }
80 
81 protected:
82 	EScrollType m_Type;		// Type of scroll effect
83 	fixed_t m_dx, m_dy;		// (dx,dy) scroll speeds
84 	int m_Affectee;			// Number of affected sidedef, sector, tag, or whatever
85 	int m_Control;			// Control sector (-1 if none) used to control scrolling
86 	fixed_t m_LastHeight;	// Last known height of control sector
87 	fixed_t m_vdx, m_vdy;	// Accumulated velocity if accelerative
88 	int m_Accel;			// Whether it's accelerative
89 	int m_Parts;			// Which parts of a sidedef are being scrolled?
90 	TObjPtr<DInterpolation> m_Interpolations[3];
91 
92 private:
93 	DScroller ();
94 };
95 
96 // Factor to scale scrolling effect into mobj-carrying properties = 3/32.
97 // (This is so scrolling floors and objects on them can move at same speed.)
98 enum { CARRYFACTOR = (3*FRACUNIT >> 5) };
99 
100 // phares 3/20/98: added new model of Pushers for push/pull effects
101 
102 class DPusher : public DThinker
103 {
104 	DECLARE_CLASS (DPusher, DThinker)
105 	HAS_OBJECT_POINTERS
106 public:
107 	enum EPusher
108 	{
109 		p_push,
110 		p_pull,
111 		p_wind,
112 		p_current
113 	};
114 
115 	DPusher ();
116 	DPusher (EPusher type, line_t *l, int magnitude, int angle, AActor *source, int affectee);
117 	void Serialize (FArchive &arc);
118 	int CheckForSectorMatch (EPusher type, int tag);
ChangeValues(int magnitude,int angle)119 	void ChangeValues (int magnitude, int angle)
120 	{
121 		angle_t ang = ((angle_t)(angle<<24)) >> ANGLETOFINESHIFT;
122 		m_Xmag = (magnitude * finecosine[ang]) >> FRACBITS;
123 		m_Ymag = (magnitude * finesine[ang]) >> FRACBITS;
124 		m_Magnitude = magnitude;
125 	}
126 
127 	void Tick ();
128 
129 protected:
130 	EPusher m_Type;
131 	TObjPtr<AActor> m_Source;// Point source if point pusher
132 	int m_Xmag;				// X Strength
133 	int m_Ymag;				// Y Strength
134 	int m_Magnitude;		// Vector strength for point pusher
135 	int m_Radius;			// Effective radius for point pusher
136 	int m_X;				// X of point source if point pusher
137 	int m_Y;				// Y of point source if point pusher
138 	int m_Affectee;			// Number of affected sector
139 
140 	friend bool PIT_PushThing (AActor *thing);
141 };
142 
143 bool PIT_PushThing (AActor *thing);
144 
145 // Define values for map objects
146 #define MO_TELEPORTMAN			14
147 
148 // Flags for P_SectorDamage
149 #define DAMAGE_PLAYERS				1
150 #define DAMAGE_NONPLAYERS			2
151 #define DAMAGE_IN_AIR				4
152 #define DAMAGE_SUBCLASSES_PROTECT	8
153 
154 
155 // [RH] If a deathmatch game, checks to see if noexit is enabled.
156 //		If so, it kills the player and returns false. Otherwise,
157 //		it returns true, and the player is allowed to live.
158 bool	CheckIfExitIsGood (AActor *self, level_info_t *info);
159 
160 // at map load
161 void P_InitSectorSpecial(sector_t *sector, int special, bool nothinkers);
162 void	P_SpawnSpecials (void);
163 
164 // every tic
165 void	P_UpdateSpecials (void);
166 
167 // when needed
168 bool	P_ActivateLine (line_t *ld, AActor *mo, int side, int activationType);
169 bool	P_TestActivateLine (line_t *ld, AActor *mo, int side, int activationType);
170 bool	P_PredictLine (line_t *ld, AActor *mo, int side, int activationType);
171 
172 void 	P_PlayerInSpecialSector (player_t *player, sector_t * sector=NULL);
173 void	P_PlayerOnSpecialFlat (player_t *player, int floorType);
174 void	P_SectorDamage(int tag, int amount, FName type, const PClass *protectClass, int flags);
175 void	P_SetSectorFriction (int tag, int amount, bool alterFlag);
176 
FrictionToMoveFactor(fixed_t friction)177 inline fixed_t FrictionToMoveFactor(fixed_t friction)
178 {
179 	fixed_t movefactor;
180 
181 	// [RH] Twiddled these values so that velocity on ice (with
182 	//		friction 0xf900) is the same as in Heretic/Hexen.
183 	if (friction >= ORIG_FRICTION)	// ice
184 //		movefactor = ((0x10092 - friction)*(0x70))/0x158;
185 		movefactor = ((0x10092 - friction) * 1024) / 4352 + 568;
186 	else
187 		movefactor = ((friction - 0xDB34)*(0xA))/0x80;
188 
189 	// killough 8/28/98: prevent odd situations
190 	if (movefactor < 32)
191 		movefactor = 32;
192 
193 	return movefactor;
194 }
195 
196 void P_GiveSecret(AActor *actor, bool printmessage, bool playsound, int sectornum);
197 
198 //
199 // getSide()
200 // Will return a side_t*
201 //	given the number of the current sector,
202 //	the line number, and the side (0/1) that you want.
203 //
getSide(int currentSector,int line,int side)204 inline side_t *getSide (int currentSector, int line, int side)
205 {
206 	return (sectors[currentSector].lines[line])->sidedef[side];
207 }
208 
209 //
210 // getSector()
211 // Will return a sector_t*
212 //	given the number of the current sector,
213 //	the line number and the side (0/1) that you want.
214 //
getSector(int currentSector,int line,int side)215 inline sector_t *getSector (int currentSector, int line, int side)
216 {
217 	return (sectors[currentSector].lines[line])->sidedef[side]->sector;
218 }
219 
220 
221 //
222 // twoSided()
223 // Given the sector number and the line number,
224 //	it will tell you whether the line is two-sided or not.
225 //
twoSided(int sector,int line)226 inline int twoSided (int sector, int line)
227 {
228 	return (sectors[sector].lines[line])->flags & ML_TWOSIDED;
229 }
230 
231 //
232 // getNextSector()
233 // Return sector_t * of sector next to current.
234 // NULL if not two-sided line
235 //
getNextSector(line_t * line,const sector_t * sec)236 inline sector_t *getNextSector (line_t *line, const sector_t *sec)
237 {
238 	if (!(line->flags & ML_TWOSIDED))
239 		return NULL;
240 
241 	return line->frontsector == sec ?
242 		   (line->backsector != sec ? line->backsector : NULL) :
243 	       line->frontsector;
244 }
245 
246 
247 #include "p_tags.h"
248 
249 //
250 // P_LIGHTS
251 //
252 
253 class DLighting : public DSectorEffect
254 {
255 	DECLARE_CLASS (DLighting, DSectorEffect)
256 public:
257 	DLighting (sector_t *sector);
258 protected:
259 	DLighting ();
260 };
261 
262 class DFireFlicker : public DLighting
263 {
264 	DECLARE_CLASS (DFireFlicker, DLighting)
265 public:
266 	DFireFlicker (sector_t *sector);
267 	DFireFlicker (sector_t *sector, int upper, int lower);
268 	void		Serialize (FArchive &arc);
269 	void		Tick ();
270 protected:
271 	int 		m_Count;
272 	int 		m_MaxLight;
273 	int 		m_MinLight;
274 private:
275 	DFireFlicker ();
276 };
277 
278 class DFlicker : public DLighting
279 {
280 	DECLARE_CLASS (DFlicker, DLighting)
281 public:
282 	DFlicker (sector_t *sector, int upper, int lower);
283 	void		Serialize (FArchive &arc);
284 	void		Tick ();
285 protected:
286 	int 		m_Count;
287 	int 		m_MaxLight;
288 	int 		m_MinLight;
289 private:
290 	DFlicker ();
291 };
292 
293 class DLightFlash : public DLighting
294 {
295 	DECLARE_CLASS (DLightFlash, DLighting)
296 public:
297 	DLightFlash (sector_t *sector);
298 	DLightFlash (sector_t *sector, int min, int max);
299 	void		Serialize (FArchive &arc);
300 	void		Tick ();
301 protected:
302 	int 		m_Count;
303 	int 		m_MaxLight;
304 	int 		m_MinLight;
305 	int 		m_MaxTime;
306 	int 		m_MinTime;
307 private:
308 	DLightFlash ();
309 };
310 
311 class DStrobe : public DLighting
312 {
313 	DECLARE_CLASS (DStrobe, DLighting)
314 public:
315 	DStrobe (sector_t *sector, int utics, int ltics, bool inSync);
316 	DStrobe (sector_t *sector, int upper, int lower, int utics, int ltics);
317 	void		Serialize (FArchive &arc);
318 	void		Tick ();
319 protected:
320 	int 		m_Count;
321 	int 		m_MinLight;
322 	int 		m_MaxLight;
323 	int 		m_DarkTime;
324 	int 		m_BrightTime;
325 private:
326 	DStrobe ();
327 };
328 
329 class DGlow : public DLighting
330 {
331 	DECLARE_CLASS (DGlow, DLighting)
332 public:
333 	DGlow (sector_t *sector);
334 	void		Serialize (FArchive &arc);
335 	void		Tick ();
336 protected:
337 	int 		m_MinLight;
338 	int 		m_MaxLight;
339 	int 		m_Direction;
340 private:
341 	DGlow ();
342 };
343 
344 // [RH] Glow from Light_Glow and Light_Fade specials
345 class DGlow2 : public DLighting
346 {
347 	DECLARE_CLASS (DGlow2, DLighting)
348 public:
349 	DGlow2 (sector_t *sector, int start, int end, int tics, bool oneshot);
350 	void		Serialize (FArchive &arc);
351 	void		Tick ();
352 protected:
353 	int			m_Start;
354 	int			m_End;
355 	int			m_MaxTics;
356 	int			m_Tics;
357 	bool		m_OneShot;
358 private:
359 	DGlow2 ();
360 };
361 
362 // [RH] Phased light thinker
363 class DPhased : public DLighting
364 {
365 	DECLARE_CLASS (DPhased, DLighting)
366 public:
367 	DPhased (sector_t *sector);
368 	DPhased (sector_t *sector, int baselevel, int phase);
369 	void		Serialize (FArchive &arc);
370 	void		Tick ();
371 protected:
372 	BYTE		m_BaseLevel;
373 	BYTE		m_Phase;
374 private:
375 	DPhased ();
376 	DPhased (sector_t *sector, int baselevel);
377 	int PhaseHelper (sector_t *sector, int index, int light, sector_t *prev);
378 };
379 
380 #define GLOWSPEED				8
381 #define STROBEBRIGHT			5
382 #define FASTDARK				15
383 #define SLOWDARK				TICRATE
384 
385 void	EV_StartLightFlickering (int tag, int upper, int lower);
386 void	EV_StartLightStrobing (int tag, int upper, int lower, int utics, int ltics);
387 void	EV_StartLightStrobing (int tag, int utics, int ltics);
388 void	EV_TurnTagLightsOff (int tag);
389 void	EV_LightTurnOn (int tag, int bright);
390 void	EV_LightTurnOnPartway (int tag, fixed_t frac);	// killough 10/98
391 void	EV_LightChange (int tag, int value);
392 void	EV_StopLightEffect (int tag);
393 
394 void	P_SpawnGlowingLight (sector_t *sector);
395 
396 void	EV_StartLightGlowing (int tag, int upper, int lower, int tics);
397 void	EV_StartLightFading (int tag, int value, int tics);
398 
399 
400 //
401 // P_SWITCH
402 //
403 
404 #define BUTTONTIME TICRATE		// 1 second, in ticks.
405 
406 bool	P_ChangeSwitchTexture (side_t *side, int useAgain, BYTE special, bool *quest=NULL);
407 bool	P_CheckSwitchRange(AActor *user, line_t *line, int sideno);
408 
409 //
410 // P_PLATS
411 //
412 class DPlat : public DMovingFloor
413 {
414 	DECLARE_CLASS (DPlat, DMovingFloor)
415 public:
416 	enum EPlatState
417 	{
418 		up,
419 		down,
420 		waiting,
421 		in_stasis
422 	};
423 
424 	enum EPlatType
425 	{
426 		platPerpetualRaise,
427 		platDownWaitUpStay,
428 		platDownWaitUpStayStone,
429 		platUpWaitDownStay,
430 		platUpNearestWaitDownStay,
431 		platDownByValue,
432 		platUpByValue,
433 		platUpByValueStay,
434 		platRaiseAndStay,
435 		platToggle,
436 		platDownToNearestFloor,
437 		platDownToLowestCeiling,
438 		platRaiseAndStayLockout,
439 	};
440 
441 	void Serialize (FArchive &arc);
442 	void Tick ();
443 
IsLift()444 	bool IsLift() const { return m_Type == platDownWaitUpStay || m_Type == platDownWaitUpStayStone; }
445 
446 protected:
447 	DPlat (sector_t *sector);
448 
449 	fixed_t 	m_Speed;
450 	fixed_t 	m_Low;
451 	fixed_t 	m_High;
452 	int 		m_Wait;
453 	int 		m_Count;
454 	EPlatState	m_Status;
455 	EPlatState	m_OldStatus;
456 	int			m_Crush;
457 	int 		m_Tag;
458 	EPlatType	m_Type;
459 
460 	void PlayPlatSound (const char *sound);
461 	void Reactivate ();
462 	void Stop ();
463 
464 private:
465 	DPlat ();
466 
467 	friend bool	EV_DoPlat (int tag, line_t *line, EPlatType type,
468 						   int height, int speed, int delay, int lip, int change);
469 	friend void EV_StopPlat (int tag);
470 	friend void P_ActivateInStasis (int tag);
471 };
472 
473 bool EV_DoPlat (int tag, line_t *line, DPlat::EPlatType type,
474 				int height, int speed, int delay, int lip, int change);
475 void EV_StopPlat (int tag);
476 void P_ActivateInStasis (int tag);
477 
478 //
479 // [RH]
480 // P_PILLAR
481 //
482 
483 class DPillar : public DMover
484 {
485 	DECLARE_CLASS (DPillar, DMover)
486 	HAS_OBJECT_POINTERS
487 public:
488 	enum EPillar
489 	{
490 		pillarBuild,
491 		pillarOpen
492 
493 	};
494 
495 	DPillar (sector_t *sector, EPillar type, fixed_t speed, fixed_t height,
496 			 fixed_t height2, int crush, bool hexencrush);
497 
498 	void Serialize (FArchive &arc);
499 	void Tick ();
500 	void Destroy();
501 
502 protected:
503 	EPillar		m_Type;
504 	fixed_t		m_FloorSpeed;
505 	fixed_t		m_CeilingSpeed;
506 	fixed_t		m_FloorTarget;
507 	fixed_t		m_CeilingTarget;
508 	int			m_Crush;
509 	bool		m_Hexencrush;
510 	TObjPtr<DInterpolation> m_Interp_Ceiling;
511 	TObjPtr<DInterpolation> m_Interp_Floor;
512 
513 private:
514 	DPillar ();
515 };
516 
517 bool EV_DoPillar (DPillar::EPillar type, line_t *line, int tag,
518 				  fixed_t speed, fixed_t height, fixed_t height2, int crush, bool hexencrush);
519 
520 //
521 // P_DOORS
522 //
523 class DDoor : public DMovingCeiling
524 {
525 	DECLARE_CLASS (DDoor, DMovingCeiling)
526 public:
527 	enum EVlDoor
528 	{
529 		doorClose,
530 		doorOpen,
531 		doorRaise,
532 		doorRaiseIn5Mins,
533 		doorCloseWaitOpen,
534 	};
535 
536 	DDoor (sector_t *sector);
537 	DDoor (sector_t *sec, EVlDoor type, fixed_t speed, int delay, int lightTag);
538 
539 	void Serialize (FArchive &arc);
540 	void Tick ();
541 protected:
542 	EVlDoor		m_Type;
543 	fixed_t 	m_TopDist;
544 	fixed_t		m_BotDist, m_OldFloorDist;
545 	vertex_t	*m_BotSpot;
546 	fixed_t 	m_Speed;
547 
548 	// 1 = up, 0 = waiting at top, -1 = down
549 	int 		m_Direction;
550 
551 	// tics to wait at the top
552 	int 		m_TopWait;
553 	// (keep in case a door going down is reset)
554 	// when it reaches 0, start going down
555 	int 		m_TopCountdown;
556 
557 	int			m_LightTag;
558 
559 	void DoorSound (bool raise, class DSeqNode *curseq=NULL) const;
560 
561 	friend bool	EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing,
562 						   int tag, int speed, int delay, int lock,
563 						   int lightTag, bool boomgen);
564 	friend void P_SpawnDoorCloseIn30 (sector_t *sec);
565 	friend void P_SpawnDoorRaiseIn5Mins (sector_t *sec);
566 private:
567 	DDoor ();
568 
569 };
570 
571 bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing,
572 				int tag, int speed, int delay, int lock,
573 				int lightTag, bool boomgen = false);
574 void P_SpawnDoorCloseIn30 (sector_t *sec);
575 void P_SpawnDoorRaiseIn5Mins (sector_t *sec);
576 
577 class DAnimatedDoor : public DMovingCeiling
578 {
579 	DECLARE_CLASS (DAnimatedDoor, DMovingCeiling)
580 public:
581 	DAnimatedDoor (sector_t *sector);
582 	DAnimatedDoor (sector_t *sec, line_t *line, int speed, int delay, FDoorAnimation *anim);
583 
584 	void Serialize (FArchive &arc);
585 	void Tick ();
586 
587 	bool StartClosing ();
588 protected:
589 	line_t *m_Line1, *m_Line2;
590 	int m_Frame;
591 	FDoorAnimation *m_DoorAnim;
592 	int m_Timer;
593 	fixed_t m_BotDist;
594 	int m_Status;
595 	enum
596 	{
597 		Opening,
598 		Waiting,
599 		Closing,
600 		Dead
601 	};
602 	int m_Speed;
603 	int m_Delay;
604 	bool m_SetBlocking1, m_SetBlocking2;
605 
606 	friend bool EV_SlidingDoor (line_t *line, AActor *thing, int tag, int speed, int delay);
607 private:
608 	DAnimatedDoor ();
609 };
610 
611 bool EV_SlidingDoor (line_t *line, AActor *thing, int tag, int speed, int delay);
612 
613 //
614 // P_CEILNG
615 //
616 
617 // [RH] Changed these
618 class DCeiling : public DMovingCeiling
619 {
620 	DECLARE_CLASS (DCeiling, DMovingCeiling)
621 public:
622 	enum ECeiling
623 	{
624 		ceilLowerByValue,
625 		ceilRaiseByValue,
626 		ceilMoveToValue,
627 		ceilLowerToHighestFloor,
628 		ceilLowerInstant,
629 		ceilRaiseInstant,
630 		ceilCrushAndRaise,
631 		ceilLowerAndCrush,
632 		ceilLowerAndCrushDist,
633 		ceilCrushRaiseAndStay,
634 		ceilRaiseToNearest,
635 		ceilLowerToLowest,
636 		ceilLowerToFloor,
637 
638 		// The following are only used by Generic_Ceiling
639 		ceilRaiseToHighest,
640 		ceilLowerToHighest,
641 		ceilRaiseToLowest,
642 		ceilLowerToNearest,
643 		ceilRaiseToHighestFloor,
644 		ceilRaiseToFloor,
645 		ceilRaiseByTexture,
646 		ceilLowerByTexture,
647 
648 		genCeilingChg0,
649 		genCeilingChgT,
650 		genCeilingChg
651 	};
652 
653 	DCeiling (sector_t *sec);
654 	DCeiling (sector_t *sec, fixed_t speed1, fixed_t speed2, int silent);
655 
656 	void Serialize (FArchive &arc);
657 	void Tick ();
658 
659 	static DCeiling *Create(sector_t *sec, DCeiling::ECeiling type, line_t *line, int tag,
660 						fixed_t speed, fixed_t speed2, fixed_t height,
661 						int crush, int silent, int change, bool hexencrush);
662 
663 protected:
664 	ECeiling	m_Type;
665 	fixed_t 	m_BottomHeight;
666 	fixed_t 	m_TopHeight;
667 	fixed_t 	m_Speed;
668 	fixed_t		m_Speed1;		// [RH] dnspeed of crushers
669 	fixed_t		m_Speed2;		// [RH] upspeed of crushers
670 	int 		m_Crush;
671 	bool		m_Hexencrush;
672 	int			m_Silent;
673 	int 		m_Direction;	// 1 = up, 0 = waiting, -1 = down
674 
675 	// [RH] Need these for BOOM-ish transferring ceilings
676 	FTextureID	m_Texture;
677 	secspecial_t m_NewSpecial;
678 
679 	// ID
680 	int 		m_Tag;
681 	int 		m_OldDirection;
682 
683 	void PlayCeilingSound ();
684 
685 private:
686 	DCeiling ();
687 
688 	friend bool EV_CeilingCrushStop (int tag);
689 	friend void P_ActivateInStasisCeiling (int tag);
690 };
691 
692 bool EV_DoCeiling (DCeiling::ECeiling type, line_t *line,
693 	int tag, fixed_t speed, fixed_t speed2, fixed_t height,
694 	int crush, int silent, int change, bool hexencrush);
695 bool EV_CeilingCrushStop (int tag);
696 void P_ActivateInStasisCeiling (int tag);
697 
698 
699 
700 //
701 // P_FLOOR
702 //
703 
704 class DFloor : public DMovingFloor
705 {
706 	DECLARE_CLASS (DFloor, DMovingFloor)
707 public:
708 	enum EFloor
709 	{
710 		floorLowerToLowest,
711 		floorLowerToNearest,
712 		floorLowerToHighest,
713 		floorLowerByValue,
714 		floorRaiseByValue,
715 		floorRaiseToHighest,
716 		floorRaiseToNearest,
717 		floorRaiseAndCrush,
718 		floorRaiseAndCrushDoom,
719 		floorCrushStop,
720 		floorLowerInstant,
721 		floorRaiseInstant,
722 		floorMoveToValue,
723 		floorRaiseToLowestCeiling,
724 		floorRaiseByTexture,
725 
726 		floorLowerAndChange,
727 		floorRaiseAndChange,
728 
729 		floorRaiseToLowest,
730 		floorRaiseToCeiling,
731 		floorLowerToLowestCeiling,
732 		floorLowerByTexture,
733 		floorLowerToCeiling,
734 
735 		donutRaise,
736 
737 		buildStair,
738 		waitStair,
739 		resetStair,
740 
741 		// Not to be used as parameters to EV_DoFloor()
742 		genFloorChg0,
743 		genFloorChgT,
744 		genFloorChg
745 	};
746 
747 	// [RH] Changed to use Hexen-ish specials
748 	enum EStair
749 	{
750 		buildUp,
751 		buildDown
752 	};
753 
754 	DFloor (sector_t *sec);
755 
756 	void Serialize (FArchive &arc);
757 	void Tick ();
758 
759 protected:
760 	EFloor	 	m_Type;
761 	int 		m_Crush;
762 	bool		m_Hexencrush;
763 	int 		m_Direction;
764 	secspecial_t m_NewSpecial;
765 	FTextureID	m_Texture;
766 	fixed_t 	m_FloorDestDist;
767 	fixed_t 	m_Speed;
768 
769 	// [RH] New parameters used to reset and delay stairs
770 	int			m_ResetCount;
771 	int			m_OrgDist;
772 	int			m_Delay;
773 	int			m_PauseTime;
774 	int			m_StepTime;
775 	int			m_PerStepTime;
776 
777 	void StartFloorSound ();
778 	void SetFloorChangeType (sector_t *sec, int change);
779 
780 	friend bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
781 		fixed_t stairsize, fixed_t speed, int delay, int reset, int igntxt,
782 		int usespecials);
783 	friend bool EV_DoFloor (DFloor::EFloor floortype, line_t *line, int tag,
784 		fixed_t speed, fixed_t height, int crush, int change, bool hexencrush, bool hereticlower);
785 	friend bool EV_FloorCrushStop (int tag);
786 	friend bool EV_DoDonut (int tag, line_t *line, fixed_t pillarspeed, fixed_t slimespeed);
787 private:
788 	DFloor ();
789 };
790 
791 bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
792 	fixed_t stairsize, fixed_t speed, int delay, int reset, int igntxt,
793 	int usespecials);
794 bool EV_DoFloor (DFloor::EFloor floortype, line_t *line, int tag,
795 	fixed_t speed, fixed_t height, int crush, int change, bool hexencrush, bool hereticlower=false);
796 bool EV_FloorCrushStop (int tag);
797 bool EV_DoDonut (int tag, line_t *line, fixed_t pillarspeed, fixed_t slimespeed);
798 
799 class DElevator : public DMover
800 {
801 	DECLARE_CLASS (DElevator, DMover)
802 	HAS_OBJECT_POINTERS
803 public:
804 	enum EElevator
805 	{
806 		elevateUp,
807 		elevateDown,
808 		elevateCurrent,
809 		// [RH] For FloorAndCeiling_Raise/Lower
810 		elevateRaise,
811 		elevateLower
812 	};
813 
814 	DElevator (sector_t *sec);
815 
816 	void Destroy();
817 	void Serialize (FArchive &arc);
818 	void Tick ();
819 
820 protected:
821 	EElevator	m_Type;
822 	int			m_Direction;
823 	fixed_t		m_FloorDestDist;
824 	fixed_t		m_CeilingDestDist;
825 	fixed_t		m_Speed;
826 	TObjPtr<DInterpolation> m_Interp_Ceiling;
827 	TObjPtr<DInterpolation> m_Interp_Floor;
828 
829 	void StartFloorSound ();
830 
831 	friend bool EV_DoElevator (line_t *line, DElevator::EElevator type, fixed_t speed,
832 		fixed_t height, int tag);
833 private:
834 	DElevator ();
835 };
836 
837 bool EV_DoElevator (line_t *line, DElevator::EElevator type, fixed_t speed,
838 	fixed_t height, int tag);
839 
840 class DWaggleBase : public DMover
841 {
842 	DECLARE_CLASS (DWaggleBase, DMover)
843 	HAS_OBJECT_POINTERS
844 public:
845 	DWaggleBase (sector_t *sec);
846 
847 	void Serialize (FArchive &arc);
848 
849 protected:
850 	fixed_t m_OriginalDist;
851 	fixed_t m_Accumulator;
852 	fixed_t m_AccDelta;
853 	fixed_t m_TargetScale;
854 	fixed_t m_Scale;
855 	fixed_t m_ScaleDelta;
856 	int m_Ticker;
857 	int m_State;
858 	TObjPtr<DInterpolation> m_Interpolation;
859 
860 	friend bool EV_StartWaggle (int tag, line_t *line, int height, int speed,
861 		int offset, int timer, bool ceiling);
862 
863 	void DoWaggle (bool ceiling);
864 	void Destroy();
865 	DWaggleBase ();
866 };
867 
868 bool EV_StartWaggle (int tag, line_t *line, int height, int speed,
869 	int offset, int timer, bool ceiling);
870 
871 class DFloorWaggle : public DWaggleBase
872 {
873 	DECLARE_CLASS (DFloorWaggle, DWaggleBase)
874 public:
875 	DFloorWaggle (sector_t *sec);
876 	void Tick ();
877 private:
878 	DFloorWaggle ();
879 };
880 
881 class DCeilingWaggle : public DWaggleBase
882 {
883 	DECLARE_CLASS (DCeilingWaggle, DWaggleBase)
884 public:
885 	DCeilingWaggle (sector_t *sec);
886 	void Tick ();
887 private:
888 	DCeilingWaggle ();
889 };
890 
891 //jff 3/15/98 pure texture/type change for better generalized support
892 enum EChange
893 {
894 	trigChangeOnly,
895 	numChangeOnly,
896 };
897 
898 bool EV_DoChange (line_t *line, EChange changetype, int tag);
899 
900 
901 
902 //
903 // P_TELEPT
904 //
905 enum
906 {
907 	TELF_DESTFOG			= 1,
908 	TELF_SOURCEFOG			= 2,
909 	TELF_KEEPORIENTATION	= 4,
910 	TELF_KEEPVELOCITY		= 8,
911 	TELF_KEEPHEIGHT			= 16,
912 };
913 
914 void P_SpawnTeleportFog(AActor *mobj, fixed_t x, fixed_t y, fixed_t z, bool beforeTele = true, bool setTarget = false); //Spawns teleport fog. Pass the actor to pluck TeleFogFromType and TeleFogToType. 'from' determines if this is the fog to spawn at the old position (true) or new (false).
915 inline void P_SpawnTeleportFog(AActor *mobj, const fixedvec3 &pos, bool beforeTele = true, bool setTarget = false)
916 {
917 	P_SpawnTeleportFog(mobj, pos.x, pos.y, pos.z, beforeTele, setTarget);
918 }
919 bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, int flags); // bool useFog, bool sourceFog, bool keepOrientation, bool haltVelocity = true, bool keepHeight = false
920 bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, int flags);
921 bool EV_SilentLineTeleport (line_t *line, int side, AActor *thing, int id, INTBOOL reverse);
922 bool EV_TeleportOther (int other_tid, int dest_tid, bool fog);
923 bool EV_TeleportGroup (int group_tid, AActor *victim, int source_tid, int dest_tid, bool moveSource, bool fog);
924 bool EV_TeleportSector (int tag, int source_tid, int dest_tid, bool fog, int group_tid);
925 
926 
927 //
928 // [RH] ACS (see also p_acs.h)
929 //
930 
931 #define ACS_BACKSIDE		1
932 #define ACS_ALWAYS			2
933 #define ACS_WANTRESULT		4
934 #define ACS_NET				8
935 
936 int  P_StartScript (AActor *who, line_t *where, int script, const char *map, const int *args, int argcount, int flags);
937 void P_SuspendScript (int script, const char *map);
938 void P_TerminateScript (int script, const char *map);
939 void P_DoDeferedScripts (void);
940 
941 //
942 // [RH] p_quake.c
943 //
944 bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags, double waveSpeedX, double waveSpeedY, double waveSpeedZ);
945 bool P_StartQuake(AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx);
946 
947 #endif
948