Source to src/p_tick.c


Enter a symbol's name here to quickly find it.

#include "doomdef.h"
#include "p_local.h"

int	playertics, thinkertics, sighttics, basetics, latetics;
int	tictics;

boolean		gamepaused;
jagobj_t	*pausepic;

/*
===============================================================================

								THINKERS

All thinkers should be allocated by Z_Malloc so they can be operated on uniformly.  The actual
structures will vary in size, but the first element must be thinker_t.

Mobjs are similar to thinkers, but kept seperate for more optimal list
processing
===============================================================================
*/

thinker_t	thinkercap;	/* both the head and tail of the thinker list */
mobj_t		mobjhead;	/* head and tail of mobj list */
int			activethinkers;	/* debug count */
int			activemobjs;	/* debug count */

/*
===============
=
= P_InitThinkers
=
===============
*/

void P_InitThinkers (void)
{
	thinkercap.prev = thinkercap.next  = &thinkercap;
	mobjhead.next = mobjhead.prev = &mobjhead;
}


/*
===============
=
= P_AddThinker
=
= Adds a new thinker at the end of the list
=
===============
*/

void P_AddThinker (thinker_t *thinker)
{
	thinkercap.prev->next = thinker;
	thinker->next = &thinkercap;
	thinker->prev = thinkercap.prev;
	thinkercap.prev = thinker;
}


/*
===============
=
= P_RemoveThinker
=
= Deallocation is lazy -- it will not actually be freed until its
= thinking turn comes up
=
===============
*/

void P_RemoveThinker (thinker_t *thinker)
{
	thinker->function = (think_t)-1;
}

/*
===============
=
= P_RunThinkers
=
===============
*/

void P_RunThinkers (void)
{
	thinker_t	*currentthinker;
	
	activethinkers = 0;
	
	currentthinker = thinkercap.next;
	while (currentthinker != &thinkercap)
	{
		if (currentthinker->function == (think_t)-1)
		{	/* time to remove it */
			currentthinker->next->prev = currentthinker->prev;
			currentthinker->prev->next = currentthinker->next;
			Z_Free (currentthinker);
		}
		else
		{
			if (currentthinker->function)
			{
				currentthinker->function (currentthinker);
			}
			activethinkers++;
		}
		currentthinker = currentthinker->next;
	}
}


/*============================================================================= */

/*
===============
=
= P_CheckSights
=
= Check sights of all mobj thinkers that are going to change state this
= tic and have MF_COUNTKILL set
===============
*/

void P_CheckSights2 ();

void P_CheckSights (void)
{
#ifdef JAGUAR
	extern	int p_sight_start;
	DSPFunction (&p_sight_start);
#else
	P_CheckSights2 ();
#endif
}

/*============================================================================= */

/* 
=================== 
= 
= P_RunMobjBase  
=
= Run stuff that doesn't happen every tick
=================== 
*/ 

void	P_RunMobjBase (void)
{
#ifdef JAGUAR
	extern	int p_base_start;
	 
	DSPFunction (&p_base_start);
#else
	P_RunMobjBase2 ();
#endif
}

/*============================================================================= */

/* 
=================== 
= 
= P_RunMobjLate  
=
= Run stuff that doesn't happen every tick
=================== 
*/ 

void	P_RunMobjLate (void)
{
	mobj_t	*mo;
	mobj_t	*next;
	
	for (mo=mobjhead.next ; mo != &mobjhead ; mo=next)
	{
		next = mo->next;	/* in case mo is removed this time */
		if (mo->latecall)
		{
			mo->latecall(mo);
		}
	}
}

/*============================================================================= */

/*
==============
=
= P_CheckCheats
=
==============
*/
 
void P_CheckCheats (void)
{
	int		buttons, oldbuttons;
	int 	warpmap;
	int		i;
	player_t	*p;
	
	for (i=0 ; i<MAXPLAYERS ; i++)
	{
		if (!playeringame[i])
			continue;
		buttons = ticbuttons[i];
		oldbuttons = oldticbuttons[i];
	
		if ( (buttons & BT_PAUSE) && !(oldbuttons&BT_PAUSE) )
			gamepaused ^= 1;
	}
	
	if (netgame)
		return;
		
	buttons = ticbuttons[0];
	oldbuttons = oldticbuttons[0];

	if ( (oldbuttons&JP_PAUSE) || !(buttons & JP_PAUSE ) )
		return;

		
	if (buttons&JP_NUM)
	{	/* free stuff */
		p=&players[0];
		for (i=0 ; i<NUMCARDS ; i++)
			p->cards[i] = true;			
		p->armorpoints = 200;
		p->armortype = 2;
		for (i=0;i<NUMWEAPONS;i++) p->weaponowned[i] = true;
		for (i=0;i<NUMAMMO;i++) p->ammo[i] = p->maxammo[i] = 500;
	}

	if (buttons&JP_STAR)
	{	/* godmode */
		players[0].cheats ^= CF_GODMODE;
	}
	warpmap = 0;
	if (buttons&JP_1) warpmap = 1;
	if (buttons&JP_2) warpmap = 2;
	if (buttons&JP_3) warpmap = 3;
	if (buttons&JP_4) warpmap = 4;
	if (buttons&JP_5) warpmap = 5;
	if (buttons&JP_6) warpmap = 6;
	if (buttons&JP_7) warpmap = 7;
	if (buttons&JP_8) warpmap = 8;
	if (buttons&JP_9) warpmap = 9;
	if (buttons&JP_A) warpmap += 10;
	else if (buttons&JP_B) warpmap += 20;
	
	if (warpmap>0 && warpmap < 27)
	{
		gamemap = warpmap;
		gameaction = ga_warped;
	}
}
  

