// It is also possible to register custom commands, that will be called in a similar way to the other bot commands,
// such as /bot waypoint. These command functions will recieve a table that is filled with all the additional options
// that were part of the command.
// For example, if the user typed the following command into the games console
//		testme hi how are you
//	This testcommand function would be called, and the params variable would be a table that contains 4 items
//	These items can be referenced by a number, such as params[0], params[1], etc...
// Script commands are an easy way to bind complex script functions to a command that can be executed from
// the games console.

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

Commands["testme"] =
{
	Func	= function(_params)
	{
		print("Test Command");
		foreach ( name and val in _params )
		{ print( name, typeName(val), val ); }
	},
	Help =
	{
		"Test command, prints out all arguments",
		"Usage: /bot testme",
	},
};

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

Commands["showweapons"] =
{
	Func = function(_params)
	{
		print("Printing Weapon List");

		foreach ( name and Id in WEAPON )
			{ print("Weapon " + name +" : id " + Id); }
	},

	Help =
	{
		"Show Weapons, lists all weapons in the WEAPON table",
		"Usage: /bot showweapons",
	},
};

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

Commands["showevents"] =
{
	Func = function(_params)
	{
		print("Printing Event List");

		foreach ( name and Id in EVENT )
			{ print("Event " + name +" : id " + Id); }
	},

	Help =
	{
		"Show Events, lists all events in the EVENT table",
		"Usage: /bot showevents",
	},
};

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

Commands["dumpglobals"] =
{
	Func = function(_params)
	{
		print("Dumping Global functions, references and typefunctions");
		dumpGlobals("globals_functions.gm", DUMP.FUNCTIONS);
		dumpGlobals("globals_references.gm", DUMP.REFERENCES);
		dumpGlobals("globals_typefunctions.gm", DUMP.TYPEFUNCTIONS);
		dumpGlobals("globals_all.gm", DUMP.ALL);
		dumpGlobals("globals_all2.gm");
	},

	Help =
	{
		"Dump Globals, writes all functions and references to files in the ~\user directory",
		"Usage: /bot dumpglobals",
	},
};

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

Commands["autosave"] =
{
	Func = function(_params)
	{
		delay = ToInt(_params[0], 20);
		if(delay < 5) { delay = 5; }

		ExecCommand("waypoint_view 1");
		Util.EnableWaypointAutoSave( true, delay );
	},

	Help =
	{
		"My Waypoint Mode, enables waypoint view and autosave",
		"Usage: /bot mywpmode",
	},
};

Commands["mywpmode"] = Commands["autosave"];

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

Commands["numthreads"] =
{
	Func = function(_params)
	{
		print("Number of threads", tableCount(threadAllIds()));
	},

	Help =
	{
		"Number of Threads, prints the number of current threads",
		"Usage: /bot numthreads",
	},
};

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

Commands["goal_exp"] =
{
	Func = function(_params)
	{
		print("goal_exp");

		foreach ( index and goal in Util.GoalTable(_params[0]) )
			{ print(index, goal, goal.GetName()); }
	},

	Help =
	{
		"Goal Exp, lists each goal index, mapgoal, and name",
		"Usage: /bot goal_exp",
	},
};

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

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

	Help =
	{
		"Skip, sets Util.Skip to true",
		"Usage: /bot skip",
		"Note: Util.Skip is used in some debugging functions",
	},
};

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

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

	Help =
	{
		"Skip Reset, sets Util.Skip to false",
		"Usage: /bot skipreset",
		"Note: Util.Skip is used in some debugging functions",
	},
};

///////////////////////////////////////////////////////////////////////////////
//
// This is a Game Monkey Script function that creates a thread using the function we defined above.
// Uncomment the following line if you want to run the function above.
//thread(stresstest);

Commands["stresstest"] =
{
	Func = function(_params)
	{
		thread( Util.StressTest );
	},

	Help =
	{
		"Stress Test, this command should only be used by developers",
		"Usage: /bot stresstest",
	},
};

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

Commands["dg"] =
{
	Func = function( _params )
	{
		Util.DisplayGoal( _params[ 0 ], _params[ 1 ] );
	},

	Help =
	{
		"Display Goal, runs a thread that lists the given goals name, position, and facing",
		"Usage: /bot dg <goalname> <true|false>",
		"Note: useful for mover type goals",
	},
};

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

