Esempio n. 1
0
bool CSDKBot::ThinkFlag() {
	CFlag* pFlag = m_PlayerSearchInfo.CloseEnemyFlagVisible();

	if (IsCapturingEnemyFlagAttempt()) {
		if (!m_bLastThinkWasInFlag) {
			m_bLastThinkWasInFlag = true;
			if (bot_randfloat() < 0.4f && ShouldReload()) {
				m_curCmd.buttons |= IN_RELOAD;
			}
			m_flNextStrafeTime = gpGlobals->curtime;
		}

		CBasePlayer* pEnemy = m_PlayerSearchInfo.CloseEnemy();
		if (pEnemy) {
			LookAt(pEnemy->Weapon_ShootPosition(), 0.7f, 3);
			if (pFlag)
				DanceAround(pFlag->GetAbsOrigin(), pFlag->m_flCaptureRadius);
			if (bot_randfloat() < 0.3f)
				m_flNextFireTime = gpGlobals->curtime;
		}
		else {
			StopMoving();
		}
	} else {
		m_bLastThinkWasInFlag = false;

		if (pFlag) {
			m_curCmd.buttons |= IN_FORWARD;
			LookAt(pFlag->GetAbsOrigin() + g_vUpFromFlag, 0.8f, 5);
		}
		TeammateGoAround(true);
	}
	return true;
}
Esempio n. 2
0
void DrawScene(void)
{

	//Render Europe:
	glEnable(GL_LIGHTING);
	FlagTexture2.SetActive();
	Flag.Render();

	//Render Germany:
	glEnable(GL_LIGHTING);
	FlagTexture1.SetActive();
	glPushMatrix();
		glTranslatef(2.5,0.0,2.5);
		Flag.Render();
	glPopMatrix();

	//Render Portugal:
	glEnable(GL_LIGHTING);
	FlagTexture3.SetActive();
	glPushMatrix();
		glTranslatef(-2.5,0.0,2.5);
		Flag.Render();
	glPopMatrix();

	//Render ground:
	GroundTexture.SetActive();
	glEnable(GL_TEXTURE_2D);
	glDisable(GL_LIGHTING);
	float HalfGroundSize = 20.0f;

	glTranslatef(0.0,-4.0,0.0);
	glBegin(GL_POLYGON);
	  
	  glNormal3f(0.0,1.0,0.0);
	  
	  glTexCoord2f(0.0,0.0);
	  glVertex3f(-HalfGroundSize, 0.0, -HalfGroundSize);
	  glTexCoord2f(0.0,1.0);
	  glVertex3f(-HalfGroundSize, 0.0, +HalfGroundSize);
	  glTexCoord2f(1.0,1.0);
	  glVertex3f(+HalfGroundSize, 0.0, +HalfGroundSize);
	  glTexCoord2f(1.0,0.0);
	  glVertex3f(+HalfGroundSize, 0.0, -HalfGroundSize);
	  

	glEnd();


}
Esempio n. 3
0
bool CSDKBot::ThinkLongRange() {
	m_curCmd.buttons |= IN_FORWARD;
	Vector lookTarget;
	CBasePlayer* pEnemy = m_PlayerSearchInfo.CloseEnemy();
	CFlag* pFlag = m_PlayerSearchInfo.CloseEnemyFlagVisible();
	//if there's a flag move towards the flag as well
	if (pEnemy && pFlag) {
		lookTarget = LerpVector(pFlag->GetAbsOrigin(), pEnemy->Weapon_ShootPosition(), 0.3f);
	} else if (pEnemy) {
		lookTarget = pEnemy->Weapon_ShootPosition();
	}
	LookAt(lookTarget, 0.6f, 5.f);
	TeammateGoAround(true);
	return true;
}
Esempio n. 4
0
void UpdateScene( float deltaTime)
{
	wind.x= 0.2+float(rand())/float(RAND_MAX)*0.1;

	
	
	Flag.UpdateVertices(deltaTime,gravity, wind);
}
Esempio n. 5
0
//-------------------------------------------------------------------------------------------------
// Purpose: Checks if we should fight nearest enemy or run to flag, if we're already in a mid-range engagement
//-------------------------------------------------------------------------------------------------
bool CSDKBot::ThinkCheckFlagOrFight() {
	CFlag* pFlag = m_PlayerSearchInfo.CloseEnemyFlagVisible();
	CBasePlayer* pEnemy = m_PlayerSearchInfo.CloseEnemy();
	if (pFlag && pEnemy) {
		float enemyDistanceToFlag = (pEnemy->GetAbsOrigin() - pFlag->GetAbsOrigin()).Length();
		float ourDistanceToFlag = (m_PlayerSearchInfo.OwnerOrigin() - pFlag->GetAbsOrigin()).Length();
		if (m_pCurThinker != &BotThinkers::Flag /*No self-scheduling!*/ 
			&& enemyDistanceToFlag > 100 //don't bother if they're on the flag
			&& enemyDistanceToFlag > ourDistanceToFlag && m_PlayerSearchInfo.CloseEnemyDist() > MELEE_RANGE_START) {
			m_bTowardFlag = true;
			ScheduleThinker(&BotThinkers::Flag, 0.1f);
			return false;
		}

		//also check if we should exit flag to med-range
		if (m_pCurThinker == &BotThinkers::Flag && m_PlayerSearchInfo.CloseEnemyDist() < ourDistanceToFlag) {
			ScheduleThinker(&BotThinkers::MedRange, 0.1f);
			return false;
		}
	}
	return true;
}
Esempio n. 6
0
bool CPlayer::SetSpectatorID(int SpecMode, int SpectatorID)
{
	if((SpecMode == m_SpecMode && SpecMode != SPEC_PLAYER) ||
		(m_SpecMode == SPEC_PLAYER && SpecMode == SPEC_PLAYER && (SpectatorID == -1 || m_SpectatorID == SpectatorID || m_ClientID == SpectatorID)))
	{
		return false;
	}

	if(m_Team == TEAM_SPECTATORS)
	{
		// check for freeview or if wanted player is playing
		if(SpecMode != SPEC_PLAYER || (SpecMode == SPEC_PLAYER && GameServer()->m_apPlayers[SpectatorID] && GameServer()->m_apPlayers[SpectatorID]->GetTeam() != TEAM_SPECTATORS))
		{
			if(SpecMode == SPEC_FLAGRED || SpecMode == SPEC_FLAGBLUE)
			{
				CFlag *pFlag = (CFlag*)GameServer()->m_World.FindFirst(CGameWorld::ENTTYPE_FLAG);
				while (pFlag)
				{
					if ((pFlag->GetTeam() == TEAM_RED && SpecMode == SPEC_FLAGRED) || (pFlag->GetTeam() == TEAM_BLUE && SpecMode == SPEC_FLAGBLUE))
					{
						m_pSpecFlag = pFlag;
						if (pFlag->GetCarrier())
							m_SpectatorID = pFlag->GetCarrier()->GetPlayer()->GetCID();
						else
							m_SpectatorID = -1;
						break;
					}
					pFlag = (CFlag*)pFlag->TypeNext();
				}
				if (!m_pSpecFlag)
					return false;
				m_SpecMode = SpecMode;
				return true;
			}
			m_pSpecFlag = 0;
			m_SpecMode = SpecMode;
			m_SpectatorID = SpectatorID;
			return true;
		}
	}
	else if(m_DeadSpecMode)
	{
		// check if wanted player can be followed
		if(SpecMode == SPEC_PLAYER && GameServer()->m_apPlayers[SpectatorID] && DeadCanFollow(GameServer()->m_apPlayers[SpectatorID]))
		{
			m_SpecMode = SpecMode;
			m_pSpecFlag = 0;
			m_SpectatorID = SpectatorID;
			return true;
		}
	}

	return false;
}
Esempio n. 7
0
void CGameControllerCTF::Tick()
{
	IGameController::Tick();

	if(GameServer()->m_World.m_ResetRequested || GameServer()->m_World.m_Paused)
		return;

	for(int fi = 0; fi < 2; fi++)
	{
		CFlag *F = m_apFlags[fi];

		if(!F)
			continue;

		// flag hits death-tile or left the game layer, reset it
		if(GameServer()->Collision()->GetCollisionAt(F->m_Pos.x, F->m_Pos.y)&CCollision::COLFLAG_DEATH || F->GameLayerClipped(F->m_Pos))
		{
			GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", "flag_return");
			GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN);
			F->Reset();
			continue;
		}

		//
		if(F->m_pCarryingCharacter)
		{
			// update flag position
			F->m_Pos = F->m_pCarryingCharacter->m_Pos;

			if(m_apFlags[fi^1] && m_apFlags[fi^1]->m_AtStand)
			{
				if(distance(F->m_Pos, m_apFlags[fi^1]->m_Pos) < CFlag::ms_PhysSize + CCharacter::ms_PhysSize)
				{
					// CAPTURE! \o/
					m_aTeamscore[fi^1] += 100;
					F->m_pCarryingCharacter->GetPlayer()->m_Score += 5;

					char aBuf[512];
					str_format(aBuf, sizeof(aBuf), "flag_capture player='%d:%s'",
						F->m_pCarryingCharacter->GetPlayer()->GetCID(),
						Server()->ClientName(F->m_pCarryingCharacter->GetPlayer()->GetCID()));
					GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);

					float CaptureTime = (Server()->Tick() - F->m_GrabTick)/(float)Server()->TickSpeed();
					if(CaptureTime <= 60)
					{
						str_format(aBuf, sizeof(aBuf), "The %s flag was captured by '%s' (%d.%s%d seconds)", fi ? "blue" : "red", Server()->ClientName(F->m_pCarryingCharacter->GetPlayer()->GetCID()), (int)CaptureTime%60, ((int)(CaptureTime*100)%100)<10?"0":"", (int)(CaptureTime*100)%100);
					}
					else
					{
						str_format(aBuf, sizeof(aBuf), "The %s flag was captured by '%s'", fi ? "blue" : "red", Server()->ClientName(F->m_pCarryingCharacter->GetPlayer()->GetCID()));
					}
					GameServer()->SendChat(-1, -2, aBuf);
					for(int i = 0; i < 2; i++)
						m_apFlags[i]->Reset();

					GameServer()->CreateSoundGlobal(SOUND_CTF_CAPTURE);
				}
			}
		}
		else
		{
			CCharacter *apCloseCCharacters[MAX_CLIENTS];
			int Num = GameServer()->m_World.FindEntities(F->m_Pos, CFlag::ms_PhysSize, (CEntity**)apCloseCCharacters, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
			for(int i = 0; i < Num; i++)
			{
				if(!apCloseCCharacters[i]->IsAlive() || apCloseCCharacters[i]->GetPlayer()->GetTeam() == TEAM_SPECTATORS || GameServer()->Collision()->IntersectLine(F->m_Pos, apCloseCCharacters[i]->m_Pos, NULL, NULL))
					continue;

				if(apCloseCCharacters[i]->GetPlayer()->GetTeam() == F->m_Team)
				{
					// return the flag
					if(!F->m_AtStand)
					{
						CCharacter *pChr = apCloseCCharacters[i];
						pChr->GetPlayer()->m_Score += 1;

						char aBuf[256];
						str_format(aBuf, sizeof(aBuf), "flag_return player='%d:%s'",
							pChr->GetPlayer()->GetCID(),
							Server()->ClientName(pChr->GetPlayer()->GetCID()));
						GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);

						GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN);
						F->Reset();
					}
				}
				else
				{
					// take the flag
					if(F->m_AtStand)
					{
						m_aTeamscore[fi^1]++;
						F->m_GrabTick = Server()->Tick();
					}

					F->m_AtStand = 0;
					F->m_pCarryingCharacter = apCloseCCharacters[i];
					F->m_pCarryingCharacter->GetPlayer()->m_Score += 1;

					char aBuf[256];
					str_format(aBuf, sizeof(aBuf), "flag_grab player='%d:%s'",
						F->m_pCarryingCharacter->GetPlayer()->GetCID(),
						Server()->ClientName(F->m_pCarryingCharacter->GetPlayer()->GetCID()));
					GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);

					for(int c = 0; c < MAX_CLIENTS; c++)
					{
						CPlayer *pPlayer = GameServer()->m_apPlayers[c];
						if(!pPlayer)
							continue;

						if(pPlayer->GetTeam() == TEAM_SPECTATORS && pPlayer->m_SpectatorID != SPEC_FREEVIEW && GameServer()->m_apPlayers[pPlayer->m_SpectatorID] && GameServer()->m_apPlayers[pPlayer->m_SpectatorID]->GetTeam() == fi)
							GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, c);
						else if(pPlayer->GetTeam() == fi)
							GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, c);
						else
							GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_PL, c);
					}
					// demo record entry
					GameServer()->CreateSoundGlobal(SOUND_CTF_GRAB_EN, -2);
					break;
				}
			}

			if(!F->m_pCarryingCharacter && !F->m_AtStand)
			{
				if(Server()->Tick() > F->m_DropTick + Server()->TickSpeed()*30)
				{
					GameServer()->CreateSoundGlobal(SOUND_CTF_RETURN);
					F->Reset();
				}
				else
				{
					F->m_Vel.y += GameServer()->m_World.m_Core.m_Tuning.m_Gravity;
					GameServer()->Collision()->MoveBox(&F->m_Pos, &F->m_Vel, vec2(F->ms_PhysSize, F->ms_PhysSize), 0.5f);
				}
			}
		}
	}
}
Esempio n. 8
0
int main (int argc, char **argv)
{
	//Initialize GLUT
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
	glutInitWindowSize(600,600);
	//Create a window with rendering context and everything else we need
	glutCreateWindow("Flag in the wind");


	//load the textures:
	FlagTexture1.LoadFromFile("germany.bmp");
	FlagTexture2.LoadFromFile("europe.bmp");
	FlagTexture3.LoadFromFile("portugal.bmp");
	GroundTexture.LoadFromFile("ground.bmp");

	//init texture stuff:
	GroundTexture.SetActive();
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	FlagTexture1.SetActive();
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	FlagTexture2.SetActive();
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

	FlagTexture3.SetActive();
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);


	//initialize the flag:
	Flag.Initialize(40,26,2.0f,50.0f,0.997f);
	//and the values affecting it:
	wind = F3dVector (0.2,0.04,0.00);
	gravity = F3dVector(0.0,-0.015,0.0005);

	//initialize camera: 
	Camera.Move(F3dVector(1.0f, 0.0f, 15.0f));


	//Enable the vertex array functionality:
	glEnableClientState(GL_VERTEX_ARRAY);
	glEnableClientState(GL_NORMAL_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY );
	glClearColor(0.0,0.0,1.0,0.0);  //blue background = sky ;-)
	
	//Switch on solid rendering:
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	glLightModeli(GL_LIGHT_MODEL_TWO_SIDE ,1);
	glEnable(GL_DEPTH_TEST);

	//Initialize lighting:
	glEnable(GL_LIGHT1);								
	glEnable(GL_LIGHT2);

	glEnable(GL_LIGHTING);

	glFrontFace(GL_CCW);   //Tell OGL which orientation shall be the front face
	glShadeModel(GL_SMOOTH);

	//initialize generation of random numbers:
	srand((unsigned)time(NULL));

	
	//Assign the two used Msg-routines
	glutDisplayFunc(Display);
	glutReshapeFunc(Reshape);
	glutKeyboardFunc(KeyDown);
	glutIdleFunc(Idle);
	//Let GLUT get the msgs
	glutMainLoop();
	return 0;
}
EStatus ActionFollowPlan(const float frametime, CBot* bot)
{
	// TODO - Doesn't account for multiple team players/ dropping the flag
	bot->SetState(ai::EBotState::BotStateGetFlag);

	bot->SetSpeed( bot->GetMaxSpeed() );

	if (!bot->IsTreeNodeInit())
	{
		int* teamFlags;
		int flagSize;
		CFlag* flag = NULL;
		
		if (bot->GetTeam() == 1)
		{
			CGameData::GetInstance()->GetTeamBFlags(&teamFlags, flagSize);
		}
		else
		{
			CGameData::GetInstance()->GetTeamAFlags(&teamFlags, flagSize);
		}

		for (int i = 0; i < flagSize; i++)
		{
			flag = (CFlag*) CEntityList::GetInstance()->GetEntity(teamFlags[i]);

			if (flag->HasFlagHolder() == NULL ||
				flag->HasFlagHolder()->GetUID() == bot->GetUID())
			{
				flagID = flag->GetUID();
				break;
			}
			flag = NULL;
		}

		if ( flag != NULL && !bot->GotFlag() && bot->CreatePath( flag->GetWaypoint() ) )
		{
			bot->SetTreeNodeInit();
			return Running;
		}
		else if ( flag != NULL && bot->GotFlag() && bot->CreatePath( bot->GetHomeBaseWP() ) )
		{
			bot->SetTreeNodeInit();
			return Running;
		}
		else if ( bot->GetWaypoint() == flag->GetWaypoint())
		{
			bot->SetTreeNodeInit();
			return Running;
		}
		else
		{
			bot->SetSpeed( 0.0f );
			return Fail;
		}
	}
	else if ( bot->AtDestination() )
	{
		if (!bot->HasFlag())
		{
			bot->PickupFlag();

			if ( !bot->HasFlag() )
			{
				// catches error  when no flag is found
				CFlag* flag = (CFlag*) CEntityList::GetInstance()->GetEntity(flagID);

				if (flag != NULL)
				{
					if (bot->GetWaypoint() == flag->GetWaypoint())
					{
						bot->MoveToLOSPosition( flag->GetPosition() );
					}
					else
					{
						bot->SetTreePos( bot->GetTreePos() );
					}				
					
					return Running;
				}
				return Fail;
			}

			if ( bot->CreatePath( bot->GetHomeBaseWP() ) )
			{
				return Running;
			}
			else
			{
				bot->SetSpeed( 0.0f );
				return Fail;
			}
		}
		else
		{
			// got the enemy flag to the home base
			// CALL FOR END OF GAME
			bot->DropFlag();
			bot->SetSpeed( 0.0f );
			return Pass;
		}
	}

	return Running;
}
Esempio n. 10
0
void CGameControllerEXP::Tick()
{
	IGameController::Tick();

	TickBots();
	TickEnvironment();

	for(int fi = 0; fi < m_CurFlag+1; fi++)
	{
		CFlag *f = NULL;
		if(fi == m_CurFlag)
			f = m_FlagEnd;
		else
			f = m_aFlagsCP[fi];
		if(!f) // if there isn't flag end
			continue;
		
		CCharacter *apCloseCharacters[MAX_CLIENTS];
		int Num = GameServer()->m_World.FindEntities(f->GetPos(), CFlag::ms_PhysSize, (CEntity**)apCloseCharacters, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
		for(int i = 0; i < Num; i++)
		{
			if(!apCloseCharacters[i]->IsAlive() || apCloseCharacters[i]->GetPlayer()->IsBot() || apCloseCharacters[i]->GetPlayer()->GetTeam() == -1)
				continue;
			int id = apCloseCharacters[i]->GetPlayer()->GetCID();
			
			if(fi == m_CurFlag)
			{
				// END
				if(!m_Boss.m_Exist || GameServer()->m_apPlayers[id]->m_GameExp.m_BossKiller)
					StopClient(id);
			}
			else
			{
				// REGEN
				if((float)Server()->Tick() > apCloseCharacters[i]->GetPlayer()->m_GameExp.m_RegenTimer + GameServer()->Tuning()->m_RegenTimer*Server()->TickSpeed())
				{
					if(apCloseCharacters[i]->m_Health < 10) //regen health
					{
						apCloseCharacters[i]->m_Health++;
						apCloseCharacters[i]->GetPlayer()->m_GameExp.m_RegenTimer = (float)Server()->Tick();
					}
					else if(apCloseCharacters[i]->m_Armor < apCloseCharacters[i]->GetPlayer()->m_GameExp.m_ArmorMax) //regen armor
					{
						apCloseCharacters[i]->m_Armor++;
						apCloseCharacters[i]->GetPlayer()->m_GameExp.m_RegenTimer = (float)Server()->Tick();
					}
					else // regen ammo
					{
						int WID = apCloseCharacters[i]->m_ActiveWeapon;
						if(apCloseCharacters[i]->m_aWeapons[WID].m_Ammo != -1)
						{
							int MaxAmmo = g_pData->m_Weapons.m_aId[WID].m_Maxammo;
							if(apCloseCharacters[i]->m_aWeapons[WID].m_Ammo < MaxAmmo)
							{
								apCloseCharacters[i]->m_aWeapons[WID].m_Ammo++;
								apCloseCharacters[i]->GetPlayer()->m_GameExp.m_RegenTimer = (float)Server()->Tick();
							}
						}
					}
				}

				// SAVE
				if(apCloseCharacters[i]->GetPlayer()->m_GameExp.m_LastFlag != fi+1)
				{
					apCloseCharacters[i]->GetPlayer()->m_GameExp.m_LastFlag = fi+1;
					GameServer()->SendChatTarget(apCloseCharacters[i]->GetPlayer()->GetCID(), "Checkpoint reached.");
					//apCloseCharacters[i]->GetPlayer()->m_GameExp.m_SaveTimer = (float)Server()->Tick() + 5.0f*Server()->TickSpeed();
				}
			}
		}
	}
}
Esempio n. 11
0
void CPlayer::OnDirectInput(CNetObj_PlayerInput *NewInput)
{
	if(GameServer()->m_World.m_Paused)
	{
		m_PlayerFlags = NewInput->m_PlayerFlags;
		return;
	}

	if(NewInput->m_PlayerFlags&PLAYERFLAG_CHATTING)
	{
		// skip the input if chat is active
		if(m_PlayerFlags&PLAYERFLAG_CHATTING)
			return;

		// reset input
		if(m_pCharacter)
			m_pCharacter->ResetInput();

		m_PlayerFlags = NewInput->m_PlayerFlags;
		return;
	}

	m_PlayerFlags = NewInput->m_PlayerFlags;

	if(m_pCharacter)
		m_pCharacter->OnDirectInput(NewInput);

	if(!m_pCharacter && m_Team != TEAM_SPECTATORS && (NewInput->m_Fire&1))
		Respawn();

	if(!m_pCharacter && m_Team == TEAM_SPECTATORS && (NewInput->m_Fire&1))
	{
		if(!m_ActiveSpecSwitch)
		{
			m_ActiveSpecSwitch = true;
			if(m_SpecMode == SPEC_FREEVIEW)
			{
				CCharacter *pChar = (CCharacter *)GameServer()->m_World.ClosestEntity(m_ViewPos, 6.0f*32, CGameWorld::ENTTYPE_CHARACTER, 0);
				CFlag *pFlag = (CFlag *)GameServer()->m_World.ClosestEntity(m_ViewPos, 6.0f*32, CGameWorld::ENTTYPE_FLAG, 0);
				if(pChar || pFlag)
				{
					if(!pChar || (pFlag && pChar && distance(m_ViewPos, pFlag->GetPos()) < distance(m_ViewPos, pChar->GetPos())))
					{
						m_SpecMode = pFlag->GetTeam() == TEAM_RED ? SPEC_FLAGRED : SPEC_FLAGBLUE;
						m_pSpecFlag = pFlag;
						m_SpectatorID = -1;
					}
					else
					{
						m_SpecMode = SPEC_PLAYER;
						m_pSpecFlag = 0;
						m_SpectatorID = pChar->GetPlayer()->GetCID();
					}
				}
			}
			else
			{
				m_SpecMode = SPEC_FREEVIEW;
				m_pSpecFlag = 0;
				m_SpectatorID = -1;
			}
		}
	}
	else if(m_ActiveSpecSwitch)
		m_ActiveSpecSwitch = false;

	// check for activity
	if(NewInput->m_Direction || m_LatestActivity.m_TargetX != NewInput->m_TargetX ||
		m_LatestActivity.m_TargetY != NewInput->m_TargetY || NewInput->m_Jump ||
		NewInput->m_Fire&1 || NewInput->m_Hook)
	{
		m_LatestActivity.m_TargetX = NewInput->m_TargetX;
		m_LatestActivity.m_TargetY = NewInput->m_TargetY;
		m_LastActionTick = Server()->Tick();
		m_InactivityTickCounter = 0;
	}
}