#include "MW4Headers.hpp"
#include "bucket.hpp"
#include "ablexec.h"
#include <adept\player.hpp>
#include <adept\application.hpp>
#include "flag.hpp"
#include "vehicle.hpp"
#include "mwapplication.hpp"
#include "team.hpp"
#include "hudscore.hpp"
#include "mwguimanager.hpp"
#include "mwmission.hpp"
#include "gameinfo.hpp"
#include <MissionLang\Resource.h>
#include "nglog_mw4.hpp"
#include "MWPlayer.hpp"

// jcem - start
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include "ctcls.h"
#include "ctcl.h"

extern g_nMR;

// jcem - end

using namespace MechWarrior4;
const Stuff::Scalar max_score_refresh_rate = 1.0f;

void MechWarrior4::BucketSecurityCheckStart()
{
	_asm 
	{
		nop
	}	
}

CBucketManager::CBucketManager (void)
{
	m_bucketFormatDirty = false;
	m_LastScoreRefresh = 0;
	m_NeedScoreRefresh = false;

	m_CustomBucketName = MWApplication::GetInstance()->GetLocString(IDS_SCORETYPE_CUSTOM);

	m_AccumulatedTimeSlice = 0;
    
    memset(&m_aMultipliers[0], 0, sizeof(m_aMultipliers));
}

CBucketManager::~CBucketManager (void)
{
	stlport::vector <CBucket *>::iterator iter;

	for (iter = m_Buckets.begin ();iter != m_Buckets.end ();iter++)
	{
		delete (*iter);
		(*iter) = NULL;
	}
}


int CBucketManager::NumTrackedBuckets (void) const
{
	return m_TrackedData.size ();
}

int CBucketManager::NumPlayerBuckets (const ReplicatorID& repid) const
{
	stlport::map < Adept::ReplicatorID , stlport::vector<CBucket *> >::const_iterator iter;
	
	iter = m_PlayersBuckets.find (repid);
	if (iter == m_PlayersBuckets.end ())
		return 0;

	return iter->second.size ();
}

CBucket *CBucketManager::PlayerBucket (const ReplicatorID& repid,int index)
{
	stlport::map < Adept::ReplicatorID , stlport::vector<CBucket *> >::iterator iter;
	
	iter = m_PlayersBuckets.find (repid);
	if (iter == m_PlayersBuckets.end ())
		return NULL;
	
	Verify (index >=0);
	Verify (index < iter->second.size ());
	return iter->second[index];
}

CBucket *CBucketManager::PlayerBucket (const ReplicatorID& repid, Bucket_Type type)
{
	stlport::map<Adept::ReplicatorID,stlport::vector<CBucket*> >::iterator iter = m_PlayersBuckets.find (repid);
	if (iter == m_PlayersBuckets.end ())
		return (0);

	stlport::vector<CBucket *>& buckets = iter->second;

	{for (stlport::vector<CBucket *>::const_iterator i = buckets.begin();
		  i != buckets.end();
		  ++i)
	{
		if ((*i)->Type() == type)
		{
			return (*i);
		}
	}}

	return (0);
}

void CBucketManager::FillTeamBuckets(int team_number, stlport::vector<CBucket*>& buckets)
{
	// TODO: OPTIMIZE THIS!
	{for (stlport::vector<CBucket*>::iterator i = m_Buckets.begin();
		  i != m_Buckets.end();
		  ++i)
	{
		if (((*i) != 0) &&
			((*i)->Affects() == -(team_number + 1)))
		{
			buckets.push_back(*i);
		}
	}}
}

int CBucketManager::AddBucket (CBucket *bucket)
{
	int id;

	id = m_Buckets.size ();
	m_Buckets.push_back (bucket);
	m_BucketArray[bucket->Type ()].push_back (bucket);
	bucket->ID (id);
	m_PlayersBuckets[bucket->RepID ()].push_back (bucket);
	return id;
}

void CBucketManager::KillBucket (int id)
{
	Verify (id>=0);
	Verify (id<m_Buckets.size ());
	Verify (m_Buckets[id]);
	if (id < 0)												// these functions will probably be used by end users, however our scripts whould not have this problem
		return;
	if (id>=m_Buckets.size ())
		return;
	if (!m_Buckets[id])
		return;

	CBucket *bucket;
	int type;
	bucket = m_Buckets[id];
	Verify (bucket->ID () == id);
	type = (int) bucket->Type ();
	stlport::vector <CBucket *>::iterator iter;
	
	for (iter = m_VisibleBuckets.begin ();iter != m_VisibleBuckets.end ();iter++)
	{
		if ((*iter)==bucket)
		{
			(*iter)->SetVisible(false);
			m_VisibleBuckets.erase (iter);
			break;
		}
	}
	for (iter = m_BucketArray[type].begin ();iter != m_BucketArray[type].end ();iter++)
	{
		if ((*iter)==bucket)
		{
			(*iter)->SetVisible(false);
			m_BucketArray[type].erase (iter);
			break;
		}
	}

	{
		stlport::map < Adept::ReplicatorID , stlport::vector<CBucket *> >::iterator mapiter;

		mapiter = m_PlayersBuckets.find (bucket->RepID ());
		if (mapiter != m_PlayersBuckets.end ())
		{
			for (iter=mapiter->second.begin ();iter != mapiter->second.end ();iter++)
			{
				if ((*iter) == bucket)
				{
					mapiter->second.erase (iter);
					break;
				}
			}
		}
	}
	delete bucket;
	m_Buckets[id] = NULL;
}

CBucket *CBucketManager::Bucket (int id)
{
	Verify (id>=0);
	Verify (id<m_Buckets.size ());
	Verify (m_Buckets[id]);
	if (id < 0)												// these functions will probably be used by end users, however our scripts whould not have this problem
		return NULL;
	if (id>=m_Buckets.size ())
		return NULL;
	Verify (m_Buckets[id]->ID () == id);
	return m_Buckets[id];
}

int CBucketManager::BucketValue (int id) const
{
	Verify (id>=0);
	Verify (id<m_Buckets.size ());
	Verify (m_Buckets[id]);
	if (id < 0)												// these functions will probably be used by end users, however our scripts whould not have this problem
		return 0;
	if (id>=m_Buckets.size ())
		return 0;
	if (!m_Buckets[id])
		return 0;
	Verify (m_Buckets[id]->ID () == id);
	return m_Buckets[id]->Value ();
}