Commands["dwon"] =
{
	Func = function( _params )
	{
		EnableDebugWindow( 1 );
	},

	Help =
	{
		"Debug Window On, opens up the debug window",
		"Usage: /bot dwon",
	},
};

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

Commands["dwoff"] =
{
	Func = function( _params )
	{
		EnableDebugWindow( 0 );
	},

	Help =
	{
		"Debug Window Off, closes the debug window",
		"Usage: /bot dwoff",
	},
};

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

Commands["kt"] =
{
	Func = function( _params )
	{
		Util.KillTeam( _params[ 0 ] );
	},

	Help =
	{
		"Kill Team, kills all bots on the given team",
		"Usage: /bot kt <teamname>",
	},
};

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

Commands["showentityinfo"] =
{
	Func = function( _params )
	{
		if ( _params[0] ) {
			type = Util.GetTableValue(TRACE, ToString(_params[0]));
			if(!type){ Error("ERROR: Invalid TRACE parameter"); }
		}
		Util.ShowEntityInfo(type);
	},

	Help =
	{
		"Show Entity Info, runs a traceline and returns entity information",
		"Usage: /bot sei <trace_mask>",
	},
};

Commands["sei"] = Commands["showentityinfo"];

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

Commands["sg"] =
{
	Func = function( _params )
	{
		Util.SetGoal( _params[ 0 ], _params[ 1 ] );
	},

	Help =
	{
		"Set Goal, enables the given goalname for the given team",
		"Usage: /bot sg <goalname> <team>",
	},
};

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

Commands["cg"] =
{
	Func = function( _params )
	{
		Util.ClearGoal( _params[ 0 ], _params[ 1 ] );
	},

	Help =
	{
		"Clear Goal, disables the given goalname for the given team",
		"Usage: /bot cg <goalname> <team>",
	},
};

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

Commands["wpa"] =
{
	Func = function( _params )
	{
		Util.AddWaypointArray( _params[ 0 ], _params[ 1 ], _params[ 2 ],
			_params[ 3 ] );
	},

	Help =
	{
		"Waypoint Array, adds an array of waypoints numx by numy, distx and disty apart",
		"Usage: /bot wpa <numx> <distx> <numy> <disty>",
	},
};

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

Commands["tracebox"] =
{
	Func = function( _params )
	{
		drawfunc = function()
		{
			delay = 0.5;

			while(TRACE_BOX)
			{
				localaabb = GetLocalAABB();
				TRACE_BOX.Expand(localaabb);
				TRACE_BOX.Render(delay);
				sleep(delay);
			}
		};

		if(!TRACE_BOX)
		{
			print("Starting Box Trace");
			p = GetLocalPosition();
			global TRACE_BOX = AABB(p,p);
			thread(drawfunc);
		}
		else
		{
			print("Trace Box ", TRACE_BOX);
			TRACE_BOX.Render(10);

			global TRACE_BOX = null;
		}
	},

	Help =
	{
		"Trace Box, builds an AABB based on the players position",
		"Usage: /bot tracebox",
	},
};

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

Commands["tracetrajectory"] =
{
	Func = function( _params )
	{
		drawfunc = function()
		{
			delay = 1.0;

			while(TRACE_TRAJECTORY)
			{
				DrawTrajectory(TRACE_TRAJECTORY,COLOR.MAGENTA,delay);
				sleep(delay);
			}
		};

		if(!TRACE_TRAJECTORY)
		{
			if(_params[0] == null)
			{
				print("tracetrajectory usage: tracetrajectory speed interval[optional] duration[optional] bounceloss[optional]");
				return;
			}

			speed = ToFloat(_params[0]);
			interval = ToFloat(_params[1],0.1);
			duration = ToFloat(_params[2],5.0);
			bounceloss = ToFloat(_params[3],1.0);

			print("Starting Trajectory Trace");

			global TRACE_TRAJECTORY =
			{
				Position = GetLocalEyePosition(),
				Velocity = GetLocalFacing() * speed,
				Interval = interval,
				Duration = duration,
				BounceLoss = bounceloss,
				StopAtHit = false,
			};

			thread(drawfunc);
		}
		else
		{
			global TRACE_TRAJECTORY = null;
		}
	},

	Help =
	{
		"Draws trajectory from player position and facing",
		"Usage: /bot tracetrajectory speed interval[optional] duration[optional] bounceloss[optional]",
	},
};

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

