/* Emacs style mode select   -*- C++ -*- */
/*-----------------------------------------------------------------------------*/

/* $Id:$*/

/* Copyright (C) 1993-1996 by id Software, Inc.*/

/* This source is available for distribution and/or modification*/
/* only under the terms of the DOOM Source Code License as*/
/* published by id Software. All rights reserved.*/

/* The source is distributed in the hope that it will be useful,*/
/* but WITHOUT ANY WARRANTY; without even the implied warranty of*/
/* FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License*/
/* for more details.*/

/* DESCRIPTION:*/
/*	Play functions, animation, global header.*/

/*-----------------------------------------------------------------------------*/


#ifndef __P_LOCAL__
#define __P_LOCAL__

#ifndef __R_LOCAL__
#include "r_local.h"
#endif

#define FLOATSPEED		(FRACUNIT*4)


/* For DeHackEd it's better to make this a variable */
/*#define MAXHEALTH		100*/
extern int MaxHealth;
extern int MaxArmor;
extern int GreenArmorClass;
extern int BlueArmorClass;
extern int MegasphereHealth;
extern int SoulsphereHealth;
extern int MaxSoulsphere;

extern int maxammo[4];
extern int clipammo[4];


#define VIEWHEIGHT		(41*FRACUNIT)

/* mapblocks are used to check movement*/
/* against lines and things*/
#define MAPBLOCKUNITS	128
#define MAPBLOCKSIZE	(MAPBLOCKUNITS*FRACUNIT)
#define MAPBLOCKSHIFT	(FRACBITS+7)
#define MAPBMASK		(MAPBLOCKSIZE-1)
#define MAPBTOFRAC		(MAPBLOCKSHIFT-FRACBITS)


/* player radius for movement checking*/
#define PLAYERRADIUS	16*FRACUNIT

/* MAXRADIUS is for precalculated sector block boxes*/
/* the spider demon is larger,*/
/* but we do not have any moving sectors nearby*/
#define MAXRADIUS		32*FRACUNIT

#define GRAVITY		FRACUNIT
#define MAXMOVE		(30*FRACUNIT)

#define USERANGE		(64*FRACUNIT)
#define MELEERANGE		(64*FRACUNIT)
#define MISSILERANGE	(32*64*FRACUNIT)

/* follow a player exlusively for 3 seconds*/
#define	BASETHRESHOLD	 	100




/* P_TICK*/


/* both the head and tail of the thinker list*/
extern	thinker_t	thinkercap;


void P_InitThinkers (void);
void P_AddThinker (thinker_t* thinker);
void P_RemoveThinker (thinker_t* thinker);



/* P_PSPR*/

void P_SetupPsprites (player_t* curplayer);
void P_MovePsprites (player_t* curplayer);
void P_DropWeapon (player_t* player);



/* P_USER*/

void	P_PlayerThink (player_t* player);
#ifndef FULL_NEW_FEATURES
/* For jump/float cheat (if full new features this is embedded in ticcmd_t) */
extern int	vertical_acceleration;
#endif



/* P_MOBJ*/

#define ONFLOORZ		MININT
#define ONCEILINGZ		MAXINT

/* Time interval for item respawning.*/
#define ITEMQUESIZE		128

extern mapthing_t	itemrespawnque[ITEMQUESIZE];
extern int		itemrespawntime[ITEMQUESIZE];
extern int		iquehead;
extern int		iquetail;


void P_RespawnSpecials (void);

mobj_t*
P_SpawnMobj
( fixed_t	x,
  fixed_t	y,
  fixed_t	z,
  mobjtype_t	type );

void 	P_RemoveMobj (mobj_t* th);
boolean	P_SetMobjState (mobj_t* mobj, statenum_t state);
void 	P_MobjThinker (mobj_t* mobj);

void	P_SpawnPuff (fixed_t x, fixed_t y, fixed_t z);
void 	P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage);
mobj_t* P_SpawnMissile (mobj_t* source, mobj_t* dest, mobjtype_t type);
void	P_SpawnPlayerMissile (mobj_t* source, mobjtype_t type);
void	P_SpawnPlayer(mapthing_t *mthing);
void	P_SpawnMapThing(mapthing_t *mthing);



/* P_ENEMY*/

extern int	TRACEANGLE;

void P_NoiseAlert (mobj_t* target, mobj_t* emmiter);



/* P_MAPUTL*/

typedef struct
{
    fixed_t	x;
    fixed_t	y;
    fixed_t	dx;
    fixed_t	dy;

} divline_t;

typedef struct
{
    fixed_t	frac;		/* along trace line*/
    boolean	isaline;
    union {
	mobj_t*	thing;
	line_t*	line;
    }			d;
} intercept_t;

extern intercept_t*	intercepts;
extern intercept_t*	intercept_p;
extern int		maxintercepts;

