// This script contains functionality to allow bots to choose primary weapons
this.Name = "SelectWeapons";
this.Parent = "Limbo";
this.Debug = false;
this.AlwaysRecieveEvents = true;

// shared weapon counters
this.UsingWeapons = {};
this.UsingWeapons[ TEAM.ALLIES ] = {};
this.UsingWeapons[ TEAM.AXIS ] = {};

this.goals_mg42 = {};
this.goals_mortar = {};
this.NoFilters = { NoFilters=true };

if (!MinPlayersForMortar) {
	global MinPlayersForMortar = ConfigGet("HeavyWeapons","MinPlayersForMortar", -1);
	global MinPlayersForMobileMG = ConfigGet("HeavyWeapons","MinPlayersForMobileMG", -1);
}

this.EXCLUDE_MORTAR_AND_MG42 = {};
this.EXCLUDE_MORTAR_AND_MG42[WEAPON.MOBILE_MG42] = true;
this.EXCLUDE_MORTAR_AND_MG42[WEAPON.MORTAR] = true;

this.EXCLUDE_SNIPE = {};
this.EXCLUDE_SNIPE[WEAPON.GARAND] = true;
this.EXCLUDE_SNIPE[WEAPON.K43] = true;
this.EXCLUDE_SNIPE[WEAPON.PROTO] = true;

this.Initialize = function()
{
	if (Map.DontSelectWeapons || Map.PanzerMap) {
		this.Disable = true;
		return;
	}
	this.justStarted = true;
};

// Count the number of users for a particular weapon id
this.NumWeaponUsers = function(weaponId)
{
	num = 0;
	deleted = null;
	teamWeapons = this.UsingWeapons[ this.Bot.GetTeam() ];
	foreach (bot and weapon in teamWeapons)
	{
		if (weapon == weaponId){
			if (!bot.Name) {
				// bot disconnected
				if (!deleted){ deleted = table(); }
				deleted[tableCount(deleted)] = bot;
			}else{
				++num;
			}
		}
	}
	if (deleted) {
		foreach (bot in deleted) {
			teamWeapons[bot] = null;
		}
	}
	return num;
};

this.CheckRole = function(goals)
{
	foreach (goal in goals) {
		needRole = false;
		foreach (role in ROLE) {
			if (goal.HasRole(role)) {
				if (this.Bot.HasRole(role)) {
					return true; //goal has same role as this bot
				}
				needRole = true;
			}
		}
		if (!needRole) {
			return true; //goal does not have any role
		}
	}
	return false; //no goal available for this bot
};

this.GetPriority = function()
{
	this.Priority = 1;
	block(0);
};

this.Update = function()
{
	if (this.Debug) {
		foreach (id and weap in WEAPON) {
			if (this.Bot.HasWeapon(weap)) {
				this.Bot.Say("have weapon " + id);
			}
		}
	}

	this.SelectWeapon();
	// This is needed in order to finish the goal. Without it, the goal will continue to have Update called on it.
	block(0);
};