Commands["trigger_bounds"] =
{
	Func = function( _params )
	{
		drawfunc = function()
		{
			delay = 0.5;

			while(TRACE_TRIGGER)
			{
					localaabb = GetLocalAABB();
					TRACE_TRIGGER.Expand(localaabb);
					TRACE_TRIGGER.Render(delay);
					sleep(delay);
			}
		};

		if(!TRACE_TRIGGER)
		{
			print("Starting Trigger Trace");
			p = GetLocalPosition();
			global TRACE_TRIGGER = AABB(p,p);
			thread(drawfunc);
		}
		else
		{
			if(_params[0]=="cancel")
			{
				global TRACE_TRIGGER = null;
				return;
			}

			print("Trace Box ", TRACE_TRIGGER);
			TRACE_TRIGGER.Render(10);

			triggerInfo =
			{
				Name="TestTrigger",
				TriggerOnClass=CLASS.ANYPLAYER,
				OnEnter = function(ent)
				{
					print(GetEntName(ent),"entered aabb trigger");
				},
				OnExit = function(ent)
				{
					print(GetEntName(ent),"exited aabb trigger");
				},
			};
			s = OnTriggerRegion(TRACE_TRIGGER,triggerInfo);

			print("AABB Trigger Created:",s);
			print("AABB(",TRACE_TRIGGER,")");

			// write it out to file for easy copy / paste
			gmfile = File();
			fileName = GetMapName() + "_regiontriggers.gm";

			if ( !System.FileExists(fileName) ) {
				assert( gmfile.Open( fileName, "text", false ) );
			}
			else {
				assert( gmfile.Open( fileName, "text", false, true ) );
			}

			if (_params[1] && (_params[0] && RegionTrigger && RegionTrigger[_params[0]])) {
				str = format("RegionTrigger.Create(AABB(%s), \"%s\", \"%s\");", ToString(TRACE_TRIGGER), _params[0], _params[1]);
			}
			else if (_params[0]) {
				str = format("OnTriggerRegion(AABB(%s), Map.%s);", ToString(TRACE_TRIGGER), _params[0]);
			}
			else {
				str = format("OnTriggerRegion(AABB(%s), Map.TRIGGERNAME); // CHANGE TRIGGER NAME", ToString(TRACE_TRIGGER));
			}

			assert( gmfile.Write( str, System.NewLine ) );
			gmfile.Close();
			global TRACE_TRIGGER = null;
		}
	},

	Help =
	{
		"Trigger Bounds, builds an AABB region trigger based on the players position",
		"Usage: /bot trigger_bounds",
	},
};

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

Commands["trigger_aimpos"] =
{
	Func = function( _params )
	{
		radius = 256;
		pt = typeName(_params[0]);
		if(pt=="float"||pt=="int")
		{
			radius =_params[0];
		}
		p = GetLocalAimPosition();

		triggerInfo =
		{
			Name="TestTrigger",
			TriggerOnClass=CLASS.ANYPLAYER,
			OnEnter = function(ent)
			{
				print(GetEntName(ent),"entered sphere trigger");
			},
			OnExit = function(ent)
			{
				print(GetEntName(ent),"exited sphere trigger");
			},
		};
		s = OnTriggerRegion(p,radius,triggerInfo);

		print("Sphere Trigger Created:",TRACE_TRIGGER);
		print("Sphere:",p,"radius",radius);
	},

	Help =
	{
		"Trigger Aim Position, creates a region trigger based on the players aim position",
		"Usage: /bot trigger_aimpos",
	},
};

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

Commands["aim_pos"] =
{
	Func = function( _params )
	{
		print(GetLocalAimPosition());
	},

	Help =
	{
		"Aim Position, lists the players current aim position",
		"Usage: /bot aim_pos",
	},
};

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

Commands["testwin"] =
{
	Func = function( _params )
	{
		RunScript("testdebugwindows.gm");
	},

	Help =
	{
		"Test Windows, tests the debug window script testdebugwindows.gm",
		"Usage: /bot testwin",
	},
};

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

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

	Help =
	{
		"Test Map, starts the auto testing of maps based on the testmap scripts",
		"Usage: /bot testmap",
	},
};