void    P_InitIntercepts(void);

typedef boolean (*traverser_t) (intercept_t *in);

fixed_t P_AproxDistance (fixed_t dx, fixed_t dy);
int 	P_PointOnLineSide (fixed_t x, fixed_t y, const line_t* line);
int 	P_PointOnDivlineSide (fixed_t x, fixed_t y, const divline_t* line);
void 	P_MakeDivline (const line_t* li, divline_t* dl);
fixed_t P_InterceptVector (const divline_t* v2, const divline_t* v1);
int 	P_BoxOnLineSide (const fixed_t* tmbox, const line_t* ld);

extern fixed_t		opentop;
extern fixed_t 		openbottom;
extern fixed_t		openrange;
extern fixed_t		lowfloor;

void 	P_LineOpening (const line_t* linedef);

#ifndef DIYINLINE
/* otherwise the functions are static */
boolean P_BlockLinesIterator (int x, int y, boolean(*func)(line_t*) );
boolean P_BlockThingsIterator (int x, int y, boolean(*func)(mobj_t*) );
#endif

#define PT_ADDLINES		1
#define PT_ADDTHINGS	2
#define PT_EARLYOUT		4

extern divline_t	trace;

boolean
P_PathTraverse
( fixed_t	x1,
  fixed_t	y1,
  fixed_t	x2,
  fixed_t	y2,
  int		flags,
  boolean	(*trav)(intercept_t *));

void P_UnsetThingPosition (mobj_t* thing);
void P_SetThingPosition (mobj_t* thing);



/* P_MAP*/


/* dynamic spechit structure */
extern line_t**		spechit;
extern int		maxspechit;
extern int		numspechit;

void	P_InitSpechits(void);


/* If "floatok" true, move would be ok*/
/* if within "tmfloorz - tmceilingz".*/
extern boolean		floatok;
extern fixed_t		tmfloorz;
extern fixed_t		tmceilingz;

extern fixed_t		attackrange;

extern line_t*		ceilingline;

#ifdef DIYBOOM
extern msecnode_t*	sector_list;
extern msecnode_t*	headsecnode;
extern fixed_t		tmbbox[4];
#endif

boolean P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y);
#ifdef DIYBOOM
boolean P_TryMove (mobj_t* thing, fixed_t x, fixed_t y, boolean dropoff);
#else
boolean P_TryMove (mobj_t* thing, fixed_t x, fixed_t y);
# define P_TryMove(t,x,y,d) (P_TryMove)((t),(x),(y))
#endif
boolean P_TeleportMove (mobj_t* thing, fixed_t x, fixed_t y);
void	P_SlideMove (mobj_t* mo);
boolean P_CheckSight (const mobj_t* t1, const mobj_t* t2);
void 	P_UseLines (const player_t* player);

boolean P_ChangeSector (sector_t* sector, boolean crunch);

#ifdef DIYBOOM
extern int  P_GetMoveFactor(mobj_t *mo);
extern void P_DelSeclist(msecnode_t *node);
extern void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y);
boolean Check_Sides(mobj_t *, int, int);
#endif

extern mobj_t*	linetarget;	/* who got hit (or NULL)*/

fixed_t
P_AimLineAttack
( mobj_t*	t1,
  angle_t	angle,
  fixed_t	distance );

void
P_LineAttack
( mobj_t*	t1,
  angle_t	angle,
  fixed_t	distance,
  fixed_t	slope,
  int		damage );

void
P_RadiusAttack
( mobj_t*	spot,
  mobj_t*	source,
  int		damage );




/* P_SETUP*/

#ifdef DIYBOOM
typedef long blockmap_t;
#else
typedef short blockmap_t;
#endif
extern byte*		rejectmatrix;	/* for fast sight rejection*/
extern blockmap_t*	blockmaplump;	/* offsets in blockmap are from here*/
extern blockmap_t*	blockmap;
extern int		bmapwidth;
extern int		bmapheight;	/* in mapblocks*/
extern fixed_t		bmaporgx;
extern fixed_t		bmaporgy;	/* origin of block map*/
extern mobj_t**		blocklinks;	/* for thing chains*/




/* P_INTER*/

extern int		maxammo[NUMAMMO];
extern int		clipammo[NUMAMMO];

void
P_TouchSpecialThing
( mobj_t*	special,
  mobj_t*	toucher );

void
P_DamageMobj
( mobj_t*	target,
  mobj_t*	inflictor,
  mobj_t*	source,
  int		damage );



/* P_SIGHT */

extern fixed_t	topslope;
extern fixed_t	bottomslope;


/* P_SPEC*/

#include "p_spec.h"


#endif	/* __P_LOCAL__*/
/*-----------------------------------------------------------------------------*/

/* $Log:$*/

/*-----------------------------------------------------------------------------*/