void CBucketManager::BucketValue (int id, int value)
{
	Verify (id>=0);
	Verify (id<m_Buckets.size ());
	Verify (m_Buckets[id]);
	if (id < 0)												// these functions will probably be used by end users, however our scripts whould not have this problem
		return ;
	if (id>=m_Buckets.size ())
		return ;
	if (!m_Buckets[id])
		return ;
	Verify (m_Buckets[id]->ID () == id);
	m_Buckets[id]->Value (value);
}

void CBucketManager::AddToCustomScore(const Adept::ReplicatorID& rep_id, int value)
{
	{for (stlport::vector <CBucket *>::iterator i = m_Buckets.begin ();
		  i != m_Buckets.end ();
		  ++i)
	{
		if (!(*i))
			continue;
		CBucket *bucket = *i;
		if (bucket->Type () != CUSTOM)
			continue;
		if ((bucket->RepID () != rep_id) && (rep_id != Adept::ReplicatorID::Null))
			continue;

		bucket->AddValue(value);
	}}
}

void CBucketManager::AddToScoreDisplay (CBucket *bucket)
{
	HUDScore *hud;

	Verify (bucket);

	MWGUIManager *manager = MWGUIManager::GetInstance ();

	if (manager)
	{
		if (manager->Component(MWGUIManager::HUD_SCORE))
		{
			hud = Cast_Object (HUDScore *,manager->Component(MWGUIManager::HUD_SCORE));
	//		if (bucket->RepID () == ReplicatorID::Null)
				hud->AddBucket (bucket);
	/*
			else
			{
				if (Player::GetInstance())
				{
					Player *player = Cast_Object(Player*, Player::GetInstance ());
					Check_Object(player->vehicle);
					if (bucket->RepID () == player->vehicle->GetReplicatorID ())
						hud->AddBucket (bucket);
				}
			}
	*/
		}
	}

}

void CBucketManager::RescanBucketsForHUD (void)
{

	stlport::vector <CBucket *>::iterator iter;
	
	for (iter = m_VisibleBuckets.begin ();iter != m_VisibleBuckets.end ();iter++)
	{
		AddToScoreDisplay (*iter);
	}

}

void CBucketManager::ShowBucket (int id)
{
	Verify (id>=0);
	Verify (id<m_Buckets.size ());
	Verify (m_Buckets[id]);
	if (id < 0)												// these functions will probably be used by end users, however our scripts whould not have this problem
		return;
	if (id>=m_Buckets.size ())
		return;
	if (!m_Buckets[id])
		return;
	Verify (m_Buckets[id]->ID () == id);

	CBucket *thisbucket = m_Buckets[id];
	{for (stlport::vector <CBucket *>::iterator iter = m_VisibleBuckets.begin();
		  iter != m_VisibleBuckets.end ();
		  ++iter)
	{
		if ((*iter) == thisbucket)
			return;
	}}

	AddToScoreDisplay (m_Buckets[id]);
	m_VisibleBuckets.push_back (m_Buckets[id]);
	m_Buckets[id]->SetVisible(true);
}

void CBucketManager::HideBucket (int id)
{
	Verify (id>=0);
	Verify (id<m_Buckets.size ());
	Verify (m_Buckets[id]);
	if (id < 0)												// these functions will probably be used by end users, however our scripts whould not have this problem
		return;
	if (id>=m_Buckets.size ())
		return;
	if (!m_Buckets[id])
		return;
	Verify (m_Buckets[id]->ID () == id);
	CBucket *thisbucket = m_Buckets[id];
	{for (stlport::vector <CBucket *>::iterator iter = m_VisibleBuckets.begin ();
		  iter != m_VisibleBuckets.end ();
		  ++iter)
	{
		if ((*iter) == thisbucket)
		{
			(*iter)->SetVisible(false);
			m_VisibleBuckets.erase (iter);
			return;
		}
	}}
}
void CBucketManager::KillBucket (CBucketManager::Bucket_Type type,int bucketaffects,int mod2)
{
	{for (stlport::vector<CBucket *>::iterator iter=m_Buckets.begin ();iter != m_Buckets.end ();++iter)
	{
		if (*iter)
		{
			if (((*iter)->Type () == type) && ((*iter)->Affects () == bucketaffects) && ((*iter)->Mod2() == mod2))
			{
				KillBucket ((*iter)->ID ());
				return;
			}
		}
	}}
}

void CBucketManager::KillBucket (CBucketManager::Bucket_Type type,const Adept::ReplicatorID& id,int bucketaffects,int mod2)
{
	{for (stlport::vector<CBucket *>::iterator iter = m_Buckets.begin ();
		  iter != m_Buckets.end ();
		  ++iter)
	{
		if (*iter)
		{
			if (((*iter)->Type () == type) && ((*iter)->RepID () == id) && ((*iter)->Affects () == bucketaffects) && ((*iter)->Mod2() == mod2))
			{
				KillBucket ((*iter)->ID ());
				return;
			}
		}
	}}
}