///////////////////////////////////////////////////////////////////////////////
// The command, "\bot makegm",  executes the function Mapgm.MakeMapgm to create
//  a map script in gm script, a testmap script in gm script and a map goal list text file
Commands["makegm"] =
{
	Func = function( _params )
	{
		ExecScript( "makegm.gm" );
		EchoToScreen( 3, "Executing make gm script." );
		print( "Executing make gm script." );
		Mapgm.MakeMapgm( _params );
		Mapgm.MakeTestMapgm( _params );
		Mapgm.MakeMapGoalList( _params );
	},

	Help =
	{
		"Make GM, creates a map script and test map script for the current map",
		"Usage: /bot makegm",
	},
};

///////////////////////////////////////////////////////////////////////////////
// The command, "\bot makemapgm",  executes the function Mapgm.MakeMapgm to create
//  a map script in gm script
Commands["makemapgm"] =
{
	Func = function( _params )
	{
		ExecScript( "makegm.gm" );
		EchoToScreen( 3, "Executing make map gm script." );
		print( "Executing make map gm script." );
		Mapgm.MakeMapgm( _params );
	},

	Help =
	{
		"Make Map GM, creates a map script for the current map",
		"Usage: /bot makemapgm",
	},
};

///////////////////////////////////////////////////////////////////////////////
// The command, "\bot maketestmapgm",  executes the function Mapgm.MakeMapgm to create
//  a testmap script in gm script
Commands["maketestmapgm"] =
{
	Func = function( _params )
	{
		ExecScript( "makegm.gm" );
		EchoToScreen( 3, "Executing make testmap gm script." );
		print( "Executing make map gm script." );
		Mapgm.MakeTestMapgm( _params );
	},

	Help =
	{
		"Make Test Map GM, creates a test map script for the current map",
		"Usage: /bot maketestmapgm",
	},
};

///////////////////////////////////////////////////////////////////////////////
// The command, "\bot makemapgoallist",  executes the function Mapgm.MakeMapgm to create
//  a map goal list text file
Commands["makemapgoallist"] =
{
	Func = function( _params )
	{
		ExecScript( "makegm.gm" );
		EchoToScreen( 3, "Executing make map goal list script." );
		print( "Executing make map goal list script." );
		Mapgm.MakeMapGoalList( _params );
	},

	Help =
	{
		"Make Map Goal List, creates a map goal list for the current map",
		"Usage: /bot makemapgoallist",
	},
};

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

Commands["testbot"] =
{
	Func = function( _params )
	{
		if ( !_params[0] )
		{
			print( "Usage: /bot testbot <team> <class>" );
			return;
		}
		Util.TestBot( _params );
	},

	Help =
	{
		"Test Bot, adds a testbot to the given team with the given class",
		"Usage: /bot testbot <team> <class>",
		"Usage: /bot testbot 0 - kicks the test bot",
		"Note: once a map restarts, the tesbot is released to a regular state",
	},
};

///////////////////////////////////////////////////////////////////////////////
Commands["sgn"] =
{
	Func = function( _params )
	{
		Util.ShowGoalName( _params[ 0 ], _params[ 1 ] );
	},

	Help =
	{
		"Show Goal Name, lists all goals found within the given radius",
		"Usage: /bot sgn <radius> <optional true>",
		"Note: passing the optional true parameter will give player offset",
	},
};

///////////////////////////////////////////////////////////////////////////////
Commands["sgo"] =
{
	Func = function( _params )
	{
		Util.ShowGoalOffset( _params[ 0 ] );
	},

	Help =
	{
		"Show Goal Offset, lists players offset to the given goal",
		"Usage: /bot sgo <goalname>",
	},
};

///////////////////////////////////////////////////////////////////////////////
Commands["sgi"] =
{
	Func = function( _params )
	{
		Util.ShowGoalInfo( _params[ 0 ] );
	},

	Help =
	{
		"Show Goal Info, lists information about the given goal",
		"Usage: /bot sgi <goalname>",
		"Note: lists goals health, DEAD status, entity number, and position",
	},
};

