///////////////////////////////////////////////////////////////////////////////

Commands["aim_debug_reload"] =
{
	Func = function( _params )
	{
		foreach ( bot in BotTable )
			{ bot.ReloadProfile(); }
	},

	Help =
	{
		"Aim Debug Reload, reloads each bots profile",
		"Usage: /bot aim_debug_reload",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["cvp"] =
{
	Func = function( _params )
	{
		ETUtil.CheckVehiclePath( _params );
	},

	Help =
	{
		"Check Vehicle Path, test bots ability to repair the vehicle along its entire path",
		"Usage: /bot cvp <goalname> <optional seconds>",
		"       goalname should be set to the BUILD goal of the vehicle",
		"       seconds can be optionally set to adjust the interval between the vehicle being damaged",
		"       run the command again to turn it off",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["bvp"] =
{
	Func = function( _params )
	{
		ETUtil.BuildVehiclePath( _params );
	},

	Help =
	{
		"Build Vehicle Path, damages a vehicle to assist the waypointer in creating the vehicle path",
		"Usage: /bot bvp <goalname> <optional seconds>",
		"       goalname should be set to the MOVER or BUILD goal of the vehicle",
		"       seconds can be optionally set to adjust the interval between the vehicle being damaged",
		"       run the command again to turn it off",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["wt"] =
{
	Func = function( _params )
	{
		ETUtil.WarpTo( _params );
	},

	Help =
	{
		"Warp To, will teleport player to given goal or waypoint name if cheats are enabled",
		"Usage: /bot wt <goalname|wpname>",
	},
};

Commands["warpto"] = Commands["wt"];

///////////////////////////////////////////////////////////////////////////////

Commands["wb"] =
{
	Func = function( _params )
	{
		ETUtil.WarpTestBot( _params );
	},

	Help =
	{
		"Warp Test Bot, will teleport testbot to given waypoint name if cheats are enabled",
		"Usage: /bot wb <wpname>",
	},
};

Commands["warpbot"] = Commands["wb"];

///////////////////////////////////////////////////////////////////////////////

Commands["wab"] =
{
	Func = function( _params )
	{
		ETUtil.WarpAnyBot( _params );
	},

	Help =
	{
		"Warp any bot, will teleport a bot matching given name to the player",
		"Usage: /bot wab",
	},
};

Commands["warpanybot"] = Commands["wab"];

///////////////////////////////////////////////////////////////////////////////

Commands["wtgo"] =
{
	Func = function( _params )
	{
		ETUtil.WarpToGoalOffset( _params );
	},

	Help =
	{
		"Warp To Goal Offset, will teleport player to given goal real world offset if cheats are enabled",
		"Usage: /bot wtgo <goalname> <x> <y> <z>",
	},
};

Commands["warptogoaloffset"] = Commands["wtgo"];

///////////////////////////////////////////////////////////////////////////////

Commands["rollcall"] =
{
	Func = function( _params )
	{
		Util.RollCall();
	},

	Help =
	{
		"Roll Call, lists each bots name, team, class, and entity",
		"Usage: /bot rollcall",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["moveskill"] =
{
	Func = function(_params)
	{
		if ( !_params[0] )
		{
			ms = ConfigGet("CombatMovement","moveskill", ms);
			print( "Combat Movement Difficulty is", ms );
			return;
		}

		if ( _params[0] < 0 || _params[0] > 4 )
		{
			Error( "ERROR: Invalid moveskill. Valid values are from 0 to 4 " );
			return;
		}

		ConfigSet("CombatMovement","moveskill", _params[0] );

		foreach ( bot in BotTable )
		{
			if ( _params[0] == 4 )
			{
				r = RandInt(0, 3);
				bot.moveskill = r;
				continue;
			}

			bot.moveskill = _params[0];
		}

		print( "Combat Movement difficulty set to ", _params[0] );
	},

	Help =
	{
		"Combat Difficulty, sets persistent combat movement difficulty",
		"0 = off, 1 = easy, 2 = medium, 3 = hard, 4 = random",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["tracearty"] =
{
	Func = function( _params )
	{
		if ( _params[0] == "all" )
		{
			ETUtil.TraceAllArty();
		}
		else
		{
			ETUtil.TraceArty(_params[ 0 ]);
		}
	},

	Help =
	{
		"Runs a trace to find arty targets from closest arty goal",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["draw_oids"] =
{
	Func = function( _params )
	{
		ETUtil.DrawObjectiveInfoDisplays();
	},

	Help =
	{
		"Draw Objective Info Displays, waypoint tool. draws the bounds of all OID's in the map",
		"Usage: /bot draw_oids",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["draw_spawns"] =
{
	Func = function( _params )
	{
		ETUtil.DrawSpawns();
	},

	Help =
	{
		"Draw spawn points, waypoint tool. draws the bounds of all spawn points in the map",
		"Usage: /bot draw_spawns",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["fgp"] =
{
	Func = function( _params )
	{
		wpTable = table();

		goalTable = Util.GoalTable("CAMP.*\nDEFEND.*\nATTACK.*\nSNIPE.*\nROUTE.*\nMOBILE.*\nCAPPOINT.*\nPLANTMINE.*\n.*ART.*");

		foreach ( goal in goalTable )
		{
			tag = goal.GetTagName();
			type = goal.GetGoalType();
			pos = goal.GetPosition();

			if ( Wp.GetWaypointByName(tag, wpTable) )
			{
				foreach( flag and set in wpTable.flags )
				{
					if ( !flag.CompareNoCase(type) )
					{
						// tagname == wp name and goal type == wp flag. woot
						// so it's a match. now check z coord for the fubar ones
						if ( wpTable.position.z - pos.z > 54 )
						{
							goal.SetPosition(wpTable.position + Util.WaypointGoalOffset);
							goal.RenderGoal = true;
							print ( goal.GetName(), "needs checked. it was detected as being too low and moved" );
						}
					}
				}
			}

			tableClear(wpTable);
		}

	},

	Help =
	{
		" fix waypoint based goal positions that were incorectly set to ground position",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["fgs"] =
{
	Func = function( _params )
	{
		wpTable = table();

		goalTable = Util.GoalTable("CAMP.*\nDEFEND.*\nATTACK.*\nSNIPE.*");

		foreach ( goal in goalTable )
		{
			oldtag = goal.GetTagName();
			type = goal.GetGoalType();
			pos = goal.GetPosition();
			tag = oldtag.ReplaceCharsInSet().TrimRight(); // replaces spaces with _

			if ( Wp.GetWaypointByName(oldtag, wpTable) )
			{
				foreach( flag and set in wpTable.flags )
				{
					stanceChanged = false;
					if ( !flag.CompareNoCase(type) )
					{
						foreach ( ptype and value in wpTable.property )
						{
							if ( ptype == "stance" )
							{
								goal.SetProperty("Stance", value);
								stanceChanged = true;
								goal.RenderGoal = true;
								print(goal.GetName(), "stance changed to", value);
							}
						}
					}

					if ( _params[0] == 1 && set == 1 && (flag == "crouch" || flag == "prone" ) )
					{
						// can we remove the flag?
						removeFlag = false;
						offset = Vector3(0,0,200);
						tr = TraceLine( wpTable.position, wpTable.position + offset, 0, TRACE.SHOT, 0, false );

						if ( !tr.end )
						{
							dist = 200;
						}
						else
						{
							dist = DistanceBetween(wpTable.position, tr.end);
						}

						if ( dist > 70 )
						{
							removeFlag = true;
						}
						else if ( dist > 40 && flag == "prone" )
						{
							removeFlag = true;
						}

						if ( removeFlag )
						{
							Wp.SetWaypointFlag(oldtag, flag, false);

							// set the property too so it works without a goals file
							Wp.SetWaypointProperty(oldtag, "stance", flag);

							print( "waypoint flag", flag, "removed from", tag );
						}

						// default to property setting
						if ( !stanceChanged )
						{
							goal.SetProperty("Stance", flag);
							stanceChanged = true;
							goal.RenderGoal = true;
							print(goal.GetName(), "stance changed to", flag);
						}
					}
				}
			}

			tableClear(wpTable);
		}

		if ( _params[0] == 1) {
			print("all stances fixed based on waypoint properties and waypoint flags");
		}
		else {
			print("all stances fixed based on waypoint properties. note: use /bot fgs 1 to fix based on flags and properties");
		}
	},

	Help =
	{
		" fix waypoint based goal stances. optionally use /bot fgs 1 to check for waypoint flags",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["stuckstart"] =
{
	Func = function( _params )
	{
		if ( !ETUtil.CheatsEnabled() ) {
			return;
		}

		stuckagefile = GetMapName() + "_stuckages.gm";
		assert( ExecScript( stuckagefile ), "Error opening " + stuckagefile + "!" );

		// copy all non-dupes to a temp table
		temp = {};
		dupeCount = 0;
		foreach ( pos in Stuckages ) {
			dupe = false;
			foreach ( tempId and tempPos in temp ) {
				if ( DistanceBetween(pos, tempPos) < 150 ) {
					dupe = true;
				}
			}
			if (!dupe) {
				temp[ tableCount(temp) ] = pos;
			}
			else {
				dupeCount += 1;
			}
		}

		print(format("^3omitted %d duplicates", dupeCount));

		ind = 0;
		total = tableCount(temp);
		foreach ( pos in temp ) {
			ind += 1;
			EchoToScreen(2.0, "^1at stuckage pos "+ ind + " of " + total);
			s = "setviewpos " + pos.x + " " + pos.y + " " + pos.z + " " + " 0";
			ExecCommandOnClient(GetLocalEntity(), s);
			block("nextstuck");
		}


		if ( ind == 0 ) {
			print("no stuckage vectors defined for this map");
		}
		else {
			print("finished iterating through stuckage vectors");
		}
	},

	Help =
	{
		"start iterating through the stuckage table for the map",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["stucknext"] =
{
	Func = function( _params )
	{
		signal("nextstuck");
	},

	Help =
	{
		"used with stuckage checking. sends a signal to advance to the next stuckage vector",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["plantstart"] =
{
	Func = function()
	{
		if ( !ETUtil.CheatsEnabled() ) {
			return;
		}

		positions = {};
		// get a table of the plant goals in the map,
		// store waypoint positions so that we don't have to noclip out of the goal
		foreach( goal in Util.GoalTable("PLANT_.*") ) {
			pos = Vector3();
			way = Wp.GetClosestWaypoint(goal.GetPosition());
			if(way){ pos = way.position; }
			positions[ goal.GetName() ] = pos;
		}

		// render the plant goals
		ExecCommand("draw_goals on PLANT_.*");

		// loop through and warp to the waypoints near plant goals
		ind = 0;
		total = tableCount(positions);
		foreach ( id and waypos in positions ) {
			ind += 1;
			EchoToScreen(10.0, "^1at plant goal "+ ind + " of " + total + "\n^2" + id);
			s = "setviewpos " + waypos.x + " " + waypos.y + " " + waypos.z + " " + " 0";
			ExecCommandOnClient(GetLocalEntity(), s);
			if (block("nextplant", "stopplant") == "stopplant") { break; }
		}

		if ( ind == 0 ) {
			print("no plant goals in this map");
		}
		else {
			print("finished iterating through plant goals");
		}
	},

	Help =
	{
		"start iterating through the plant goals in the map. helper for adding cover spots",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["plantnext"] =
{
	Func = function( _params )
	{
		if (_params[0] && _params[0] == "stop") {
			signal("stopplant");
		}
		else {
			signal("nextplant");
		}
	},

	Help =
	{
		"sends a signal to advance to the next plant goal position. waypoint tool for adding cover spots",
	},
};

///////////////////////////////////////////////////////////////////////////////
// guess i coulda made one command that took a query string. oh well, sue me
Commands["campstart"] =
{
	Func = function( _params )
	{
		if ( !ETUtil.CheatsEnabled() ) {
			return;
		}

		// get a table of the camp type goals in the map
		goals = Util.GoalTable("CAMP.*\nDEFEND.*\nATTACK.*\nSNIPE.*");

		foreach ( goal in goals )
		{
			goalPos = goal.GetPosition();
			goalName = goal.GetName();
			ExecCommand("draw_goals on " + goalName);
			if ( goal.AimVectors ) {
				EchoToScreen(3, "^3" + goalName + " has " + tableCount(goal.AimVectors) + " facings");
			}
			else {
				EchoToScreen(3, "^1" + goalName + " has no facings!");
			}
			z = goalPos.z + 24.0; // up a bit to avoid clip
			s = "setviewpos " + goalPos.x + " " + goalPos.y + " " + z + " " + " 0";
			ExecCommandOnClient(GetLocalEntity(), s);
			yield();yield();
			ExecCommand("goal_edit");
			if (block("nextcamp", "stopcamp") == "stopcamp") { break; }
			ExecCommand("goal_finish");
			ExecCommand("draw_goals off " + goalName);
		}

		print("finished iterating through camp goals");
	},

	Help =
	{
		"start iterating through the camp goals in the map. helper for adding facings",
		"note: when warped, it will automatically select the goal",
		"binding a key to /bot goal_setproperty facing 99 will make things fast!",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["campnext"] =
{
	Func = function( _params )
	{
		if (_params[0] && _params[0] == "stop") {
			signal("stopcamp");
		}
		else {
			signal("nextcamp");
		}
	},

	Help =
	{
		"sends a signal to advance to the next camp goal position. waypoint tool for adding camp facings",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["saveplayerpos"] =
{
	Func = function( _params )
	{
		pos = GetLocalPosition();
		string = ToString( _params[0] ) + ": Vec3(" + ToInt(pos.x) + "," + ToInt(pos.y) + "," + ToInt(pos.z) + ")";
		DrawDebugLine( pos - Vec3(0,0,6), pos + Vec3(0,0,6), COLOR.CYAN, 15 );

		MapName = GetMapName();
		gmName = MapName + "_positions.txt";
		gmfile = File();
		assert( gmfile.Open( gmName, "text", false, true ), "^1Error writing to file!" );
		assert( gmfile.Write( string, System.NewLine ), "^1Error writing to file!" );
		gmfile.Close();
		print( "Current player position written to " + gmName + ". Drawing cyan debug line for 15 seconds." );
	},

	Help =
	{
		"Waypointing tool - writes player positions to a file in user folder",
	},
};

Commands["spp"] = Commands["saveplayerpos"];

///////////////////////////////////////////////////////////////////////////////

Commands["saveusepoint"] =
{
	Func = function( _params )
	{
		if ( _params[0] )
			{ regEx = _params[0]; }
		else
			{ regEx = ".*"; }
		goal = Util.FindClosestGoal( 200, regEx );
		if ( !goal )
		{
			print( "No goal found!" );
			return;
		}
		goalname = goal.GetName();
		print( "Using goal: " + goalname );
		pos = GetLocalPosition();
		string = "Util.AddUsePoint( \"" + goalname + "\", Vec3(" + ToInt(pos.x) + "," + ToInt(pos.y) + "," + ToInt(pos.z) + ") );";
		DrawDebugLine( pos - Vec3(0,0,6), pos + Vec3(0,0,6), COLOR.CYAN, 15 );

		MapName = GetMapName();
		fileName = MapName + "_positions.txt";
		file = File();
		assert( file.Open( fileName, "text", false, true ), "^1Error writing to file!" );
		assert( file.Write( string, System.NewLine ), "^1Error writing to file!" );
		file.Close();
		print( "Usepoint written to " + fileName + ". Drawing cyan debug line for 15 seconds." );
	},

	Help =
	{
		"Waypointing tool - stores player position as usepoint in a file in user folder",
	},
};

Commands["sup"] = Commands["saveusepoint"];

///////////////////////////////////////////////////////////////////////////////

Commands["difficulty"] =
{
	Func = function( _params )
	{
		if(tableCount(_params))
		{
			ConfigSet("Difficulty","CurrentDifficulty", Clamp( ToInt(_params[0], 4), -1, 6 ) );
		}

		print("Difficulty:", ConfigGet("Difficulty","CurrentDifficulty", 4));
	},

	Help =
	{
		"Sets the bots difficulty (-1...6), -1 is random, default 4",
	},
};

////////////////////////////////////////////////////////////////////

Commands["resetxp"] =
{
	Func = function( _params )
	{
		resetXP = ToInt(_params[0], 1);
		ConfigSet("XP","Reset", resetXP);
		if(resetXP > 0){
			print("reset xp enabled");
		}else{
			print("reset xp disabled");
		}
	},

	Help =
	{
		"enables bots resetting xp. use -1 to disable",
	},
};

Commands["maxxp"] =
{
	Func = function( _params )
	{
		if(tableCount(_params))
		{
			ConfigSet("XP","Max", ToInt(_params[0], 10000));
		}
		print("max xp:", ConfigGet("XP","Max", 10000));
	},

	Help =
	{
		"max xp before bots should reset",
	},
};

///////////////////////////////////////////////////////////////////////////////

Commands["cleargoalflags"] =
{
	Func = function( _params )
	{
		flags = { "attack", "defend", "mobilemg42", "mobilemortar", "snipe", "callartillery", "artillery_s", "artillery_d", "plantmine", "route" , "cappoint", "ammo", "health" };
		indexedFlags = {};
		foreach (f in flags) { indexedFlags[f] = 1; }
		wpTable = {};
		Wp.GetAllWaypoints(wpTable);
		foreach( id and wp in wpTable ) {
			foreach( flag and set in wp.flags ) {
				if(indexedFlags[flag]){
					name = wp.name;
					if(!name){ name = wp.guid; }
					print(flag, name);
					Wp.SetWaypointFlag(wp.guid, flag, false);
					Wp.SetWaypointName(id, "");
					if(flag == "defend" || flag == "attack" || flag == "snipe") {
						Wp.SetWaypointFlag(wp.guid, "crouch", false);
						Wp.SetWaypointFlag(wp.guid, "prone", false);
					}
				}
			}
		}
	},

	Help =
	{
		"clears deprecated waypoint flags (attack, snipe, ...) and names of those waypoints",
	},
};