#ifdef LAB_ONLY
void CBucketManager::UpdateGameInfo(const Adept::ReplicatorID& id, CBucketManager::Bucket_Type type)
{
	if (MWApplication::SaveGameStats == false)
	{
		return;
	}

	Connection* connection = Network::GetInstance()->GetConnection(id.connectionID);

	if (connection == 0)
	{
		return;
	}

	if (type == KILLS)
	{
		MWGameInfo::g_playerKills[connection->GetID()] = FindBucketValue(KILLS,id);
	}
	else
	{
		if (type == DEATHS)
		{
			MWGameInfo::g_playerDeaths[connection->GetID()] = FindBucketValue(DEATHS,id);
		}
	}

	MWGameInfo::g_playerScores[connection->GetID()] = FindBucketValue(CUSTOM,id);
}
#endif
/*
void CBucketManager::NotifyAction (CBucketManager::Bucket_Type type,const Adept::ReplicatorID& id,int mod2, int value)
{
	Vehicle *obj = (Vehicle*)-1;

	for (stlport::vector<CBucket *>::iterator iter=m_BucketArray[type].begin ();iter != m_BucketArray[type].end ();iter++)
	{
		if (*iter)
		{
			if ((*iter)->Mod2 () == mod2)
			{
				if ((*iter)->Affects () == BUCKET_AFFECT_ALL)
				{
					(*iter)->AddValue (value);
				}
				else if (((*iter)->Affects () == BUCKET_AFFECT_ONE) && ((*iter)->RepID() == id))
				{
					(*iter)->AddValue (value);
				}
				else
				{
					if (obj == (Vehicle*)-1)
					{
						obj = 0;
						Connection	*connection = Network::GetInstance()->GetConnection(id.connectionID);
						if (connection != NULL)
						{
							Check_Object(connection);

							Replicator* rep = connection->FindReplicator(id);
							if (rep != NULL)
							{
								Entity *ent = Cast_Object(Entity *, rep);
								if (ent->IsDerivedFrom (Vehicle::DefaultData))
								{
									obj = Cast_Object (Vehicle *,ent);
								}
							}
						}
					}

					if (obj)				// must be a team bucket
					{
						if (((*iter)->Affects () * -1) == (obj->GetTeam ()+1))
							(*iter)->AddValue (value);
					}
				}
			}
		}
	}

	if (Application::GetInstance()->serverFlag)
	{
		m_NeedScoreRefresh = true;
	}

	#ifdef LAB_ONLY
	UpdateGameInfo(id,type);
	#endif
}
*/
void CBucketManager::NotifyAction (Bucket_Type type,const Adept::ReplicatorID& id, int value, const Adept::ReplicatorID& id2/* = *(const Adept::ReplicatorID*)NULL*/)
{
    if (g_nMR == 2)
        return;

	Vehicle *obj = (Vehicle*)-1;

	{for (stlport::vector<CBucket *>::iterator iter=m_BucketArray[type].begin ();iter != m_BucketArray[type].end ();iter++)
	{
		if (*iter)
		{
			if ((*iter)->Affects () == BUCKET_AFFECT_ALL)
			{
				(*iter)->AddValue (value);
			}
			else if (((*iter)->Affects () == BUCKET_AFFECT_ONE) && ((*iter)->RepID() == id))
			{
				(*iter)->AddValue (value);
			}
			else								// must be a team bucket
			{
				if (obj == (Vehicle*)-1)
				{
					obj = 0;
					Connection	*connection = Network::GetInstance()->GetConnection(id.connectionID);
					if (connection != NULL)
					{
						Check_Object(connection);
						Replicator* rep = connection->FindReplicator(id);
						if (rep != NULL)
						{
							Entity *ent = Cast_Object(Entity *, rep);
							if (ent->IsDerivedFrom (Vehicle::DefaultData))
							{
								obj = Cast_Object (Vehicle *,ent);
							}
						}
					}
				}

				if ((obj != 0) &&
					((*iter)->Affects () * -1) == (obj->GetTeam ()+1))
					(*iter)->AddValue (value);
			}
		}
	}}

	if (Application::GetInstance()->serverFlag)
	{
		m_NeedScoreRefresh = true;

        if (&id && &id2) {
            bool bFound = false;
	        {for (stlport::vector<PVP_Rec>::iterator i = m_aPVP_Recs.begin(); i != m_aPVP_Recs.end(); ++i)
	        {
                PVP_Rec& pvp = (*i);
                if ((pvp.m_Inf == id) && (pvp.m_Rcv == id2)) {
			        if ((type == FRIENDLY_KILLS) || (type == ENEMY_KILLS) || (type == SUICIDES))
                        pvp.m_nKills += value;
                    pvp.m_nScore += m_aMultipliers[type] * value;
                    bFound = true;
                    break;
                }
            }}
            if (!bFound) {
                PVP_Rec pvp(id, id2);
			    if ((type == FRIENDLY_KILLS) || (type == ENEMY_KILLS) || (type == SUICIDES))
                    pvp.m_nKills += value;
                pvp.m_nScore += m_aMultipliers[type] * value;
                m_aPVP_Recs.push_back(pvp);
            }
        }
	}

	#ifdef LAB_ONLY
	UpdateGameInfo(id,type);
	#endif
}