int playernum;

void G_DoReborn (int playernum); 

/*
=================
=
= P_Ticker
=
=================
*/

int		ticphase;

int P_Ticker (void)
{
	int		start;
	int		ticstart;
	player_t	*pl;
	
	ticstart = samplecount;
	
	while (!I_RefreshLatched () )
	;		/* wait for refresh to latch all needed data before */
			/* running the next tick */

#ifdef JAGAUR
	while (DSPRead (&dspfinished) != 0xdef6)
	;		/* wait for sound mixing to complete */
#endif

	gameaction = ga_nothing;
	
	gametic++; 		 
 
/* */
/* check for pause and cheats */
/* */
	P_CheckCheats ();
	
/* */
/* do option screen processing */
/* */

	for (playernum=0,pl=players ; playernum<MAXPLAYERS ; playernum++,pl++)
		if (playeringame[playernum])
			O_Control (pl);


	if (gamepaused)
		return 0;

/* */
/* run player actions */
/* */
	start = samplecount;
	for (playernum=0,pl=players ; playernum<MAXPLAYERS ; playernum++,pl++)
		if (playeringame[playernum])
		{
			if (pl->playerstate == PST_REBORN) 
				G_DoReborn (playernum); 
			AM_Control (pl);
			P_PlayerThink (pl);
		}
	playertics = samplecount - start;
	
	
	start = samplecount;
	P_RunThinkers ();
	thinkertics = samplecount - start;
		
	start = samplecount;
	P_CheckSights ();	
	sighttics = samplecount - start;

	start = samplecount;
	P_RunMobjBase ();
	basetics = samplecount - start;

	start = samplecount;
	P_RunMobjLate ();
	latetics = samplecount - start;

	P_UpdateSpecials ();

	P_RespawnSpecials ();
	
	ST_Ticker ();			/* update status bar */
		
	tictics = samplecount - ticstart;
	
	return gameaction;		/* may have been set to ga_died, ga_completed, */
							/* or ga_secretexit */
}


/* 
============= 
= 
= DrawPlaque 
= 
============= 
*/ 
 
void DrawPlaque (jagobj_t *pl)
{
#ifdef JAGUAR
	int			x,y,w;
	short		*sdest;
	byte		*bdest, *source;
	extern		int isrvmode;
	
	while ( !I_RefreshCompleted () )
	;

	bufferpage = (byte *)screens[!workpage];
	source = pl->data;
	
	if (isrvmode == 0xc1 + (3<<9) )
	{	/* 320 mode, stretch pixels */
		bdest = (byte *)bufferpage + 80*320 + (160 - pl->width);
		w = pl->width;
		for (y=0 ; y<pl->height ; y++)
		{
			for (x=0 ; x<w ; x++)
			{
				bdest[x*2] = bdest[x*2+1] = *source++;
			}
			bdest += 320;
		}
	}
	else
	{	/* 160 mode, draw directly */
		sdest = (short *)bufferpage + 80*160 + (80 - pl->width/2);
		w = pl->width;
		for (y=0 ; y<pl->height ; y++)
		{
			for (x=0 ; x<w ; x++)
			{
				sdest[x] = palette8[*source++];
			}
			sdest += 160;
		}
	}
	
#endif
}

/* 
============= 
= 
= DrawPlaque 
= 
============= 
*/ 
 
void DrawSinglePlaque (jagobj_t *pl)
{
	int			x,y,w;
	byte		*bdest, *source;
	
	while ( !I_RefreshCompleted () )
	;

	bufferpage = (byte *)screens[!workpage];
	source = pl->data;
	
	bdest = (byte *)bufferpage + 80*320 + (160 - pl->width/2);
	w = pl->width;
	for (y=0 ; y<pl->height ; y++)
	{
		for (x=0 ; x<w ; x++)
			bdest[x] = *source++;
		bdest += 320;
	}
}


/* 
============= 
= 
= P_Drawer 
= 
= draw current display 
============= 
*/ 
 
 
void P_Drawer (void) 
{ 	
	static boolean	refreshdrawn;
#ifndef MARS
	if (players[consoleplayer].automapflags & AF_OPTIONSACTIVE)
	{
		O_Drawer ();
		refreshdrawn = false;
	}
	else if (gamepaused && refreshdrawn)
		DrawPlaque (pausepic);
	else if (players[consoleplayer].automapflags & AF_ACTIVE)
	{
		ST_Drawer ();
		AM_Drawer ();
		I_Update ();
		refreshdrawn = true;
	}
	else
#endif
	{
#ifdef JAGUAR
		ST_Drawer ();
#endif
		R_RenderPlayerView (); 
		refreshdrawn = true;
	/* assume part of the refresh is now running parallel with main code */
	}
} 
 
 
extern	 int		ticremainder[2];

void P_Start (void)
{
#ifndef MARS
	AM_Start ();
	S_RestartSounds ();
#endif
	players[0].automapflags = 0;
	players[1].automapflags = 0;
	ticremainder[0] = ticremainder[1] = 0;
	M_ClearRandom ();
}

void P_Stop (void)
{
	Z_FreeTags (mainzone);
}