///////////////////////////////////////////////////////////////////////////////
Commands["eob"] =
{
	Func = function( _params )
	{
		Util.ExecOnBots(_params[0]);
	},

	Help =
	{
		"Exec on Bots, executes the given command on all bots",
		"Usage: /bot eob <command>",
	},
};

///////////////////////////////////////////////////////////////////////////////
Commands["dist"] =
{
	Func = function( _params )
	{
		Util.DistanceView(_params[0]);
	},

	Help =
	{
		"Distance View, gives distance to a players aim position",
		"Usage: /bot dist, /bot dist off",
	},
};

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

Commands["kg"] =
{
	Func = function( _params )
	{
		foreach ( Goals in _params )
			{ Util.KillGoal( Goals ); }
	},

	Help =
	{
		"Kill Goal, damage a given goal if cheats are allowed",
		"Usage: /bot kg <goalname>",
	},
};

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

Commands["ip"] =
{
	Func = function( _params )
	{
		Util.IgnorePlayer(_params[0]);
	},

	Help =
	{
		"Ignore Player, bots won't shoot player",
		"Usage: /bot ip <on|off>",
	},
};

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

Commands["cwn"] =
{
	Func = function( _params )
	{
		Util.ClearWaypointNames(_params[0]);
	},

	Help =
	{
		"Clear Waypoint Names, remove all waypoint names",
		"Usage: /bot cwn <optional true>",
		"Note: the true parameter will list each waypoint that has been cleared",
	},
};

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

Commands["dump_autocomplete"] =
{
	Formats =
	{
		Npp =
		{
			CreateFile = function()
			{
				gmfile = File();
				gmName = "omni-bot.xml";
				assert( gmfile.Open( gmName, "text", false ) );
				return gmfile;
			},
			Header = function(gmfile)
			{
				gmfile.Write("<?xml version=\"1.0\" encoding=\"Windows-1252\" ?>", System.NewLine);
				gmfile.Write("<NotepadPlus>", System.NewLine);
				gmfile.Write("	<AutoComplete language=\"GameMonkey\">", System.NewLine);
				gmfile.Write("		<Environment ignoreCase=\"yes\" startFunc=\"(\" stopFunc=\")\" paramSeparator=\",\" terminal=\";\" />", System.NewLine);
			},
			Footer = function(gmfile)
			{
				gmfile.Write("	</AutoComplete>", System.NewLine);
				gmfile.Write("</NotepadPlus>", System.NewLine);
			},
			Var = function(gmfile,name)
			{
				gmfile.Write("			<KeyWord name=\"", name, "\"/>", System.NewLine);
			},
			Func = function(gmfile,name,shortname)
			{
				// does it have a param descriptor?
				if(OmnibotAPI && OmnibotAPI[shortname])
				{
					doc = OmnibotAPI[shortname];

					gmfile.Write("			<KeyWord name=\"", name, "\" func=\"yes\">", System.NewLine);

					foreach ( x and rv in doc.RetVal )
					{
						if(doc.Decription)
						{
							gmfile.Write("				<Overload retVal=\"", rv, "\" desc=\"", doc.Decription, "\">", System.NewLine);
						}
						else
						{
							gmfile.Write("				<Overload retVal=\"", rv, "\">", System.NewLine);
						}



						// if(typeName(doc.Param[x]) == "table")
						// {

						// }

						foreach ( param in doc.Param )
						{
							gmfile.Write("					<Param retVal=\"", param, "\"/>", System.NewLine);
						}

						gmfile.Write("				</Overload>", System.NewLine);
					}

					gmfile.Write("			</KeyWord>", System.NewLine);
				}
				else
				{
					gmfile.Write("			<KeyWord name=\"", name, "\" func=\"yes\"/>", System.NewLine);
				}
			},
		},
	},

	DumpTable = function(gmFile,formattbl,tbl,path)
	{
		dmpTable = Commands["dump_autocomplete"].DumpTable;

		foreach ( name and val in tbl )
		{
			kt = typeName(name);
			vt = typeName(val);

			if(kt != "string")
			{
				continue;
			}

			p = path;
			if(p!="")
			{
				p += ".";
			}
			p += name;

			if(vt == "function")
			{
				formattbl.Func(gmFile,p,name);
			}
			else if(vt == "table")
			{
				formattbl.Var(gmFile,p);
				dmpTable(gmFile,formattbl,val,p);
			}
			else
			{
				formattbl.Var(gmFile,p);
			}
		}
	},

	Func = function( _params )
	{
		ExecScript("functions.gm");

		// dump all format types
		fmtTable = Commands["dump_autocomplete"].Formats;
		dmpTable = Commands["dump_autocomplete"].DumpTable;
		foreach ( name and tbl in fmtTable )
		{
			print("Dumping auto complete for", name);
			gmFile = tbl.CreateFile();
			tbl.Header(gmFile);
			dmpTable(gmFile,tbl,globals(),"");
			tbl.Footer(gmFile);
			gmFile.Close();
			print("Done Dumping auto complete for", name);
		}

		// clear the api table to let go of the memory
		global OmnibotAPI = null;
		sysCollectGarbage(true);
	},

	Help =
	{
		"Creates an xml file for autocompletion with Notepad++",
	},
};

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