void CBucketManager::UpdateShutdownFrame(int int_time_slice)
{
	stlport::vector<CBucket *>::iterator iter;
	for (iter=m_BucketArray[SHUTDOWN_TIMER].begin ();iter != m_BucketArray[SHUTDOWN_TIMER].end ();iter++)
	{
		if ((*iter)->Affects () == 0)				// means just one entity
		{
			Connection	*connection = Network::GetInstance()->GetConnection((*iter)->RepID().connectionID);
			if (connection == NULL)
				continue;
			Check_Object(connection);
			Replicator* rep = connection->FindReplicator((*iter)->RepID());
			if (rep == NULL)
				return;
			Entity *ent = Cast_Object(Entity *, rep);
			MWObject *obj;
			obj = Cast_Object (MWObject *,ent);
			
			if (obj->vehicleShutDown)
			{
				(*iter)->AddValue (int_time_slice);
			}
		}
		else if ((*iter)->Affects () < 0)			// means for a team
		{
			MWApplication *app;
			app = Cast_Object (MWApplication *,Application::GetInstance());
			Team *team;
			int teamid = (*iter)->Affects () * -1;
			teamid -= 1;
			Verify (teamid < MWApplication::Maximum_Teams);
			team = app->teams[teamid]->GetCurrent ();
			if (!team)
				continue;
			ChainIteratorOf<Vehicle*> members (&team->membersOfTeam);
			Vehicle *veh;
			while ((veh = members.ReadAndNext ()) != NULL)
			{
				if (veh->vehicleShutDown)
				{
					(*iter)->AddValue (int_time_slice);
					break;
				}
			}
		}
	}
}
void CBucketManager::UpdateObjectiveFrame (int int_time_slice)
{
	m_VehiclesInsideObjectiveArea.clear();

	{for (int i_type = OBJECTIVE;
		  i_type <= OBJECTIVE_UNCONTESTED;
		  ++i_type)
	{
		stlport::vector<CBucket *>::iterator iter;
		for (iter=m_BucketArray[i_type].begin ();iter != m_BucketArray[i_type].end ();iter++)
		{
			if ((*iter)->ObjectID() < 0)
			{
				continue;
			}

			Entity *obj = NameTable::GetInstance()->FindData((*iter)->ObjectID ());

			if (obj == 0)
			{
				continue;
			}

			if ((*iter)->Affects () == 0)				// means just one entity
			{
				Connection	*connection = Network::GetInstance()->GetConnection((*iter)->RepID().connectionID);

				if (connection == NULL)
					continue;

				Check_Object(connection);

				Replicator* rep = connection->FindReplicator((*iter)->RepID());

				if (rep == NULL)
					continue;

				Entity *ent = Cast_Object(Entity *, rep);
				if ((ent->IsDerivedFrom(Vehicle::DefaultData) == true) &&
					(ent->IsWithin(obj,(Stuff::Scalar)(*iter)->Mod2(),true) == true) &&
					(ent->IsDestroyed() == false))
				{
					Vehicle* v = Cast_Object(Vehicle*,ent);

					if (std::find(m_VehiclesInsideObjectiveArea.begin(),
								  m_VehiclesInsideObjectiveArea.end(),
								  v) == m_VehiclesInsideObjectiveArea.end())
					{
						m_VehiclesInsideObjectiveArea.push_back(v);
					}
				}
			}
			else
			{
				if ((*iter)->Affects () < 0)			// means for a team
				{
					MWApplication *app;
					app = Cast_Object(MWApplication*,Application::GetInstance());
					Team *team;
					int teamid = (*iter)->Affects () * -1;
					teamid -= 1;
					Verify (teamid < MWApplication::Maximum_Teams);
					team = app->teams[teamid]->GetCurrent ();
					if (!team)
						continue;
					ChainIteratorOf<Vehicle*> members (&team->membersOfTeam);
					Vehicle *veh;
					while ((veh = members.ReadAndNext ()) != NULL)
					{
						if ((veh->IsDestroyed() == false) &&
							(veh->IsWithin (obj,(Stuff::Scalar)(*iter)->Mod2 (),true)))
						{
							if (std::find(m_VehiclesInsideObjectiveArea.begin(),
										  m_VehiclesInsideObjectiveArea.end(),
										  veh) == m_VehiclesInsideObjectiveArea.end())
							{
								m_VehiclesInsideObjectiveArea.push_back(veh);
							}
							break;
						}
					}
				}
			}
		}
	}}

	stlport::vector<int> teams_inside;
	{for (stlport::vector<Vehicle*>::const_iterator i = m_VehiclesInsideObjectiveArea.begin();
		  i != m_VehiclesInsideObjectiveArea.end();
		  ++i)
	{
		int team = (*i)->GetTeam();

		if (team == MWApplication::No_Team)
		{
			team = (*i)->GetAlignment();
		}

		if (std::find(teams_inside.begin(),teams_inside.end(),team) == teams_inside.end())
		{
			teams_inside.push_back(team);
		}
	}}

	switch (teams_inside.size())
	{
		case 0:
		{
			return;
		}

		case 1:
		{
			{for (stlport::vector<Vehicle*>::const_iterator i = m_VehiclesInsideObjectiveArea.begin();
				  i != m_VehiclesInsideObjectiveArea.end();
				  ++i)
			{
				NotifyAction(OBJECTIVE,(*i)->GetReplicatorID(),int_time_slice);
				NotifyAction(OBJECTIVE_UNCONTESTED,(*i)->GetReplicatorID(),int_time_slice);
				// ngLog - KotH uncontested logging
#if !defined(NO_LOG)
				MW4log_generic(MW4P_DSTATS, va("KU\t%d\t%d", (*i)->GetReplicatorID().connectionID, int_time_slice));
#endif // !defined(NO_LOG)
			}}
			break;
		}

		default:
		{
			{for (stlport::vector<Vehicle*>::const_iterator i = m_VehiclesInsideObjectiveArea.begin();
				  i != m_VehiclesInsideObjectiveArea.end();
				  ++i)
			{
				NotifyAction(OBJECTIVE,(*i)->GetReplicatorID(),int_time_slice);
				NotifyAction(OBJECTIVE_CONTESTED,(*i)->GetReplicatorID(),int_time_slice);
				// ngLog - KotH contested logging
#if !defined(NO_LOG)
				MW4log_generic(MW4P_DSTATS, va("KC\t%d\t%d", (*i)->GetReplicatorID().connectionID, int_time_slice));
#endif // !defined(NO_LOG)
			}}
			break;
		}
	}
}

void CBucketManager::UpdateTimeFrame(int int_time_slice)
{
	stlport::vector<CBucket *>::iterator iter;
	for (iter=m_BucketArray[TIME].begin ();iter != m_BucketArray[TIME].end ();iter++)
	{
		(*iter)->AddValue (int_time_slice);
	}
}

void CBucketManager::UpdateScoreDirty()
{
	if ((Application::GetInstance()->serverFlag == false) ||
		(m_NeedScoreRefresh == false) ||
		(m_LastScoreRefresh + max_score_refresh_rate > (Stuff::Scalar)gos_GetElapsedTime()))
	{
		return;
	}

	MWMission::GetInstance()->scoreDirty = true;

	m_LastScoreRefresh = (Stuff::Scalar)gos_GetElapsedTime();
	m_NeedScoreRefresh = false;
}

void CBucketManager::UpdateFrame (Stuff::Scalar time_slice)
{
	m_AccumulatedTimeSlice += time_slice;

	if (m_AccumulatedTimeSlice < 1)
	{
		return;
	}

	int int_time_slice = (int)m_AccumulatedTimeSlice;
	m_AccumulatedTimeSlice -= (Stuff::Scalar)int_time_slice;

	UpdateShutdownFrame(int_time_slice);
	UpdateObjectiveFrame(int_time_slice);
	UpdateTimeFrame(int_time_slice);
	UpdateScoreDirty();
	UpdateTeamBucketVisibility();
	SortVisibleBuckets();
}

