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:
18 //		Play functions, animation, global header.
19 //
20 //-----------------------------------------------------------------------------
21 
22 
23 #ifndef __P_LOCAL__
24 #define __P_LOCAL__
25 
26 #include "doomtype.h"
27 #include "doomdef.h"
28 #include "tables.h"
29 #include "r_state.h"
30 #include "r_utility.h"
31 #include "d_player.h"
32 
33 #include "a_morph.h"
34 
35 #include <stdlib.h>
36 
37 #define STEEPSLOPE		46342	// [RH] Minimum floorplane.c value for walking
38 
39 #define BONUSADD		6
40 
41 // mapblocks are used to check movement
42 // against lines and things
43 #define MAPBLOCKUNITS	128
44 #define MAPBLOCKSIZE	(MAPBLOCKUNITS*FRACUNIT)
45 #define MAPBLOCKSHIFT	(FRACBITS+7)
46 #define MAPBMASK		(MAPBLOCKSIZE-1)
47 #define MAPBTOFRAC		(MAPBLOCKSHIFT-FRACBITS)
48 
49 // Inspired by Maes
50 extern int bmapnegx;
51 extern int bmapnegy;
52 
GetSafeBlockX(int blockx)53 inline int GetSafeBlockX(int blockx)
54 {
55 	blockx >>= MAPBLOCKSHIFT;
56 	return (blockx <= bmapnegx) ? blockx & 0x1FF : blockx;
57 }
GetSafeBlockX(long long blockx)58 inline int GetSafeBlockX(long long blockx)
59 {
60 	blockx >>= MAPBLOCKSHIFT;
61 	return int((blockx <= bmapnegx) ? blockx & 0x1FF : blockx);
62 }
63 
GetSafeBlockY(int blocky)64 inline int GetSafeBlockY(int blocky)
65 {
66 	blocky >>= MAPBLOCKSHIFT;
67 	return (blocky <= bmapnegy) ? blocky & 0x1FF: blocky;
68 }
GetSafeBlockY(long long blocky)69 inline int GetSafeBlockY(long long blocky)
70 {
71 	blocky >>= MAPBLOCKSHIFT;
72 	return int((blocky <= bmapnegy) ? blocky & 0x1FF: blocky);
73 }
74 
75 // MAXRADIUS is for precalculated sector block boxes
76 // the spider demon is larger,
77 // but we do not have any moving sectors nearby
78 #define MAXRADIUS		0/*32*FRACUNIT*/
79 
80 //#define GRAVITY 		FRACUNIT
81 #define MAXMOVE 		(30*FRACUNIT)
82 
83 #define TALKRANGE		(128*FRACUNIT)
84 #define USERANGE		(64*FRACUNIT)
85 #define MELEERANGE		(64*FRACUNIT)
86 #define MISSILERANGE	(32*64*FRACUNIT)
87 #define PLAYERMISSILERANGE	(8192*FRACUNIT)	// [RH] New MISSILERANGE for players
88 
89 // follow a player exlusively for 3 seconds
90 #define BASETHRESHOLD	100
91 
92 
93 //
94 // P_PSPR
95 //
96 void P_SetupPsprites (player_t* curplayer, bool startweaponup);
97 void P_MovePsprites (player_t* curplayer);
98 void P_DropWeapon (player_t* player);
99 
100 
101 //
102 // P_USER
103 //
104 void	P_FallingDamage (AActor *ent);
105 void	P_PlayerThink (player_t *player);
106 void	P_PredictPlayer (player_t *player);
107 void	P_UnPredictPlayer ();
108 void	P_PredictionLerpReset();
109 
110 //
111 // P_MOBJ
112 //
113 
114 #define ONFLOORZ		FIXED_MIN
115 #define ONCEILINGZ		FIXED_MAX
116 #define FLOATRANDZ		(FIXED_MAX-1)
117 
118 #define SPF_TEMPPLAYER		1	// spawning a short-lived dummy player
119 #define SPF_WEAPONFULLYUP	2	// spawn with weapon already raised
120 
121 APlayerPawn *P_SpawnPlayer (struct FPlayerStart *mthing, int playernum, int flags=0);
122 
123 void P_ThrustMobj (AActor *mo, angle_t angle, fixed_t move);
124 int P_FaceMobj (AActor *source, AActor *target, angle_t *delta);
125 bool P_SeekerMissile (AActor *actor, angle_t thresh, angle_t turnMax, bool precise = false, bool usecurspeed=false);
126 
127 enum EPuffFlags
128 {
129 	PF_HITTHING = 1,
130 	PF_MELEERANGE = 2,
131 	PF_TEMPORARY = 4,
132 	PF_HITTHINGBLEED = 8,
133 	PF_NORANDOMZ = 16
134 };
135 
136 AActor *P_SpawnPuff (AActor *source, const PClass *pufftype, fixed_t x, fixed_t y, fixed_t z, angle_t dir, int updown, int flags = 0, AActor *vict = NULL);
137 inline AActor *P_SpawnPuff(AActor *source, const PClass *pufftype, const fixedvec3 &pos, angle_t dir, int updown, int flags = 0, AActor *vict = NULL)
138 {
139 	return P_SpawnPuff(source, pufftype, pos.x, pos.y, pos.z, dir, updown, flags, vict);
140 }
141 void	P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AActor *originator);
P_SpawnBlood(const fixedvec3 & pos,angle_t dir,int damage,AActor * originator)142 inline void	P_SpawnBlood(const fixedvec3 &pos, angle_t dir, int damage, AActor *originator)
143 {
144 	P_SpawnBlood(pos.x, pos.y, pos.z, dir, damage, originator);
145 }
146 void	P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator);
147 void	P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator);
148 void	P_RipperBlood (AActor *mo, AActor *bleeder);
149 int		P_GetThingFloorType (AActor *thing);
150 void	P_ExplodeMissile (AActor *missile, line_t *explodeline, AActor *target);
151 
152 AActor *P_SpawnMissile (AActor* source, AActor* dest, const PClass *type, AActor* owner = NULL);
153 AActor *P_SpawnMissileZ (AActor* source, fixed_t z, AActor* dest, const PClass *type);
154 AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, AActor *source, AActor *dest, const PClass *type, bool checkspawn = true, AActor *owner = NULL);
155 inline AActor *P_SpawnMissileXYZ(const fixedvec3 &pos, AActor *source, AActor *dest, const PClass *type, bool checkspawn = true, AActor *owner = NULL)
156 {
157 	return P_SpawnMissileXYZ(pos.x, pos.y, pos.z, source, dest, type, checkspawn, owner);
158 }
159 AActor *P_SpawnMissileAngle (AActor *source, const PClass *type, angle_t angle, fixed_t velz);
160 AActor *P_SpawnMissileAngleSpeed (AActor *source, const PClass *type, angle_t angle, fixed_t velz, fixed_t speed);
161 AActor *P_SpawnMissileAngleZ (AActor *source, fixed_t z, const PClass *type, angle_t angle, fixed_t velz);
162 AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z, const PClass *type, angle_t angle, fixed_t velz, fixed_t speed, AActor *owner=NULL, bool checkspawn = true);
163 AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, const PClass *type);
164 
165 AActor *P_SpawnPlayerMissile (AActor* source, const PClass *type);
166 AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type, angle_t angle);
167 AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, const PClass *type, angle_t angle,
168 							  AActor **pLineTarget = NULL, AActor **MissileActor = NULL, bool nofreeaim = false, bool noautoaim = false);
169 
170 void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz, bool oldz_has_viewheight=false);
171 
172 //
173 // [RH] P_THINGS
174 //
175 extern FClassMap SpawnableThings;
176 extern FClassMap StrifeTypes;
177 
178 bool	P_Thing_Spawn (int tid, AActor *source, int type, angle_t angle, bool fog, int newtid);
179 bool	P_Thing_Projectile (int tid, AActor *source, int type, const char * type_name, angle_t angle,
180 			fixed_t speed, fixed_t vspeed, int dest, AActor *forcedest, int gravity, int newtid,
181 			bool leadTarget);
182 bool	P_MoveThing(AActor *source, fixed_t x, fixed_t y, fixed_t z, bool fog);
183 bool	P_Thing_Move (int tid, AActor *source, int mapspot, bool fog);
184 int		P_Thing_Damage (int tid, AActor *whofor0, int amount, FName type);
185 void	P_Thing_SetVelocity(AActor *actor, fixed_t vx, fixed_t vy, fixed_t vz, bool add, bool setbob);
186 void P_RemoveThing(AActor * actor);
187 bool P_Thing_Raise(AActor *thing, AActor *raiser);
188 bool P_Thing_CanRaise(AActor *thing);
189 const PClass *P_GetSpawnableType(int spawnnum);
190 void InitSpawnablesFromMapinfo();
191 int P_Thing_Warp(AActor *caller, AActor *reference, fixed_t xofs, fixed_t yofs, fixed_t zofs, angle_t angle, int flags, fixed_t heightoffset, fixed_t radiusoffset, angle_t pitch);
192 
193 enum WARPF
194 {
195 	WARPF_ABSOLUTEOFFSET = 0x1,
196 	WARPF_ABSOLUTEANGLE  = 0x2,
197 	WARPF_USECALLERANGLE = 0x4,
198 
199 	WARPF_NOCHECKPOSITION = 0x8,
200 
201 	WARPF_INTERPOLATE       = 0x10,
202 	WARPF_WARPINTERPOLATION = 0x20,
203 	WARPF_COPYINTERPOLATION = 0x40,
204 
205 	WARPF_STOP             = 0x80,
206 	WARPF_TOFLOOR          = 0x100,
207 	WARPF_TESTONLY         = 0x200,
208 	WARPF_ABSOLUTEPOSITION = 0x400,
209 	WARPF_BOB              = 0x800,
210 	WARPF_MOVEPTR          = 0x1000,
211 	WARPF_USEPTR           = 0x2000,
212 	WARPF_USETID           = 0x2000,
213 	WARPF_COPYVELOCITY		= 0x4000,
214 	WARPF_COPYPITCH			= 0x8000,
215 };
216 
217 
218 
219 //
220 // P_MAPUTL
221 //
222 struct divline_t
223 {
224 	fixed_t 	x;
225 	fixed_t 	y;
226 	fixed_t 	dx;
227 	fixed_t 	dy;
228 
229 };
230 
231 struct intercept_t
232 {
233 	fixed_t 	frac;			// along trace line
234 	bool	 	isaline;
235 	bool		done;
236 	union {
237 		AActor *thing;
238 		line_t *line;
239 	} d;
240 };
241 
242 typedef bool (*traverser_t) (intercept_t *in);
243 
244 fixed_t P_AproxDistance (fixed_t dx, fixed_t dy);
245 
246 //==========================================================================
247 //
248 // P_PointOnLineSide
249 //
250 // Returns 0 (front/on) or 1 (back)
251 // [RH] inlined, stripped down, and made more precise
252 //
253 //==========================================================================
254 
P_PointOnLineSide(fixed_t x,fixed_t y,const line_t * line)255 inline int P_PointOnLineSide (fixed_t x, fixed_t y, const line_t *line)
256 {
257 	extern int P_VanillaPointOnLineSide(fixed_t x, fixed_t y, const line_t* line);
258 
259 	return i_compatflags2 & COMPATF2_POINTONLINE
260 		? P_VanillaPointOnLineSide(x, y, line)
261 		: DMulScale32 (y-line->v1->y, line->dx, line->v1->x-x, line->dy) > 0;
262 }
263 
P_PointOnLineSidePrecise(fixed_t x,fixed_t y,const line_t * line)264 inline int P_PointOnLineSidePrecise (fixed_t x, fixed_t y, const line_t *line)
265 {
266 	return DMulScale32 (y-line->v1->y, line->dx, line->v1->x-x, line->dy) > 0;
267 }
268 
269 
270 //==========================================================================
271 //
272 // P_PointOnDivlineSide
273 //
274 // Same as P_PointOnLineSide except it uses divlines
275 // [RH] inlined, stripped down, and made more precise
276 //
277 //==========================================================================
278 
P_PointOnDivlineSide(fixed_t x,fixed_t y,const divline_t * line)279 inline int P_PointOnDivlineSide (fixed_t x, fixed_t y, const divline_t *line)
280 {
281 	extern int P_VanillaPointOnDivlineSide(fixed_t x, fixed_t y, const divline_t* line);
282 
283 	return (i_compatflags2 & COMPATF2_POINTONLINE)
284 		? P_VanillaPointOnDivlineSide(x, y, line)
285 		: (DMulScale32 (y-line->y, line->dx, line->x-x, line->dy) > 0);
286 }
287 
P_PointOnDivlineSidePrecise(fixed_t x,fixed_t y,const divline_t * line)288 inline int P_PointOnDivlineSidePrecise (fixed_t x, fixed_t y, const divline_t *line)
289 {
290 	return DMulScale32 (y-line->y, line->dx, line->x-x, line->dy) > 0;
291 }
292 
293 
294 //==========================================================================
295 //
296 // P_MakeDivline
297 //
298 //==========================================================================
299 
P_MakeDivline(const line_t * li,divline_t * dl)300 inline void P_MakeDivline (const line_t *li, divline_t *dl)
301 {
302 	dl->x = li->v1->x;
303 	dl->y = li->v1->y;
304 	dl->dx = li->dx;
305 	dl->dy = li->dy;
306 }
307 
308 fixed_t P_InterceptVector (const divline_t *v2, const divline_t *v1);
309 
310 struct FLineOpening
311 {
312 	fixed_t			top;
313 	fixed_t			bottom;
314 	fixed_t			range;
315 	fixed_t			lowfloor;
316 	sector_t		*bottomsec;
317 	sector_t		*topsec;
318 	FTextureID		ceilingpic;
319 	FTextureID		floorpic;
320 	int				floorterrain;
321 	bool			touchmidtex;
322 	bool			abovemidtex;
323 };
324 
325 void	P_LineOpening (FLineOpening &open, AActor *thing, const line_t *linedef, fixed_t x, fixed_t y, fixed_t refx=FIXED_MIN, fixed_t refy=0, int flags=0);
326 
327 class FBoundingBox;
328 struct polyblock_t;
329 
330 class FBlockLinesIterator
331 {
332 	int minx, maxx;
333 	int miny, maxy;
334 
335 	int curx, cury;
336 	polyblock_t *polyLink;
337 	int polyIndex;
338 	int *list;
339 
340 	void StartBlock(int x, int y);
341 
342 public:
343 	FBlockLinesIterator(int minx, int miny, int maxx, int maxy, bool keepvalidcount = false);
344 	FBlockLinesIterator(const FBoundingBox &box);
345 	line_t *Next();
Reset()346 	void Reset() { StartBlock(minx, miny); }
347 };
348 
349 class FBlockThingsIterator
350 {
351 	int minx, maxx;
352 	int miny, maxy;
353 
354 	int curx, cury;
355 
356 	FBlockNode *block;
357 
358 	int Buckets[32];
359 
360 	struct HashEntry
361 	{
362 		AActor *Actor;
363 		int Next;
364 	};
365 	HashEntry FixedHash[10];
366 	int NumFixedHash;
367 	TArray<HashEntry> DynHash;
368 
GetHashEntry(int i)369 	HashEntry *GetHashEntry(int i) { return i < (int)countof(FixedHash) ? &FixedHash[i] : &DynHash[i - countof(FixedHash)]; }
370 
371 	void StartBlock(int x, int y);
372 	void SwitchBlock(int x, int y);
373 	void ClearHash();
374 
375 	// The following is only for use in the path traverser
376 	// and therefore declared private.
377 	FBlockThingsIterator();
378 
379 	friend class FPathTraverse;
380 
381 public:
382 	FBlockThingsIterator(int minx, int miny, int maxx, int maxy);
383 	FBlockThingsIterator(const FBoundingBox &box);
384 	AActor *Next(bool centeronly = false);
Reset()385 	void Reset() { StartBlock(minx, miny); }
386 };
387 
388 class FPathTraverse
389 {
390 	static TArray<intercept_t> intercepts;
391 
392 	divline_t trace;
393 	unsigned int intercept_index;
394 	unsigned int intercept_count;
395 	unsigned int count;
396 
397 	void AddLineIntercepts(int bx, int by);
398 	void AddThingIntercepts(int bx, int by, FBlockThingsIterator &it, bool compatible);
399 public:
400 
401 	intercept_t *Next();
402 
403 	FPathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags);
404 	~FPathTraverse();
Trace()405 	const divline_t &Trace() const { return trace; }
406 };
407 
408 
409 #define PT_ADDLINES 	1
410 #define PT_ADDTHINGS	2
411 #define PT_COMPATIBLE	4
412 #define PT_DELTA		8		// x2,y2 is passed as a delta, not as an endpoint
413 
414 AActor *P_BlockmapSearch (AActor *mo, int distance, AActor *(*check)(AActor*, int, void *), void *params = NULL);
415 AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable=false);
416 
417 //
418 // P_MAP
419 //
420 
421 struct FCheckPosition
422 {
423 	// in
424 	AActor			*thing;
425 	fixed_t			x;
426 	fixed_t			y;
427 	fixed_t			z;
428 
429 	// out
430 	sector_t		*sector;
431 	fixed_t			floorz;
432 	fixed_t			ceilingz;
433 	fixed_t			dropoffz;
434 	FTextureID		floorpic;
435 	int				floorterrain;
436 	sector_t		*floorsector;
437 	FTextureID		ceilingpic;
438 	sector_t		*ceilingsector;
439 	bool			touchmidtex;
440 	bool			abovemidtex;
441 	bool			floatok;
442 	bool			FromPMove;
443 	line_t			*ceilingline;
444 	AActor			*stepthing;
445 	// [RH] These are used by PIT_CheckThing and P_XYMovement to apply
446 	// ripping damage once per tic instead of once per move.
447 	bool			DoRipping;
448 	TMap<AActor*, bool> LastRipped;
449 	int				PushTime;
450 
451 	FCheckPosition(bool rip=false)
452 	{
453 		DoRipping = rip;
454 		PushTime = 0;
455 		FromPMove = false;
456 	}
457 };
458 
459 
460 
461 // If "floatok" true, move would be ok
462 // if within "tmfloorz - tmceilingz".
463 extern msecnode_t		*sector_list;		// phares 3/16/98
464 
465 extern TArray<line_t *> spechit;
466 
467 
468 bool	P_TestMobjLocation (AActor *mobj);
469 bool	P_TestMobjZ (AActor *mobj, bool quick=true, AActor **pOnmobj = NULL);
470 bool	P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bool actorsonly=false);
471 bool	P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, bool actorsonly=false);
472 inline bool P_CheckPosition(AActor *thing, const fixedvec3 &pos, bool actorsonly = false)
473 {
474 	return P_CheckPosition(thing, pos.x, pos.y, actorsonly);
475 }
476 AActor	*P_CheckOnmobj (AActor *thing);
477 void	P_FakeZMovement (AActor *mo);
478 bool	P_TryMove (AActor* thing, fixed_t x, fixed_t y, int dropoff, const secplane_t * onfloor, FCheckPosition &tm, bool missileCheck = false);
479 bool	P_TryMove (AActor* thing, fixed_t x, fixed_t y, int dropoff, const secplane_t * onfloor = NULL);
480 bool	P_CheckMove(AActor *thing, fixed_t x, fixed_t y);
481 void	P_ApplyTorque(AActor *mo);
482 bool	P_TeleportMove (AActor* thing, fixed_t x, fixed_t y, fixed_t z, bool telefrag, bool modifyactor = true);	// [RH] Added z and telefrag parameters
483 inline bool	P_TeleportMove(AActor* thing, const fixedvec3 &pos, bool telefrag, bool modifyactor = true)
484 {
485 	return P_TeleportMove(thing, pos.x, pos.y, pos.z, telefrag, modifyactor);
486 }
487 void	P_PlayerStartStomp (AActor *actor, bool mononly=false);		// [RH] Stomp on things for a newly spawned player
488 void	P_SlideMove (AActor* mo, fixed_t tryx, fixed_t tryy, int numsteps);
489 bool	P_BounceWall (AActor *mo);
490 bool	P_BounceActor (AActor *mo, AActor *BlockingMobj, bool ontop);
491 bool	P_CheckSight (const AActor *t1, const AActor *t2, int flags=0);
492 
493 enum ESightFlags
494 {
495 	SF_IGNOREVISIBILITY=1,
496 	SF_SEEPASTSHOOTABLELINES=2,
497 	SF_SEEPASTBLOCKEVERYTHING=4,
498 	SF_IGNOREWATERBOUNDARY=8
499 };
500 
501 void	P_ResetSightCounters (bool full);
502 bool	P_TalkFacing (AActor *player);
503 void	P_UseLines (player_t* player);
504 bool	P_UsePuzzleItem (AActor *actor, int itemType);
505 
506 enum
507 {
508 	FFCF_ONLYSPAWNPOS = 1,
509 	FFCF_SAMESECTOR = 2,
510 	FFCF_ONLY3DFLOORS = 4,	// includes 3D midtexes
511 	FFCF_3DRESTRICT = 8,	// ignore 3D midtexes and floors whose floorz are above thing's z
512 };
513 void	P_FindFloorCeiling (AActor *actor, int flags=0);
514 
515 bool	P_ChangeSector (sector_t* sector, int crunch, int amt, int floorOrCeil, bool isreset);
516 
517 fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget = NULL, fixed_t vrange=0, int flags = 0, AActor *target=NULL, AActor *friender=NULL);
518 
519 enum	// P_AimLineAttack flags
520 {
521 	ALF_FORCENOSMART = 1,
522 	ALF_CHECK3D = 2,
523 	ALF_CHECKNONSHOOTABLE = 4,
524 	ALF_CHECKCONVERSATION = 8,
525 	ALF_NOFRIENDS = 16,
526 };
527 
528 enum	// P_LineAttack flags
529 {
530 	LAF_ISMELEEATTACK = 1,
531 	LAF_NORANDOMPUFFZ = 2,
532 	LAF_NOIMPACTDECAL = 4
533 };
534 
535 AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, const PClass *pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL);
536 AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL);
537 AActor *P_LinePickActor (AActor *t1, angle_t angle, fixed_t distance, int pitch, ActorFlags actorMask, DWORD wallMask);
538 void	P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target, angle_t angle, int pitch);
539 void	P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch);
540 void	P_TraceBleed (int damage, AActor *target, AActor *missile);		// missile version
541 void	P_TraceBleed (int damage, AActor *target);		// random direction version
542 bool	P_HitFloor (AActor *thing);
543 bool	P_HitWater (AActor *thing, sector_t *sec, fixed_t splashx = FIXED_MIN, fixed_t splashy = FIXED_MIN, fixed_t splashz=FIXED_MIN, bool checkabove = false, bool alert = true, bool force = false);
544 void	P_CheckSplash(AActor *self, fixed_t distance);
545 void	P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z = 0, int color1 = 0, int color2 = 0, double maxdiff = 0, int flags = 0, const PClass *puff = NULL, angle_t angleoffset = 0, angle_t pitchoffset = 0, fixed_t distance = 8192*FRACUNIT, int duration = 0, double sparsity = 1.0, double drift = 1.0, const PClass *spawnclass = NULL, int SpiralOffset = 270);	// [RH] Shoot a railgun
546 
547 enum	// P_RailAttack / A_RailAttack / A_CustomRailgun / P_DrawRailTrail flags
548 {
549 	RAF_SILENT = 1,
550 	RAF_NOPIERCE = 2,
551 	RAF_EXPLICITANGLE = 4,
552 	RAF_FULLBRIGHT = 8,
553 	RAF_CENTERZ = 16,
554 };
555 
556 
557 bool	P_CheckMissileSpawn (AActor *missile, fixed_t maxdist);
558 void	P_PlaySpawnSound(AActor *missile, AActor *spawner);
559 
560 // [RH] Position the chasecam
561 void	P_AimCamera (AActor *t1, fixed_t &x, fixed_t &y, fixed_t &z, sector_t *&sec);
562 
563 // [RH] Means of death
564 enum
565 {
566 	RADF_HURTSOURCE = 1,
567 	RADF_NOIMPACTDAMAGE = 2,
568 	RADF_SOURCEISSPOT = 4,
569 	RADF_NODAMAGE = 8,
570 };
571 void	P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance,
572 						FName damageType, int flags, int fulldamagedistance=0);
573 
574 void	P_DelSector_List();
575 void	P_DelSeclist(msecnode_t *);							// phares 3/16/98
576 msecnode_t*	P_DelSecnode(msecnode_t *);
577 void	P_CreateSecNodeList(AActor*,fixed_t,fixed_t);		// phares 3/14/98
578 int		P_GetMoveFactor(const AActor *mo, int *frictionp);	// phares  3/6/98
579 int		P_GetFriction(const AActor *mo, int *frictionfactor);
580 bool	Check_Sides(AActor *, int, int);					// phares
581 
582 // [RH]
583 const secplane_t * P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymove);
584 
585 //----------------------------------------------------------------------------------
586 //
587 // Added so that in the source there's a clear distinction between
588 // game engine and renderer specific calls.
589 // (For ZDoom itself this doesn't make any difference here but for GZDoom it does.)
590 //
591 //----------------------------------------------------------------------------------
592 subsector_t *P_PointInSubsector (fixed_t x, fixed_t y);
P_PointInSector(fixed_t x,fixed_t y)593 inline sector_t *P_PointInSector(fixed_t x, fixed_t y)
594 {
595 	return P_PointInSubsector(x,y)->sector;
596 }
597 
598 //
599 // P_SETUP
600 //
601 extern BYTE*			rejectmatrix;	// for fast sight rejection
602 extern int*				blockmaplump;	// offsets in blockmap are from here
603 
604 extern int*				blockmap;
605 extern int				bmapwidth;
606 extern int				bmapheight; 	// in mapblocks
607 extern fixed_t			bmaporgx;
608 extern fixed_t			bmaporgy;		// origin of block map
609 extern FBlockNode**		blocklinks; 	// for thing chains
610 
611 
612 
613 //
614 // P_INTER
615 //
616 void P_TouchSpecialThing (AActor *special, AActor *toucher);
617 int  P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags=0);
618 void P_PoisonMobj (AActor *target, AActor *inflictor, AActor *source, int damage, int duration, int period, FName type);
619 bool P_GiveBody (AActor *actor, int num, int max=0);
620 bool P_PoisonPlayer (player_t *player, AActor *poisoner, AActor *source, int poison);
621 void P_PoisonDamage (player_t *player, AActor *source, int damage, bool playPainSound);
622 
623 enum EDmgFlags
624 {
625 	DMG_NO_ARMOR = 1,
626 	DMG_INFLICTOR_IS_PUFF = 2,
627 	DMG_THRUSTLESS = 4,
628 	DMG_FORCED = 8,
629 	DMG_NO_FACTOR = 16,
630 	DMG_PLAYERATTACK = 32,
631 	DMG_FOILINVUL = 64,
632 	DMG_FOILBUDDHA = 128,
633 	DMG_NO_PROTECT = 256,
634 };
635 
636 
637 // ===== PO_MAN =====
638 
639 typedef enum
640 {
641 	PODOOR_NONE,
642 	PODOOR_SLIDE,
643 	PODOOR_SWING,
644 } podoortype_t;
645 
646 bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle, int direction, bool overRide);
647 bool EV_MovePoly (line_t *line, int polyNum, int speed, angle_t angle, fixed_t dist, bool overRide);
648 bool EV_MovePolyTo (line_t *line, int polyNum, int speed, fixed_t x, fixed_t y, bool overRide);
649 bool EV_OpenPolyDoor (line_t *line, int polyNum, int speed, angle_t angle, int delay, int distance, podoortype_t type);
650 bool EV_StopPoly (int polyNum);
651 
652 
653 // [RH] Data structure for P_SpawnMapThing() to keep track
654 //		of polyobject-related things.
655 struct polyspawns_t
656 {
657 	polyspawns_t *next;
658 	fixed_t x;
659 	fixed_t y;
660 	short angle;
661 	short type;
662 };
663 
664 extern int po_NumPolyobjs;
665 extern polyspawns_t *polyspawns;	// [RH] list of polyobject things to spawn
666 
667 
668 void PO_Init ();
669 bool PO_Busy (int polyobj);
670 FPolyObj *PO_GetPolyobj(int polyNum);
671 
672 //
673 // P_SPEC
674 //
675 #include "p_spec.h"
676 
677 bool P_AlignFlat (int linenum, int side, int fc);
678 
679 #endif	// __P_LOCAL__
680