// 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.
//
// $Log:$
//
// DESCRIPTION:
//		Ticker.
//
//-----------------------------------------------------------------------------


#include "z_zone.h"
#include "p_local.h"
#include "p_effect.h"
#include "p_acs.h"
#include "c_console.h"
#include "b_bot.h"
#include "cl_main.h"
#include "doomstat.h"
#include "c_dispatch.h"

extern constate_e ConsoleState;
extern gamestate_t wipegamestate;

EXTERN_CVAR (cl_predict_players)

void P_XYMovement (AActor *mo);
void P_ZMovement (AActor *mo);

botspawn_t botspawn[MAXPLAYERS];	// [BC]

//
// P_Ticker
//

void P_Ticker (void)
{
	if (netstate == NS_CLIENT)
	{
		if (noservermsgs)
			return;

		P_ThinkParticles ();   // [RH] make the particles think

		for (int i=0; i<MAXPLAYERS; i++)
		{
			if (!playeringame[i] || i==consoleplayer)
				continue;

			player_t *player = &players[i];

			if (!player->mo)
				continue;

			// Counter, time dependent invisibility.
			if (player->powers[pw_invisibility])
				if (! --player->powers[pw_invisibility] )
					player->mo->flags &= ~MF_SHADOW;
		
			if (player->last_received == gametic)
				continue;

			// [BC] Do chatting and stuff
			P_MedalThink (&players[i]);

			// predict players
			if (cl_predict_players.value || player->last_received == gametic-1 )
				player->mo->RunThink();
		}

		DThinker::RunThinkers ();

		P_UpdateSpecials ();

		P_RunEffects ();	// [RH] Run particle effects

		// [BC] Return dropped sitting skulls
		if (teamgame.value)
		{
			for (int i=0; i<NUMTEAMS; i++)
			{
				if (teams[i].returnTics)
				{
					if (!(--teams[i].returnTics))
					{
						if (i == TM_BLUE)
							P_StartTeam1ReturnScripts ();
						else
							P_StartTeam2ReturnScripts ();
//						teams[i].returnroutine;
					}
				}
			}
		}

		// for par times
		level.time++;
	}
	else if (netstate == NS_SERVER)
	{
	    // [csDoom] if the floor or the ceiling of a sector is moving,
		// mark it as moveable
	    for (int i=0; i<numsectors; i++)
		{
			sector_t* sec = &sectors[i];

	        if (sec->ceilingdata && sec->ceilingdata->IsKindOf (RUNTIME_CLASS(DMover)))
		        sec->moveable = true;

			if (sec->floordata && sec->floordata->IsKindOf (RUNTIME_CLASS(DMover)))
				sec->moveable = true;
		}
	
		// [BC] Think for bots
		for (i = 0; i<MAXPLAYERS; i++)
		{
			if (playeringame[i] && players[i].skullb)
			{
				P_PlayerThink (&players[i]);
				players[i].mo->RunThink();
			}
		}

		DThinker::RunThinkers ();

		P_UpdateSpecials ();
	    P_RespawnSpecials ();

		// for par times
	    level.time++;

		// [BC] Return dropped sitting skulls
		if (teamgame.value)
		{
			for (int i=0; i<NUMTEAMS; i++)
			{
				if (teams[i].returnTics)
				{
					if (!(--teams[i].returnTics))
					{
						if (i == TM_BLUE)
							P_StartTeam1ReturnScripts ();
						else
							P_StartTeam2ReturnScripts ();
					}
//						teams[i].returnroutine;
				}
			}
		}
	}
	else
	{
		int i;

		// run the tic
		if (paused)
			return;

		// pause if in menu or console and at least one tic has been run
		if ((menuactive || ConsoleState == c_down || ConsoleState == c_falling)
			&& !demoplayback
			&& !demorecording
			&& players[consoleplayer].viewz != 1
			&& wipegamestate == gamestate)
		{
			return;
		}

		P_ThinkParticles ();	// [RH] make the particles think

		// [BC] Spawn in bots for skirmish games
		for (i=0; i<MAXPLAYERS; i++)
		{
			if (botspawn[i].tics)
				if (!--botspawn[i].tics)
				{
					char str[80];
					sprintf (str, "addbot \"%s\"", botspawn[i].name);
					AddCommandString (str);
				}
		}

		for (i = 0; i<MAXPLAYERS; i++)
			if (playeringame[i])
				P_PlayerThink (&players[i]);

		DThinker::RunThinkers ();

		if (!freeze)
		{
			P_UpdateSpecials ();
			P_RespawnSpecials ();
		}

		// [RH] Apply falling damage
		for (i = 0; i < MAXPLAYERS; i++)
			if (playeringame[i] && players[i].mo)
			{
				P_FallingDamage (players[i].mo);

				players[i].oldvelocity[0] = players[i].mo->momx;
				players[i].oldvelocity[1] = players[i].mo->momy;
				players[i].oldvelocity[2] = players[i].mo->momz;
			}

		P_RunEffects ();	// [RH] Run particle effects

		// for par times
		level.time++;

		// [BC] Return dropped sitting skulls
		if (teamgame.value)
		{
			for (int i=0; i<NUMTEAMS; i++)
			{
				if (teams[i].returnTics)
				{
					if (!(--teams[i].returnTics))
					{
						if (i == TM_BLUE)
							P_StartTeam1ReturnScripts ();
						else
							P_StartTeam2ReturnScripts ();
//						teams[i].returnroutine;
					}
				}
			}
		}
	}
}