void CBucketManager::UpdateTeamBucketVisibility()
{
	MWApplication *app = Cast_Object(MWApplication*,Application::GetInstance());

	bool team_exists[8];

	{for (int i = 0;
		  i < 8;
		  ++i)
	{
		team_exists[i] = false;
	}}

	{for (int i = 0;
		  i < Maximum_Players;
		  ++i)
	{
		if ((app->servedConnectionData[i].clientPlayer != NULL) &&
			(app->servedConnectionData[i].clientPlayer->vehicle != NULL) &&
			(app->servedConnectionData[i].clientPlayer->vehicle->IsDerivedFrom(Vehicle::DefaultData) == true))
		{
			Vehicle* vehicle = Cast_Object(Vehicle*,app->servedConnectionData[i].clientPlayer->vehicle);

			if (vehicle->GetTeam() != MWApplication::No_Team)
			{
				team_exists[vehicle->GetTeam()] = true;
			}
		}
	}}

	{for (int i = 0;
		  i < Maximum_Lancemates;
		  ++i)
	{
		if (app->lancemateConnectionData[i].lancemateConnected &&
			app->lancemateConnectionData[i].lancemateVehicleAccepted)
		{
			Vehicle* vehicle = app->lancemateConnectionData[i].lancemateMech;

			if ((vehicle != 0) &&
				(vehicle->GetTeam() != MWApplication::No_Team))
			{
				team_exists[vehicle->GetTeam()] = true;
			}
		}
	}}

	{for (stlport::vector<CBucket*>::iterator i = m_Buckets.begin();
		  i != m_Buckets.end();
		  ++i)
	{
		if (((*i) != 0) &&
			((*i)->Affects() < 0))
		{
			int team_number = (- (*i)->Affects()) - 1;

			if ((team_number >= 0) &&
				(team_number < 8))
			{
				if (team_exists[team_number] == true)
				{
					{for (stlport::vector<Track_Data>::const_iterator j = m_TrackedData.begin();
						  j != m_TrackedData.end();
						  ++j)
					{
						if ((*j).buckettype == (*i)->Type())
						{
							if ((*j).visible == true)
							{
								ShowBucket((*i)->ID());
							}
							else
							{
								HideBucket((*i)->ID());
							}

							break;
						}
					}}
				}
				else
				{
					HideBucket((*i)->ID());
				}
			}
		}
	}}
}

void CBucketManager::SortVisibleBuckets()
{
	HUDScore *hud;

	MWGUIManager *manager = MWGUIManager::GetInstance ();
	if (manager)
	{
		if (manager->Component(MWGUIManager::HUD_SCORE))
		{
			hud = Cast_Object (HUDScore *,manager->Component(MWGUIManager::HUD_SCORE));

			if (hud != 0)
			{
				hud->SortByTeam();
			}
		}
	}
}

int CBucketManager::FindBucket (Bucket_Type type,const Adept::ReplicatorID& repid,int bucketaffects,int mod2,int objid)
{
	stlport::vector <CBucket *>::iterator iter;
	
	for (iter = m_Buckets.begin ();iter != m_Buckets.end ();iter++)
	{
		if (!(*iter))
			continue;
		CBucket *bucket = *iter;
		if (bucket->Type () != type)
			continue;
		if ((bucket->RepID () != repid) && (repid != Adept::ReplicatorID::Null))
			continue;
		if (bucket->Affects () != bucketaffects)
			continue;
		if (bucket->Mod2 () != mod2)
			continue;
		if ((bucket->ObjectID () == objid) && (objid != -2))
			continue;
		return bucket->ID ();
	}
	return -1;
}

int CBucketManager::FindBucketValue(Bucket_Type type, const Adept::ReplicatorID& repid)
{
	CBucket* bucket = FindBucket(type,repid);

	if (bucket == 0)
	{
		return (0);
	}

	return (bucket->Value());
}

int CBucketManager::FindBucketValue(Bucket_Type type, int affects)
{
	CBucket* bucket = FindBucket(type,affects);

	if (bucket == 0)
	{
		return (0);
	}

	return (bucket->Value());
}

CBucket* CBucketManager::FindBucket (Bucket_Type type,const Adept::ReplicatorID& repid)
{
	// these lines added to track down bug 5472
	if (repid == ReplicatorID::Null)
	{
		_asm 
		{
			nop
		}
	}

	{for (stlport::vector <CBucket *>::iterator i = m_Buckets.begin ();
		  i != m_Buckets.end ();
		  ++i)
	{
		if (((*i) != 0) &&
			((*i)->Type () == type) &&
			((*i)->RepID () == repid))
		{
			return (*i);
		}
	}}

	return (0);
}

CBucket* CBucketManager::FindBucket (Bucket_Type type, int affects)
{
	{for (stlport::vector <CBucket *>::iterator i = m_Buckets.begin ();
		  i != m_Buckets.end ();
		  ++i)
	{
		if (((*i) != 0) &&
			((*i)->Type() == type) &&
			((*i)->Affects() == affects))
		{
			return (*i);
		}
	}}

	return (0);
}

void CBucketManager::SetupTrackData (int id)
{
	Adept::Mission* mission = Adept::Mission::GetInstance();
	if (mission == 0)
	{
		return;
	}

	Stuff::SortedChainIteratorOf<ScoreObject *,Adept::ReplicatorID> i(&mission->ScoreChain());

	ScoreObject* o;
	while ((o = i.ReadAndNext()) != 0)
	{
		NewTrackBucket(id,o->GetID());
	}

	{for (int i = 0;
		  i < 8;
		  ++i)
	{
		NewTeamBucket(id,i);
	}}
}

void CBucketManager::NewTeamBucket(int id, int team_number)
{
	{for (stlport::vector<CBucket*>::const_iterator i = m_Buckets.begin();
		  i != m_Buckets.end();
		  ++i)
	{
		if (((*i)->Type() == m_TrackedData[id].buckettype) &&
			((*i)->Affects() == -(team_number + 1)))
		{
			return;
		}
	}}

	CBucket* newbuck = new CBucket (m_TrackedData[id].buckettype,-(team_number + 1),m_TrackedData[id].mod2);
	newbuck->Tracked(true);

	m_TrackedBuckets.push_back (newbuck);
	AddBucket (newbuck);
}

