// This script contains functionality to allow bots to mount static mg42
this.Name = "MOUNTMG42";
this.Parent = "HighLevel";
this.SkipGetPriorityWhenActive = true;
this.Debug = false;

this.CheckOwner = function()
{
	owner = this.Bot.GetMountedPlayerOnMG42(this.GoalEnt);
	return !owner || !this.Bot.IsAllied(owner);
};

this.GetPriority = function()
{
	Util.GetPriority(this,0xe1a2b09c /* MOUNTMG42 */,0,0, function(goal, bot, _this)
	{
		ent = goal.GetEntity();
		if (!ent || !GetEntFlags(ent, ENTFLAG.MOUNTABLE) || GetEntFlags(ent, ENTFLAG.DEAD)) {
			return;
		}

		owner = bot.GetMountedPlayerOnMG42(ent);

		if (_this.Debug && owner) {
			bot.Say(format("%s is mounted on %s",GetEntName(owner), goal.GetName()));
		}

		if (!owner || !bot.IsAllied(owner)) {
			_this.GoalEnt = ent;
			return true;
		}
	});
};

this.Enter = function()
{
	this.MarkInProgress();

	// finish criteria
	this.AddFinishCriteria(this.GoalEnt,"hasentflag",ENTFLAG.DEAD);
	this.AddFinishCriteria(this.GoalEnt,"not hasentflag",ENTFLAG.MOUNTABLE);
	this.LimitTo(this.CheckOwner, 3, true);

	this.CombatThread = this.ForkThread(this.DisableCombat);
};

this.Update = function()
{
	Util.RouteTo(this);

	this.LimitTo(null);

	// wait while the mg42 is mounted by enemy
	for(timeout = 0; ;++timeout)
	{
		owner = this.Bot.GetMountedPlayerOnMG42(this.GoalEnt);
		if (!owner){ break; }
		if (this.Bot.IsAllied(owner)){ this.Finished(); }
		if (timeout > 10)
		{
			this.BlackboardDelay(10);
			Util.ScriptDebugPrint(this.MapGoal.GetName(), "timedout");
			this.Finished();
		}
		sleep(1);
	}

	// bot can't shoot if he mounts mg42 while reloading,
	// because RELOADING entity flag is not cleared (probably bug in the interface)
	while (this.Bot.HasEntityFlag(ENTFLAG.RELOADING)) {
		sleep(0.2);
	}

	timeout = 0;
	CampTime = RandFloat(this.MapGoal.MinCampTime, this.MapGoal.MaxCampTime);
	while(timeout < CampTime)
	{
		if (!this.Bot.HasAnyEntityFlag(ENTFLAG.MNT_MG42)) {
			// can't mount it
			if (timeout > 3) {
				this.BlackboardDelay(10);
				Util.ScriptDebugPrint(this.MapGoal.GetName(), "timedout");
				this.Finished();
			}
			else {
				// try to mount it
				this.AddAimRequest(Priority.High, "position", this.MapGoal.GetPosition());
				this.Bot.HoldButton(BTN.BACKWARD, 0.5); // sometimes if they are too close it's unmountable
				this.Bot.PressButton(BTN.USE);
				this.UseTime = GetTime();
			}
		}
		else // mounted
		{
			// doing this here rather than in Enter() so it won't require respawn
			vectors = this.MapGoal.AimVectors;
			if (!vectors || tableCount(vectors) == 0)
			{
				// get the mg42 properties if we don't have them yet
				if (!this.Facings) {
					MG42Info = {};
					this.Bot.GetMG42Info(MG42Info);
					this.Facings = {
						MG42Info.CenterFacing,
						MG42Info.CenterFacing, // weighted towards middle
						Vec3FromSpherical(0, 0, MG42Info.MinHorizontal),
						Vec3FromSpherical(0, 0, MG42Info.MaxHorizontal)
					};
				}
				vectors = this.Facings;
			}
			r = Util.GetRandomTableValue(vectors);
			this.AddAimRequest(Priority.Low, "facing", r);
			if (this.Debug) {
				goalPos = this.MapGoal.GetPosition() + Vec3(0,0,12);
				DrawArrow(goalPos,goalPos+r*64,COLOR.YELLOW,2);
			}
		}

		++timeout;
		sleep(1);
	}

	this.BlackboardDelay(10);
	this.Finished();
};

//disable combat movement when a bot is near mg42, so that he can mount it
this.DisableCombat = function()
{
	for(;;)
	{
		dist = this.Bot.DistanceTo(this.MapGoal.GetPosition());
		if (dist < 600)
		{
			if (!this.Bot.DisableCombatMovement)
			{
				this.CombatMovementDisabled = true;
				this.Bot.DisableCombatMovement = true;
			}
			break;
		}
		sleep((dist-500)/320);
	}
};

this.Exit = function()
{
	if (this.CombatThread) {
		this.KillThread(this.CombatThread);
	}
	if (this.CombatMovementDisabled) {
		this.Bot.DisableCombatMovement = false;
		this.CombatMovementDisabled = false;
	}
	this.Facings = null;

	if (this.UseTime > GetTime() - 0.1){
		//wait 2 frames because ENTFLAG.MNT_MG42 is false immediately after mount
		sleep(0.1);
	}
	if (this.Bot && this.Bot.HasEntityFlag(ENTFLAG.MNT_MG42)) {
		this.Bot.PressButton(BTN.USE);
	}
};