Commands["ab"] =
{
	Func = function( _params )
	{
		if ( !IsInt(_params[0]) || _params[0] < 1 )
		{
			Error( "number of bots must be greater than 0" );
			return;
		}

		for ( i = 0; i < _params[0]; i += 1 )
		{
			if(OnBotAutoJoin) {
				// OnBotAutoJoin should give us a table of bot info to use
				t = OnBotAutoJoin();
				// cs: passing an empty table may not give expected results
				if(tableCount(t) != 0) {
					AddBot(t);
				}
				else {
					AddBot();
				}
			}
			else {
				AddBot();
			}
			yield(); // give time for server manager to update bot counts
		}
	},

	Help =
	{
		"Add Bots, add a given number of bots",
		"Usage: /bot ab <numbots>",
	},
};

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

Commands["mypos"] =
{
	Func = function()
	{
		print("pos: ", GetEntPosition(GetLocalEntity()));
		print("facing: ", GetLocalFacing());
	},

	Help =
	{
		"My Position, gets the players current position and facing",
		"Usage: /bot mypos",
	},
};

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

Commands["keepbot"] =
{
	Func = function( _params )
	{
		foundMatch = false;

		foreach ( bot in BotTable )
		{
			n = bot.Name;
			if ( n.Find(_params[0])!= -1 )
			{
				foundMatch = true;
			}
		}

		if (foundMatch)
		{
			foreach ( bot in BotTable )
			{
				n = bot.Name;
				if ( n.Find(_params[0])== -1 )
				{
					KickBot(n);
				}
			}
		}
		else
		{
			print("Keep Bot: No match found, keeping all bots");
		}
	},

	Help =
	{
		"Keep Bot, remove all bots without the given partial name",
		"Usage: /bot keepbot <partial botname>",
	},
};

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

Commands["botgoal"] =
{
	Func = function( _params )
	{
		foreach ( bot in BotTable )
		{
			n = bot.Name;
			if ( !_params[0] || n.Find(_params[0])!= -1 )
			{
				g = bot.GetMapGoalName();
				if(!g){ g = bot.GetHighLevelGoalName(); }
				bot.Say("My high level goal is " + g);
			}
		}
	},

	Help =
	{
		"Bot Goal, used for debugging a bots goal on remote server"
	},
};

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

Commands["testvoice"] =
{
	Func = function( _params )
	{
		if ( !_params[0] )
		{
			Error( "ERROR: command testvoice expects one parameter" );
			return;
		}

		Util.TestVoiceMacro( _params[0] );
	},

	Help =
	{
		" Test Voice Macro, used for testing a bots usage of given voice macro ",
		" usage, /bot testvoice <voice macro name>",
		"example, /bot testvoice NEED_MEDIC",
	},
};

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

Commands["test_priorities"]=
{
	Func = function(_params)
	{
		Util.TestGoalPriorities(_params[0]);
	},

	Help =
	{
		"Test Priorities, test SetGoalPriorities calls on all map goals",
		"usage, /bot test_priorities <bool allgoals>",
		"example: /bot test_priorities true will loop through all goals in the map table"
	},
};

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