void CBucketManager::NewTrackBucket (int id,const Adept::ReplicatorID& repid)
{
	Verify (id>=0);
	Verify (id < m_TrackedData.size ());
	CBucket *newbuck;

	newbuck = new CBucket (m_TrackedData[id].buckettype,repid,0,m_TrackedData[id].mod2);
	newbuck->Tracked(true);
	if (m_TrackedData[id].objid != -1)
	{
		newbuck->ObjectID (m_TrackedData[id].objid);
	}
	m_TrackedBuckets.push_back (newbuck);
	int newid = AddBucket (newbuck);
	if (m_TrackedData[id].visible)
		ShowBucket (newid);
}

void CBucketManager::SetupTrack (Bucket_Type type, int mod2, bool visible, bool can_replace)
{
	m_bucketFormatDirty = true;

	bool already_exists = false;
	{for (stlport::vector<Track_Data>::iterator i = m_TrackedData.begin();
		  i != m_TrackedData.end();
		  ++i)
	{
		if ((*i).buckettype == type)
		{
			already_exists = true;

			if (can_replace == true)
			{
				(*i).mod2 = mod2;
				(*i).visible = visible;
			}
		}
	}}

	if (already_exists == true)
	{
		return;
	}

	int id;

	id = m_TrackedData.size ();
	m_TrackedData.push_back (Track_Data (type,mod2,-1,visible));
	SetupTrackData (id);
}

void CBucketManager::SetupTrackObject (Bucket_Type type,int objid,int distance,bool visible)
{
	m_bucketFormatDirty = true;

	int id;

	id = m_TrackedData.size ();
	m_TrackedData.push_back (Track_Data (type,distance,objid,visible));
	SetupTrackData (id);
}

void CBucketManager::SetupTrackNet(Bucket_Type p1, int p2, int p3,bool p4)
{
	int id = m_TrackedData.size ();
	m_TrackedData.push_back (Track_Data (p1,p2,p3,p4));
	SetupTrackData (id);
}

void CBucketManager::NotifyAddPlayer (const Adept::ReplicatorID& repid)
{
	int i;
	for (i=0;i<m_TrackedData.size ();i++)
	{
		NewTrackBucket (i,repid);
	}
}

void CBucketManager::NotifyRemovePlayer (const Adept::ReplicatorID& repid)
{
	stlport::vector <CBucket *>::iterator iter;
	
	iter = m_TrackedBuckets.begin ();
	while (iter != m_TrackedBuckets.end ())
	{
		Verify (*iter);
		if ((*iter)->RepID () == repid)
		{
			KillBucket ((*iter)->ID ());
			iter = m_TrackedBuckets.erase (iter);
		}
		else
			iter++;
	}
}

void CBucketManager::AddCustomBucketParameter(Bucket_Type bucket_type, int bucket_multiplier)
{
    m_aMultipliers[bucket_type] = bucket_multiplier;

	Custom_Parameter c(bucket_type,bucket_multiplier);

	{for (stlport::vector<Custom_Parameter>::iterator i = m_CustomParameters.begin();
		  i != m_CustomParameters.end();
		  ++i)
	{
		if ((*i).bucket_type == bucket_type)
		{
			(*i).bucket_multiplier = bucket_multiplier;

			return;
		}
	}}

	m_CustomParameters.push_back(c);

	SetupTrack(bucket_type,0,false,false);
}

int CBucketManager::GetCustomBucketValue(const Adept::ReplicatorID& rep_id)
{
	int value(0);

	{for (stlport::vector<Custom_Parameter>::const_iterator i = m_CustomParameters.begin();
		  i != m_CustomParameters.end();
		  ++i)
	{
		int this_value = FindBucketValue((*i).bucket_type,rep_id);

		value += (this_value * (*i).bucket_multiplier);
	}}

	return (value);
}

int CBucketManager::GetCustomBucketValue(int affects)
{
	int value(0);

	{for (stlport::vector<Custom_Parameter>::const_iterator i = m_CustomParameters.begin();
		  i != m_CustomParameters.end();
		  ++i)
	{
		int this_value = FindBucketValue((*i).bucket_type,affects);

		value += (this_value * (*i).bucket_multiplier);
	}}

	return (value);
}

const stlport::vector<Vehicle*>& CBucketManager::GetVehiclesInsideObjectiveArea() const
{
	return (m_VehiclesInsideObjectiveArea);
}

void CBucketManager::AddTeamPoints(int team, int points)
{
	{for (stlport::vector<CBucket*>::iterator i = m_Buckets.begin();
		  i != m_Buckets.end();
		  ++i)
	{
		if (((*i) != 0) &&
			((*i)->Type() == CUSTOM) &&
			((*i)->Affects() == -(team + 1)))
		{
			(*i)->AddValue(points);
		}
	}}
}

int CBucketManager::RelativeGetScore4Player(const ReplicatorID& me, const ReplicatorID& whom, int& nKills, int& nDeaths) const
{
    nKills = 0;
    nDeaths = 0;
    int nScore = 0;

    stlport::vector <PVP_Rec>& aPVP_Recs = *(stlport::vector <PVP_Rec>*)&m_aPVP_Recs;
	for(stlport::vector<PVP_Rec>::iterator i = aPVP_Recs.begin(); i != aPVP_Recs.end(); ++i)
	{
        CBucketManager::PVP_Rec& pvp = (*i);
        if (pvp.m_Inf == whom) {
            if (pvp.m_Rcv == me) {
                nKills = pvp.m_nKills;
                nScore = pvp.m_nScore;
            }
        } else if (pvp.m_Inf == me) {
            if (pvp.m_Rcv == whom) {
                nDeaths = pvp.m_nKills;
            }
        }
	}

	return nScore;
}
//________________________________________________________________________________________________________________

CBucket::CBucket (CBucketManager::Bucket_Type type,int bucketaffects,int mod2)
{
	m_BucketType = type;
	m_Value = 0;
	m_BucketAffects = bucketaffects;
	m_Mod2 = mod2;
	m_Replicator = ReplicatorID::Null;
	m_Tracked = false;
	m_ObjectID = -2;
	m_Visible = false;
	m_Team = -1;
}

