// This script contains functionality to allow bots to camp on a given position. It can be restricted to specific weapons (panzer, flamethrower, sniper).
this.Name = "CAMP";
this.Parent = "HighLevel";
this.SkipGetPriorityWhenActive = true;
this.Debug = false;
this.query = { 0xa9ef3654 /* CAMP */, 0x4fed19c1 /* DEFEND */, 0x4595b8fd /* ATTACK */, 0xe8fbadc0 /* SNIPE */ };

this.GetPriority = function()
{
	Util.GetPriority(this, this.query);
};

this.Enter = this.MarkInProgress;

this.Exit = function()
{
	this.Bot.ReleaseButton(BTN.CROUCH, BTN.PRONE);

	// restore combat movement restrictions
	if (this.CombatMovementDisabled) {
		this.Bot.DisableCombatMovement = false;
		this.CombatMovementDisabled = false;
	}

	// restore weapon desirability
	wpn = this.DesirableWeapon;
	if (wpn) {
		this.DesirableWeapon = null;
		//command /bot reload_weapons causes error "getdot failed on null user type"
		wpn.PrimaryFire.DefaultDesirability = this.OldDesirability;
		this.OldDesirability = null;
		if (this.DisabledReload) {
			this.DisabledReload = false;
			wpn.PrimaryFire.IgnoreReload = false;
		}
	}
};

this.Update = function()
{
	position = this.MapGoal.GetPosition();
	Util.RouteTo(this);

	UsingWeapon = 0;
	IsSniper = null;

	if (this.MapGoal.Weapons)
	{
		if (tableCount(this.MapGoal.Weapons) > 0)
		{
			UsingWeapon = this.Bot.HasAnyWeapon(this.MapGoal.Weapons, { CheckCharged=false, CheckAmmo=false });
			IsSniper = Util.IndexedSniperWeapons[UsingWeapon];
		}
	}
	else if (this.Debug)
	{
		print(this.MapGoal.GetName() + " has no Weapons Table");
	}

	if(this.Debug)
	{
		print("camp goal update", Util.WeaponName(UsingWeapon), UsingWeapon, IsSniper);
	}

	if (this.MapGoal.DisableCM && !this.Bot.DisableCombatMovement)
	{
		this.CombatMovementDisabled = true;
		this.Bot.DisableCombatMovement = true;
	}

	if (!this.DesirableWeapon)
	{
		wpn = UsingWeapon;
		if (!wpn) {
			wpn = ETUtil.GetBotPrimaryWeapon(this.Bot);
		}
		// AddWeaponRequest cannot be used because it ignores ammo and charge
		if (wpn) {
			weap = this.Bot.GetWeapon(wpn);
			if (weap) {
				this.OldDesirability = weap.PrimaryFire.DefaultDesirability;
				this.DesirableWeapon = weap;
				if (UsingWeapon) {
					weap.PrimaryFire.DefaultDesirability = 0.9;
					if (IsSniper && !weap.PrimaryFire.IgnoreReload) {
						weap.PrimaryFire.IgnoreReload = true;
						this.DisabledReload = true;
					}
				} else if(this.OldDesirability > 0) {
					weap.PrimaryFire.DefaultDesirability = this.OldDesirability + 0.15;
				}
			}
		}
	}

	peektime = 0;
	minz = this.MapGoal.GetPosition().z - Max(this.MapGoal.Radius, 32.0) - 70;
	CampTime = RandFloat(this.MapGoal.MinCampTime, this.MapGoal.MaxCampTime);
	for (timeout = 0; timeout < CampTime; ++timeout)
	{
		if (this.MapGoal.GetPosition() != position)
		{
			//go to a new position
			this.ReleaseAimRequest();
			return;
		}
		if (this.Bot.GetPosition().z < minz)
		{
			Util.ScriptDebugPrint(this.MapGoal.GetName(), "pathfailed", "fell down to " + this.Bot.GetPosition());
			if (timeout==0) { break; } //BlackboardDelay
			this.ReleaseAimRequest();
			return; //go to the same goal
		}
		if (UsingWeapon && !this.Bot.HasAmmo(UsingWeapon))
		{
			if(this.Debug)
			{
				print("camp goal has no ammo for", Util.WeaponName(UsingWeapon));
			}
			this.BlackboardDelay(20);
			this.Finished();
		}

		switch (this.MapGoal.Stance)
		{
			case "crouch":
			{
				this.Bot.HoldButton(BTN.CROUCH, 1.1);
			}
			case "prone":
			{
				this.Bot.HoldButton(BTN.PRONE, 1.1);
			}
			case "peek":
			{
				if (timeout % RandInt(2,4) == 0) { // stand
					if (peektime == 0) {
						peektime = timeout + this.Bot.ReactionTime + 1;
					}
				}
				else if (timeout >= peektime) { // hide
					peektime = 0;
					this.Bot.HoldButton(BTN.CROUCH, RandInt(1,3));
				}
			}
		}

		if (IsSniper && this.Bot.GetCurrentWeapon()==UsingWeapon)
		{
			this.Bot.HoldButton(BTN.AIM, 1.1);
		}

		this.AddAimRequest(Priority.Low, "facing", Util.GetRandomTableValue(this.MapGoal.AimVectors));

		sleep(1);
	}

	// don't choose the same camp spot
	this.BlackboardDelay(5);
	this.Finished();
};