Commands["sag"] =
{
	Func = function( _params )
	{
		Util.ShowActiveGoals( _params[0], _params[1], _params[2] );
	},

	Help =
	{
		"Show Active Goals, lists and optionally renders each currently active goal by team",
		"Usage: /bot sag <optional render teamId>, <optional bool routes>, <optional bool show use slots>",
		"Example: /bot sag 0 0 1  - shows active goals for both team plus current MaxInuse and MaxInProgress settings",
	},
};

Commands["showactive"] = Commands["sag"];

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

Commands["wiki_commands"] =
{
	Func = function()
	{
		cmdFile = File();
		assert( cmdFile.Open( "wiki_commands.gm", "text", false ) );
		assert( cmdFile.Write( "{{TOCright}}\n", System.NewLine ) );

		sorted = tableSort(Commands, "key");

		foreach( index and cmd in sorted )
		{
			txt = "===" + cmd + "===";

			if ( Commands[cmd].Help )
			{
				foreach ( i and text in Commands[cmd].Help )
				{
					txt += "\n" + "        " + text;
				}
			}

			assert( cmdFile.Write( txt, System.NewLine ) );
			assert( cmdFile.Write( System.NewLine ) );
		}

		cmdFile.Close();
	},

	Help =
	{
		"write all script commands to a file in wiki markup",
	},
};

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

Commands["table_members"] =
{
	Func = function(_params)
	{
		ExecCommand("script_run Util.ListTableMembers("+ _params[0] + "," + "'" + _params[1] + "');");
	},

	Help =
	{
		"prints a sorted list of table members to the console for the given table name",
		"optionally list by 'value' by passing value as the second param"
	},
};

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

Commands["trace_pos"] =
{
	Func = function( _params )
	{
		print("Trace Position: ", Util.TraceForPosition() );
	},

	Help =
	{
		"returns position from a trace",
	},
};

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

Commands["sendtrigger"] =
{
	TestFunc = function(trigger)
	{
		print("sendtrigger triggered!");
		print("ent: " + trigger.Entity, "action: " + trigger.Action, "activator: " + GetEntName(trigger.Activator));
	},

	Func = function( _params )
	{
		if ( !Commands["sendtrigger"].TriggerInfo )
		{
			Commands["sendtrigger"].TriggerInfo =
			{
				Entity = null,
				Activator = GetLocalEntity(),
				TagName = "Testing SendTrigger",
				Action = "A test of the SendTrigger function",
			};

			OnTrigger( "Testing SendTrigger", Commands["sendtrigger"].TestFunc );
			sleep(1);
		}

		SendTrigger(Commands["sendtrigger"].TriggerInfo);
	},

	Help =
	{
		"test command and example of sending a trigger from script",
	},
};

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

Commands["sysusage"] =
{
	Func = function( _params )
	{
		if (!Util.SystemUsageThread) {
			print("Starting system usage timeline thread");
			Util.SystemUsageThread = thread(Util.SystemUsageTimeline, _params[0]);
		}
		else {
			threadKill(Util.SystemUsageThread);
			Util.SystemUsageThread = null;
			print("Killed system usage timeline thread");
		}
	},

	Help =
	{
		"writes a timeline of system usage stats to systemtimeline.gm",
	},
};

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

Commands["time"] =
{
	Func = function(_params)
	{
		EchoToScreen(3, Util.TimeFormat("time"));
	},

	Help =
	{
		"echo's the current time to the screen",
	},
};

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

Commands["goal_echo"] =
{
	Func = function(_params)
	{
		Util.EchoCloseGoal(150, "Selected");
	},

	Help =
	{
		"echo's the closest enabled and rendering goal within goal_edit range to the screen",
	},
};

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

Commands["showgroup"] =
{
	Func = function(_params)
	{
		Util.ShowGroup(_params[0]);
	},

	Help =
	{
		"lists all goals of a given group in console",
	},
};

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

Commands["dbg_mapscripts"] =
{
	Func = function(_params)
	{
		// toggle it
		global DEBUG_MAP_SCRIPTS = !DEBUG_MAP_SCRIPTS;
		if ( DEBUG_MAP_SCRIPTS ) {
			print("map script debugging enabled");
		}
		else {
			print("map script debugging disabled");
		}
	},

	Help =
	{
		"toggle map script debugging",
	},
};

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