CBucket::CBucket (CBucketManager::Bucket_Type type,const Adept::ReplicatorID& id,int bucketaffects,int mod2)
{
	m_BucketType = type;
	m_Value = 0;
	m_BucketAffects = bucketaffects;
	m_Mod2 = mod2;
	m_Replicator = id;
	m_Tracked = false;
	m_ObjectID = -2;
	m_Team = -1;
	m_Visible = false;
}

CBucket::~CBucket (void)
{
	HUDScore *hud;

	if (MWGUIManager::GetInstance ())
	{
		if (MWGUIManager::GetInstance ()->Component(MWGUIManager::HUD_SCORE))
		{
			hud = Cast_Object (HUDScore *,MWGUIManager::GetInstance ()->Component(MWGUIManager::HUD_SCORE));

			hud->KillBucket(this);
		}
	}
}

char CBucket::buf[256] = "";
const char *CBucket::Text (void) const
{
	switch (m_BucketType)
	{
		#define HANDLE_BUCKET(bucket_type,string_index)		\
			case CBucketManager::##bucket_type:		\
				sprintf(buf,"%s:",MWApplication::GetInstance()->GetLocString(string_index));	\
			  break;

		HANDLE_BUCKET(KILL_LINK,IDS_SCORETYPE_KILL_LINK);
		HANDLE_BUCKET(DEATH_LINK,IDS_SCORETYPE_DEATH_LINK);
		HANDLE_BUCKET(KILLS,IDS_SCORETYPE_KILLS);
		HANDLE_BUCKET(FRIENDLY_KILLS,IDS_SCORETYPE_FRIENDLY_KILLS);
		HANDLE_BUCKET(ENEMY_KILLS,IDS_SCORETYPE_ENEMY_KILLS);
		HANDLE_BUCKET(KILLS_BY_TONNAGE,IDS_SCORETYPE_KILLS_BY_TONNAGE);
		HANDLE_BUCKET(FRIENDLY_KILLS_BY_TONNAGE,IDS_SCORETYPE_FRIENDLY_KILLS_BY_TONNAGE);
		HANDLE_BUCKET(ENEMY_KILLS_BY_TONNAGE,IDS_SCORETYPE_ENEMY_KILLS_BY_TONNAGE);
		HANDLE_BUCKET(DEATHS,IDS_SCORETYPE_DEATHS);
		HANDLE_BUCKET(DAMAGE_INFLICT,IDS_SCORETYPE_DAMAGE_INFLICT);
		HANDLE_BUCKET(FRIENDLY_DAMAGE_INFLICT,IDS_SCORETYPE_FRIENDLY_DAMAGE_INFLICT);
		HANDLE_BUCKET(ENEMY_DAMAGE_INFLICT,IDS_SCORETYPE_ENEMY_DAMAGE_INFLICT);
		HANDLE_BUCKET(DAMAGE_RECEIVE,IDS_SCORETYPE_DAMAGE_RECEIVE);
		HANDLE_BUCKET(FRIENDLY_DAMAGE_RECEIVE,IDS_SCORETYPE_FRIENDLY_DAMAGE_RECEIVE);
		HANDLE_BUCKET(ENEMY_DAMAGE_RECEIVE,IDS_SCORETYPE_ENEMY_DAMAGE_RECEIVE);
		HANDLE_BUCKET(DFA,IDS_SCORETYPE_DFA);
		HANDLE_BUCKET(SHOTS_HIT,IDS_SCORETYPE_SHOTS_HIT);
		HANDLE_BUCKET(SHOTS_FIRED,IDS_SCORETYPE_SHOTS_FIRED);
		HANDLE_BUCKET(HEAD_SHOTS,IDS_SCORETYPE_HEAD_SHOTS);
		HANDLE_BUCKET(ARM_SHOTS,IDS_SCORETYPE_ARM_SHOTS);
		HANDLE_BUCKET(LEG_SHOTS,IDS_SCORETYPE_LEG_SHOTS);
		HANDLE_BUCKET(TORSO_SHOTS,IDS_SCORETYPE_TORSO_SHOTS);
		HANDLE_BUCKET(KILLS_PC,IDS_SCORETYPE_KILLS_PC);
		HANDLE_BUCKET(KILLS_AI,IDS_SCORETYPE_KILLS_AI);
		HANDLE_BUCKET(BLANK,IDS_SCORETYPE_BLANK);
		HANDLE_BUCKET(SHUTDOWN_TIMER,IDS_SCORETYPE_SHUTDOWN_TIMER);
		HANDLE_BUCKET(OBJECTIVE,IDS_SCORETYPE_OBJECTIVE);
		HANDLE_BUCKET(OBJECTIVE_CONTESTED,IDS_SCORETYPE_OBJECTIVE_CONTESTED);
		HANDLE_BUCKET(OBJECTIVE_UNCONTESTED,IDS_SCORETYPE_OBJECTIVE_UNCONTESTED);
		HANDLE_BUCKET(FLAGS_TAKEN,IDS_SCORETYPE_FLAGS_TAKEN);
		HANDLE_BUCKET(FLAGS_DROPPED,IDS_SCORETYPE_FLAGS_DROPPED);
		HANDLE_BUCKET(FLAGS_CAPTURED,IDS_SCORETYPE_FLAGS_CAPTURED);
		HANDLE_BUCKET(FLAG_HOLD_TIME,IDS_SCORETYPE_FLAG_HOLD_TIME);
		HANDLE_BUCKET(TIME,IDS_SCORETYPE_TIME);
		HANDLE_BUCKET(ALIVE_PLAYERS,IDS_SCORETYPE_ALIVE_PLAYERS);
		HANDLE_BUCKET(DEAD_PLAYERS,IDS_SCORETYPE_DEAD_PLAYERS);
		HANDLE_BUCKET(ENEMY_TURRET_KILLS, IDS_SCORETYPE_ENEMY_TURRET_KILLS);
		HANDLE_BUCKET(FRIENDLY_TURRET_KILLS, IDS_SCORETYPE_FRIENDLY_TURRET_KILLS); 
		HANDLE_BUCKET(ENEMY_BUILDING_KILLS, IDS_SCORETYPE_ENEMY_BUILDING_KILLS);
		HANDLE_BUCKET(FRIENDLY_BUILDING_KILLS, IDS_SCORETYPE_FRIENDLY_BUILDING_KILLS);

		#undef HANDLE_BUCKET

		case CBucketManager::CUSTOM:
			if (Affects() < 0)
			{
				sprintf(buf,"Team %d ",-Affects());
			}
			else
			{
				if ((m_Replicator != ReplicatorID::Null) &&
					(Adept::Mission::GetInstance() != 0))
				{
					Stuff::SortedChainIteratorOf<ScoreObject *,Adept::ReplicatorID> i(&(Adept::Mission::GetInstance()->ScoreChain()));

					ScoreObject* o;
					while ((o = i.ReadAndNext()) != 0)
					{
						if (o->GetID() == m_Replicator)
						{
							sprintf(buf,"%s",o->GetName());
							return buf;
						}
					}
				}

				sprintf(buf,"?");
			}
		break;
	}

	return buf;
}