this.SelectWeapon = function()
{
	if (!this.Bot.ClassPrimaryWeaponChoice) {
		if (this.Debug) { print(this.Bot.Name, "ClassPrimaryWeaponChoice not defined"); }
		return;
	}

	myTeam = this.Bot.GetTeam();
	lastWeapon = this.UsingWeapons[myTeam][this.Bot];

	switch (this.Bot.GetClass())
	{
		case CLASS.SOLDIER:
		{
			// count how many goals are available for each weapon type
			numMg42Goals = this.QueryGoals(this.goals_mg42, 0xbe8488ed /* MOBILEMG42 */, this.NoFilters);
			numMortarGoals = this.QueryGoals(this.goals_mortar, 0x74708d7a /* MOBILEMORTAR */, this.NoFilters);

			// count how many other bots have these weapons
			numMg42Users = 9;
			if(numMg42Goals > 0){
				numMg42Users = this.NumWeaponUsers(WEAPON.MOBILE_MG42);
				if(this.Debug) {
					print(this.Bot.Name, ":" ,Util.TeamName(myTeam), ": # Mg42 Users:",numMg42Users,"/",numMg42Goals);
				}
			}
			numMortarUsers = 9;
			if(numMortarGoals > 0){
				numMortarUsers = this.NumWeaponUsers(WEAPON.MORTAR);
				if(this.Debug) {
					print(this.Bot.Name, ":" ,Util.TeamName(myTeam), ": # Mortar Users:",numMortarUsers,"/",numMortarGoals);
				}
			}

			if(lastWeapon != WEAPON.MOBILE_MG42) { ++numMg42Users; }
			if(lastWeapon != WEAPON.MORTAR) { ++numMortarUsers; }

			newWeapon = null;
			if(numMortarUsers <= numMortarGoals && Server.NumPlayers >= MinPlayersForMortar * numMortarUsers && this.CheckRole(this.goals_mortar))
			{
				newWeapon = WEAPON.MORTAR;
			}
			if(numMg42Users <= numMg42Goals && Server.NumPlayers >= MinPlayersForMobileMG * numMg42Users && this.CheckRole(this.goals_mg42) && (!newWeapon || RandInt(0,1)))
			{
				newWeapon = WEAPON.MOBILE_MG42;

				//enable mid-clip reload for skilled soldier
				modName = GetModName();
				if (modName == "noquarter" || modName == "nitmod")
				{
					skills = {};
					this.Bot.GetSkills(skills);
					if (skills[SKILL.HEAVY_WEAPONS] > 4) {
						wpn = this.Bot.GetWeapon(WEAPON.MOBILE_MG42);
						if (wpn) {
							wpn.PrimaryFire.IgnoreReload = false;
						}
					}
				}
			}
			if (!newWeapon)
			{
				// pick a new weapon other than mg42 and mortar
				newWeapon = this.Bot.ClassPrimaryWeaponChoice(this.EXCLUDE_MORTAR_AND_MG42);
			}
		}
		case CLASS.COVERTOPS:
		{
			// count how many goals are available
			if (Util.IsSnipeMap) {
				numSnipeGoals = 99;
			}
			else
			{
				GetGoals(Util.QueryTable, myTeam, 0xe8fbadc0 /* SNIPE */);
				numSnipeGoals = tableCount(Util.QueryTable);
			}

			if (numSnipeGoals > 0)
			{
				tbl = Util.TeamSniperWeapons[ Util.TeamName(myTeam) ];
				newWeapon = Util.GetRandomTableValue(tbl);
			}
			else
			{
				// pick a new weapon other than GARAND and K43
				newWeapon = this.Bot.ClassPrimaryWeaponChoice(this.EXCLUDE_SNIPE);
			}
		}
		default:
		{
			//random available weapon
			newWeapon = this.Bot.ClassPrimaryWeaponChoice(null);
		}
	}

	if (newWeapon)
	{
		this.Bot.ChangePrimaryWeapon(newWeapon);
		this.UsingWeapons[myTeam][this.Bot] = newWeapon;

		if(this.Debug && newWeapon!=lastWeapon)
		{
			this.Bot.SayTeam("Changing to ", Util.WeaponName(newWeapon));
			print(this.Bot.Name, ":" ,"Chose New Weapon:^8",Util.WeaponName(newWeapon));
		}
	}
};

this.Events[EVENT.CHANGETEAM] = function(newTeam)
{
	if (newTeam==TEAM.AXIS){ oldTeam=TEAM.ALLIES; }
	else if (newTeam==TEAM.ALLIES){ oldTeam=TEAM.AXIS; }
	else {
		//experimental workaround to fix issue with CONNECTING bots which block server slots
		sleep(0.2);
		if (this.Bot && this.Bot.GetTeam() < 0) {
			ExecCommand("kickbot " + this.Bot.GetGameId());
			global DelayManagePlayers = true;
		}
		return;
	}
	weapon = this.UsingWeapons[oldTeam][this.Bot];
	if (weapon) {
		this.UsingWeapons[oldTeam][this.Bot] = null;
		this.UsingWeapons[newTeam][this.Bot] = weapon;
	}
};

this.Events[EVENT.CHANGECLASS] = function(newClass)
{
	if ((!this.justStarted || GetGameState() != "Playing") && !this.Disable)
	{
		this.SelectWeapon();
		if (!this.justStarted && GetGameState() != "Playing")
		{
			this.Bot.ExecCommand("kill");
		}
	}
	this.justStarted = null;
};

Commands["minformortar"] =
{
	Func = function(_params)
	{
		minformortar = ToInt(_params[0], -1);
		ConfigSet("HeavyWeapons","MinPlayersForMortar", minformortar);
		global MinPlayersForMortar = minformortar;
		print("MinPlayersForMortar set to", minformortar);
	},

	Help =
	{
		"set the minimum number of players playing in order for bots to choose the mobile mortar",
	},
};

Commands["minformobilemg"] =
{
	Func = function(_params)
	{
		minformobilemg = ToInt(_params[0], -1);
		ConfigSet("HeavyWeapons","MinPlayersForMobileMG", minformobilemg);
		global MinPlayersForMobileMG = minformobilemg;
		print("MinPlayersForMobileMG set to", minformobilemg);
	},

	Help =
	{
		"set the minimum number of players playing in order for bots to choose the mobile mg42",
	},
};