Commands["dbg_goalavailability"] =
{
	Func = function(_params)
	{
		global DEBUG_GOAL_AVAILABILITY = !DEBUG_GOAL_AVAILABILITY;
		if ( DEBUG_GOAL_AVAILABILITY ) {
			print("goal availability debugging enabled");
		}
		else {
			print("goal availability debugging disabled");
		}
	},

	Help =
	{
		"toggle goal availability debugging",
	},
};

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

Commands["dbg_scriptgoals"] =
{
	Func = function(_params)
	{
		global DEBUG_SCRIPT_GOALS = !DEBUG_SCRIPT_GOALS;
		if ( DEBUG_SCRIPT_GOALS ) {
			print("script goals debugging enabled");
		}
		else {
			print("script goals debugging disabled");
		}
	},

	Help =
	{
		"toggle script goals debugging (pathfailed, timedout, ...)",
	},
};

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

Commands["draw_paththrough"] =
{
	Func = function(_params)
	{
		Util.RenderPaththroughNodes(_params[0]);
	},

	Help =
	{
		"render 3d text over paththrough node locations",
	},
};

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

Commands["fix_waterwps"] =
{
	Func = function(_params)
	{
		wpTable = {};
		Wp.GetAllWaypoints(wpTable);

		foreach ( wp in wpTable ) {
			foreach ( flag && set in wp.flags ) {
				if ( flag == "underwater" && set == 1 ) {
					if ( !(GetPointContents(wp.position + Vector3(0,0,128)) & CONTENT.WATER) ) {
						Wp.SetWaypointFlag(wp.guid, "inwater", true);
					}
				}
			}
		}
	},

	Help =
	{
		"adds inwater flag to waypoints close to the water surface",
	},
};

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

Commands["testbotroles"] =
{
	Func = function(_params)
	{
		if ( tableCount(BotTable) < 1 ) {
			print("adding testbot");
			ExecCommand("testbot 1 1");
			yield();
		}

		usebot = null;
		foreach ( bot in BotTable ) {
			usebot = bot;
			break;
		}

		if (!usebot) {
			print("please add a bot first");
			return;
		}

		print("testing single role");
		usebot.SetRoles(ROLE.DEFENDER);
		yield();
		if ( !usebot.HasRole(ROLE.DEFENDER) ) {
			print("single role failed!");
			return;
		}

		print("\ntesting accumulated role");

		usebot.SetRoles(ROLE.DEFENDER1);
		yield();
		if ( !usebot.HasRole(ROLE.DEFENDER) || !usebot.HasRole(ROLE.DEFENDER1) ) {
			print("accumulated role failed!");
			return;
		}

		print("\ntesting single role removal");

		usebot.ClearRoles(ROLE.DEFENDER1);
		yield();
		if ( !usebot.HasRole(ROLE.DEFENDER) || usebot.HasRole(ROLE.DEFENDER1) ) {
			print("single role removal failed!");
			return;
		}

		print("\nall tests passed\n");
	},

	Help =
	{
		"test bot roles",
	},
};

///////////////////////////////////////////////////////////////////////////////
// delete all waypoints that do not have properties / flags
Commands["waypoint_startover"] =
{
	Func = function(params)
	{
		wpTable = {};
		Wp.GetAllWaypoints(wpTable);

		foreach ( wp in wpTable ) {
			keep = false;

			foreach ( flag && set in wp.flags ) {
				if ( set == 1 ) {
					keep = true;
				}
			}

			foreach( ptype and value in wp.property ) {
				if ( ptype == "paththrough" ) {
					keep = true;
				}
			}

			if (!keep) {
				Wp.DeleteWaypoint(wp.guid);
			}
		}
	},

	Help =
	{
		"delete all waypoints that do not have properties / flags",
	},
};

///////////////////////////////////////////////////////////////////////////////
// print and draw goals range
Commands["draw_goalrange"] = function(_params)
{
	foreach(mg in Util.GoalTable())
	{
		range = mg.GetRange();
		if (range > 0) {
			print(mg.GetName(), range);
			if(mg.GoalType!="AMMOCAB" && mg.GoalType!="HEALTHCAB") {
				DrawRadius(mg.GetPosition(), range, COLOR.CYAN, 20);
			}
		}
	}
};