int CBucket::Value() const
{
	if ((m_BucketType == CBucketManager::CUSTOM) &&
		(MWApplication::GetInstance()->serverFlag == true))
	{
		MWMission* mwmission = Cast_Object(MWMission*,MWMission::GetInstance());
		int score = 0;
		
		if (Affects() < 0)
		{
			score = mwmission->m_BucketManager->GetCustomBucketValue(Affects());
		}
		else
		{
			score = mwmission->m_BucketManager->GetCustomBucketValue(RepID());
		}

		return (score + m_Value);
	}

	return (m_Value);
}

void CBucket::Value(int value)
{
    if (g_nMR != 2)
        m_Value = value;
    else {
        extern bool g_bScoreMessageHandler;
        if (g_bScoreMessageHandler) {
            m_Value = value;
        } else {
            //m_Value = value;
        }
    }
}

void CBucket::AddValue(int value)
{
    if (g_nMR != 2)
    m_Value += value;
}

void CBucket::SubtractValue(int value)
{
    if (g_nMR != 2)
    m_Value -= value;
}

int CBucket::Team()
{
	if (m_Team >= 0)
	{
		return (m_Team);
	}

	if (Affects() < 0)
	{
		m_Team = -Affects() - 1;
		return (m_Team);
	}

	Connection* connection = Network::GetInstance()->GetConnection(RepID().connectionID);

	if (connection != NULL)
	{
		Check_Object(connection);
		Replicator* rep = connection->FindReplicator(RepID());

		if (rep != NULL)
		{
			Entity* ent = Cast_Object(Entity*,rep);
			if (ent->IsDerivedFrom(Vehicle::DefaultData) == true)
			{
				Vehicle* v = Cast_Object(Vehicle*,ent);

				m_Team = v->GetTeam();
				return (m_Team);
			}
		}
	}

	m_Team = MWApplication::No_Team;
	return (m_Team);
}

bool CBucket::GetVisible() const
{
	return (m_Visible);
}

void CBucket::SetVisible(bool visible)
{
	m_Visible = visible;
}

void CBucketManager::SetCustomBucketName(char* name)
{
	m_CustomBucketName = name;

	if (MWGUIManager::GetInstance() != 0)
	{
		MWGUIManager::GetInstance()->MPName(name);
	}
}

const char* CBucketManager::GetCustomBucketName()
{
	return (m_CustomBucketName.c_str());
}


using namespace ABL;

namespace ABL
{
extern TypePtr			IntegerTypePtr;
extern TypePtr			CharTypePtr;
extern TypePtr			RealTypePtr;
extern TypePtr			BooleanTypePtr;


//***************************************************************************
// PARSING HELPER FUNCTIONS
//***************************************************************************

void ABL_getInteger (bool lastParam = false);
void ABL_getReal (bool lastParam = false);
void ABL_getBoolean (bool lastParam = false);
void ABL_getIntegerOrReal (bool lastParam = false);
void ABL_getString (bool lastParam = false);
void ABL_getIntegerArray (bool lastParam = false);
void ABL_getRealArray (bool lastParam = false);
void ABL_getOpenParen (void);
};

ABL::TypePtr ParseAddBucket (void)
{
	ABL_getOpenParen ();
	ABL_getInteger ();
	ABL_getInteger ();
	ABL_getInteger ();
	ABL_getInteger (true);
	return ABL::IntegerTypePtr;
}
ABL::TypePtr ParseKillBucket (void)
{
	ABL_getOpenParen ();
	ABL_getInteger (true);
	return NULL;
}
ABL::TypePtr ParseShowBucket (void)
{
	ABL_getOpenParen ();
	ABL_getInteger (true);
	return NULL;
}
ABL::TypePtr ParseHideBucket (void)
{
	ABL_getOpenParen ();
	ABL_getInteger (true);
	return NULL;
}
ABL::TypePtr ParseGetBucketValue (void)
{
	ABL_getOpenParen ();
	ABL_getInteger (true);
	return ABL::RealTypePtr;
}
ABL::TypePtr ParseFindBucketValue (void)
{
	ABL_getOpenParen ();
	ABL_getInteger ();
	ABL_getInteger (true);
	return ABL::IntegerTypePtr;
}
ABL::TypePtr ParseSetBucketValue (void)
{
	ABL_getOpenParen ();
	ABL_getInteger ();
	ABL_getReal (true);
	return NULL;
}

ABL::TypePtr ParseTrackBucket (void)
{
	ABL_getOpenParen ();
	ABL_getInteger ();
	ABL_getInteger ();
	ABL_getBoolean (true);
	return NULL;
}

ABL::TypePtr ParseTrackObjectBucket (void)
{
	ABL_getOpenParen ();
	ABL_getInteger ();
	ABL_getInteger ();
	ABL_getInteger ();
	ABL_getBoolean (true);
	return NULL;
}

ABL::TypePtr ParseFindBucket (void)
{
	ABL_getOpenParen ();
	ABL_getInteger ();
	ABL_getInteger ();
	ABL_getInteger ();
	ABL_getInteger ();
	ABL_getInteger (true);
	return ABL::IntegerTypePtr;
}

void MechWarrior4::BucketSecurityCheckStop()
{
	_asm 
	{
		nop
	}	
}
