Game Development Community

dev|Pro Game Development Curriculum

AI Marker Editor

by Twisted Jenius · 01/18/2009 (9:16 pm) · 18 comments

AI Marker Editor

This is an add-on to the Improved AI Guard Unit resource to help simplify creating, editing and managing of your spawn markers through use of a GUI based editor.

Tired of having to remember the correct values for all 7 dynamic variables? Having problems managing dozens of spawn markers? Well here's your solution. This GUI based spawn marker editor can help with all of that and much more. Create, edit and manage all of your spawn points with just a few clicks.

This editor is specifically designed to be as compatible with the Improved AI Guard Unit resource as possible. For example, if you change the default settings located at the top of aiplayer.cs, the defaults will also change in the editor and on all of your spawn points that are currently set to the default value. This also allows the minimum amount of needed data to be saved to your .mis file, without compromising any features.

This resource automatically detects your current valid spawn markers, AI path markers, player body datablocks and weapon datablocks. So there's no need to go hunting around for, or even to remember the names of, those things. All you have to do is select what you want from the drop down lists, apply, save your mission once you're done applying all of your changes and then reload your mission to see the results.



INSTALLATION

In creator/main.cs add the following to the bottom of the executes list:

exec("./editor/AIMarkerEditor.cs");
      exec("./editor/AIMarkerEditor.gui");

Add the following line to the bottom of your client/scripts/default.bind.cs file:

GlobalActionMap.bind(keyboard, "alt a", toggleAIMarkerEditor);

Then put the two files, whose code is below, in the correct folder:
creator/editor/AIMarkerEditor.cs
creator/editor/AIMarkerEditor.gui

And you're done. Press alt + a to open the AI Marker Editor. Usage should be fairly self explanatory.



KNOWN ISSUES

-If you use object names that are unusual, non-unique or blank; this can cause minor errors.
-If you use a complex structure the simgroups (with multiple simgroups inside of another simgroup) and you have AI markers or paths deep within that structure, sometime the markers and paths won't be added to the lists they should be on.



CHANGE LOG
* March 4, 2009: Changed the install instructions to fix a minor bug.



If you enjoy using this resource, you should consider purchasing The Universal AI Starter Kit. It has been updated with many new features, bugs fixes and performance enhancements, along with better documentation, an easier installation process, and the code has been more modular and customizable. Check The UAISK's product page or my blogs for more information.



AIMarkerEditor.cs

// ============================================================
// AIMarkerEditor.cs
// ============================================================

function toggleAIMarkerEditor(%val)
{
   if (!%val)
      return;

   if ($AIMarkerEditor::isOpen)
   {
      Canvas.popDialog(AIMarkerEditor);
      $AIMarkerEditor::isOpen = false;
	  return;
   }
   else if (!$AIMarkerEditor::recentlyOpen)
   {
		AIMarkerEditor.initEditor();

 		Canvas.pushDialog(AIMarkerEditor);
 		$AIMarkerEditor::isOpen = true;
		$AIMarkerEditor::recentlyOpen = true; //to check whether we load the most recently editted object
   }
   else //recentlyOpen = true
   {
		Canvas.pushDialog(AIMarkerEditor);
		$AIMarkerEditor::isOpen = true;
   }

   $currentSetting1 = "Create a New Marker";

   AIMarkerEditor.updateControls();
}

function AIMarkerEditor::initEditor(%this)
{
	echo("Initializing AI Marker Editor");

   // From here until the end of the next for loop is to cycle through all the
   // datablocks and add player and item data to the appropriate lists.
   %count = DatablockGroup.getCount();
   %playerBlockCount = 0;
   %itemBlockCount = 0;

   AIME_CharacterSelector.clear();
   AIME_WeaponSelector.clear();

   for (%i = 0; %i < %count; %i++)
   {
      %obj = DatablockGroup.getObject(%i);
      if (%obj.getClassName() $= "PlayerData")
      {
         AIME_CharacterSelector.add(%obj.getName(), %playerBlockCount);

         // Check if this datablock should be the default, set it as the default if it is
         if (%obj.getName() $= $AI_GUARD_CHAR_TYPE)
             %playerDefaultNum = %playerBlockCount;

         %playerBlockCount++;
      }
      if (%obj.getClassName() $= "ItemData")
      {
         AIME_WeaponSelector.add(%obj.getName(), %itemBlockCount);

         // Check if this datablock should be the default, set it as the default if it is
         if (%obj.getName() $= $AI_GUARD_WEAPON)
             %itemDefaultNum = %itemBlockCount;

         %itemBlockCount++;
      }
   }

   // From here until the end of the next for loop is to cycle through all the
   // mission objects and add ai markers and paths to the appropriate lists.
   %countB = MissionGroup.getCount();
   $aiMarkerCount = 0;
   $pathMarkerCount = 0;
   $simCounting = 0;

   AIME_MarkerSelector.clear();
   AIME_PathSelector.clear();
   AIME_SimGroupSelector.clear();

    for (%i = 0; %i < %countB; %i++)
    {
     %obj = MissionGroup.getObject(%i);

      if (%obj.getFieldValue(Datablock) $= "AIPlayerMarker")
      {
         AIME_MarkerSelector.add(%obj.getName(), $aiMarkerCount);
         $aiMarkerCount++;
      }
      if (%obj.getClassName() $= "Path")
      {
         AIME_PathSelector.add(%obj.getName(), $pathMarkerCount);
         $pathMarkerCount++;
      }
      if (%obj.getClassName() $= "SimGroup")
      {
         AIME_SimGroupSelector.add(%obj.getName(), $simCounting);
         $simNameVar = %obj.getName();
         $simCounting++;
         AIMarkerEditor.cycleSimGroups();
      }
    }

   echo("AI Marker Editor counts: " @ %playerBlockCount @ " players, " @ %itemBlockCount @ " items, " @ $aiMarkerCount @
   " markers, and " @ $pathMarkerCount @ " paths within " @ $simCounting @ " simgroups.");

   //add the default, non-dynamic options to already created lists
   AIME_PathSelector.add("-NOT PATHED", $pathMarkerCount++);
   AIME_SimGroupSelector.add("MissionGroup", $simCounting++);

   //create some new non-dynamic lists
   AIME_RangeSelector.clear();
   AIME_RangeSelector.add("Not Ranged", 0);
   AIME_RangeSelector.add("Ranged", 1);

   AIME_BehaviorSelector.clear();
   AIME_BehaviorSelector.add("Chase", 0);
   AIME_BehaviorSelector.add("Guard", 1);

   AIME_RespawnSelector.clear();
   AIME_RespawnSelector.add("Respawn", 0);
   AIME_RespawnSelector.add("Do Not Respawn", 1);

   AIME_ModeSelector.clear();
   AIME_ModeSelector.add("Create a New Marker", 0);
   AIME_ModeSelector.add("Edit the Current Marker", 1);

   //sort alphabetically
   AIME_CharacterSelector.sort();
   AIME_WeaponSelector.sort();
   AIME_MarkerSelector.sort();
   AIME_PathSelector.sort();
   AIME_SimGroupSelector.sort();

   //select default options
   AIME_CharacterSelector.setSelected(%playerDefaultNum);
   AIME_WeaponSelector.setSelected(%itemDefaultNum);
   AIME_MarkerSelector.setSelected(0);
   AIME_PathSelector.setSelected($pathMarkerCount);
   AIME_SimGroupSelector.setSelected($simCounting);
   AIME_RangeSelector.setSelected(0);
   AIME_BehaviorSelector.setSelected(0);

   txtLifetimeVarianceMS.text = "NULL";
   txtLifetimeVarianceMS2.text = "NULL";
   txtLifetimeVarianceMS3.text = "1 0 0 0";
   txtLifetimeVarianceMS4.text = "0 0 0";

   if ($AI_GUARD_DEFAULTRESPAWN)
   {
      AIME_RespawnSelector.setSelected(0);
      $respawnDefaultSet = "Respawn";
   }
   else
   {
      AIME_RespawnSelector.setSelected(1);
      $respawnDefaultSet = "Do Not Respawn";
   }

   if ($currentSetting1 $= "Create a New Marker")
      AIME_ModeSelector.setSelected(0);
   else
      AIME_ModeSelector.setSelected(1);
}

// This function cycles through simgroups that are inside of the MissionGroup or another simgroup
function AIMarkerEditor::cycleSimGroups()
{
   %simNameVar2 = "";
   %simCountingB = $simNameVar.getCount();

    for (%i = 0; %i < %simCountingB; %i++)
    {
     %obj = $simNameVar.getObject(%i);

      if (%obj.getFieldValue(Datablock) $= "AIPlayerMarker")
      {
         AIME_MarkerSelector.add(%obj.getName(), $aiMarkerCount);
         $aiMarkerCount++;
      }
      if (%obj.getClassName() $= "Path")
      {
         AIME_PathSelector.add(%obj.getName(), $pathMarkerCount);
         $pathMarkerCount++;
      }
      if (%obj.getClassName() $= "SimGroup")
      {
         AIME_SimGroupSelector.add(%obj.getName(), $simCounting);
         %simNameVar2 = %obj.getName();
         $simCounting++;
      }
    }

   if (%simNameVar2 !$= "")
   {
      $simNameVar = %simNameVar2;
      AIMarkerEditor.cycleSimGroups();
   }
}

//this function updates all controls in the editor to be equal to the selected element
function AIMarkerEditor::updateControls(%this)
{
	%data = AIME_MarkerSelector.getText();
	%data2 = %data.getGroup();

	echo("Selected Marker:" SPC %data);

	// all the following if/else check if a data field has a value, and if not set it to the default
	if (%data.block !$= "")
		AIME_CharacterSelector.setText(getField(%data.block, 0));
	else
		AIME_CharacterSelector.setText($AI_GUARD_CHAR_TYPE);

	if (%data.Weapon !$= "")
		AIME_WeaponSelector.setText(getField(%data.Weapon, 0));
	else
		AIME_WeaponSelector.setText($AI_GUARD_WEAPON);

	if (%data.pathname !$= "")
		AIME_PathSelector.setText(getField(%data.pathname, 0));
	else
		AIME_PathSelector.setText("-NOT PATHED");

	if (%data2.getName() !$= "")
		AIME_SimGroupSelector.setText(getField(%data2.getName(), 0));
	else
		AIME_SimGroupSelector.setText("MissionGroup");

	if (%data.range !$= "")
		AIME_RangeSelector.setText(getField(%data.range, 0));
	else
		AIME_RangeSelector.setText("Not Ranged");

	if (%data.doesReturn !$= "")
		AIME_BehaviorSelector.setText(getField(%data.doesReturn, 0));
	else
		AIME_BehaviorSelector.setText("Chase");

	if (%data.respawn !$= "")
	{
		if(%data.respawn $= "true" || %data.respawn $= "True")
      		AIME_RespawnSelector.setText("Respawn");
   		else
      		AIME_RespawnSelector.setText("Do Not Respawn");
	}
	else
	{
   		if ($respawnDefaultSet $= "Respawn")
      		AIME_RespawnSelector.setText("Respawn");
   		else
      		AIME_RespawnSelector.setText("Do Not Respawn");
	}

	if (%data.spawnGroup !$= "")
		txtLifetimeVarianceMS.text = %data.getFieldValue(spawnGroup);
	else
		txtLifetimeVarianceMS.text = "NULL";

	if (%data.getName() !$= "")
		txtLifetimeVarianceMS2.text = %data.getName();
	else
		txtLifetimeVarianceMS2.text = "NULL";

	if (%data.rotation !$= "")
		txtLifetimeVarianceMS3.text = %data.getFieldValue(rotation);
	else
		txtLifetimeVarianceMS3.text = "1 0 0 0";

	if (%data.position !$= "")
		txtLifetimeVarianceMS4.text = %data.getFieldValue(position);
	else
		txtLifetimeVarianceMS4.text = "0 0 0";

	if (AIME_ModeSelector.getText() !$= $currentSetting1)
		AIME_ModeSelector.setText($currentSetting1);
}

function AIMarkerEditor::saveEffect(%this)
{
	%i = 0;

	if (AIME_ModeSelector.getText() $= "Edit the Current Marker")
	{
        %data = AIME_MarkerSelector.getText();
        %data.delete();

        //if the markers name has been changed, set a flag so we can refresh the marker list
        if (AIME_MarkerSelector.getText() !$= txtLifetimeVarianceMS2.getText())
        	%i = 1;
	}
	else
        AIME_MarkerSelector.setText("");

	// If something is the default value, set it blank so it's not added to the marker
	if (AIME_PathSelector.getText() $= "-NOT PATHED")
		AIME_PathSelector.setText("");

	if (AIME_CharacterSelector.getText() $= $AI_GUARD_CHAR_TYPE)
		AIME_CharacterSelector.setText("");

	if (AIME_WeaponSelector.getText() $= $AI_GUARD_WEAPON)
		AIME_WeaponSelector.setText("");

	if (AIME_RangeSelector.getText() $= "Not Ranged")
		AIME_RangeSelector.setText("");

	if (AIME_BehaviorSelector.getText() $= "Chase")
		AIME_BehaviorSelector.setText("");

	if (txtLifetimeVarianceMS.getText() $= "NULL" || txtLifetimeVarianceMS.getText() $= "Null" || txtLifetimeVarianceMS.getText() $= "null")
		txtLifetimeVarianceMS.setText("");

	if (txtLifetimeVarianceMS2.getText() $= "NULL" || txtLifetimeVarianceMS2.getText() $= "Null" || txtLifetimeVarianceMS2.getText() $= "null")
		txtLifetimeVarianceMS2.setText("");

	if (AIME_RespawnSelector.getText() $= $respawnDefaultSet)
		AIME_RespawnSelector.setText("");

	//change the value of respawn to true or false
	if (AIME_RespawnSelector.getText() $= "Respawn")
		AIME_RespawnSelector.setText("true");
	else if (AIME_RespawnSelector.getText() $= "Do Not Respawn")
		AIME_RespawnSelector.setText("false");
	else
		AIME_RespawnSelector.setText("");

    // setup the objects data
    %marker = new StaticShape(txtLifetimeVarianceMS2.getText()) {
        canSaveDynamicFields = "1";
        position = txtLifetimeVarianceMS4.getText();
        rotation = txtLifetimeVarianceMS3.getText();
        scale = "1 1 1";
        dataBlock = "AIPlayerMarker";
        receiveSunLight = "1";
        receiveLMLighting = "1";
        useAdaptiveSelfIllumination = "0";
        useCustomAmbientLighting = "0";
        customAmbientSelfIllumination = "0";
        customAmbientLighting = "0 0 0 1";
        useLightingOcclusion = "1";
            block = AIME_CharacterSelector.getText();
            Weapon = AIME_WeaponSelector.getText();
            range = AIME_RangeSelector.getText();
            pathname = AIME_PathSelector.getText();
            respawn = AIME_RespawnSelector.getText();
            doesReturn = AIME_BehaviorSelector.getText();
            spawnGroup = txtLifetimeVarianceMS.getText();
    };

	//save it in the correct simgroup
	%simGroupSet = AIME_SimGroupSelector.getText();
	%simGroupSet.add(%marker);

	//change the value of respawn back now that it's saved
	if (AIME_RespawnSelector.getText() $= "true")
		AIME_RespawnSelector.setText("Respawn");
	else if (AIME_RespawnSelector.getText() $= "false")
		AIME_RespawnSelector.setText("Do Not Respawn");
	else
		AIME_RespawnSelector.setText("");

	//refresh the marker list if needed
	if (%i = 1)
		AIMarkerEditor.initEditor();

	AIMarkerEditor.updateControls();
}

//save what mode should be the default
function AIMarkerEditor::saveCurrentSettings(%this)
{
   $currentSetting1 = AIME_ModeSelector.getText();
}






AIMarkerEditor.gui

//--- OBJECT WRITE BEGIN ---
new GuiControl(AIMarkerEditor) {
   canSaveDynamicFields = "0";
   Profile = "GuiDefaultProfile";
   HorizSizing = "right";
   VertSizing = "bottom";
   position = "0 0";
   Extent = "640 480";
   MinExtent = "8 2";
   canSave = "1";
   Visible = "1";
   hovertime = "1000";

   new GuiWindowCtrl() {
      canSaveDynamicFields = "0";
      Profile = "GuiWindowProfile";
      HorizSizing = "right";
      VertSizing = "bottom";
      position = "0 0";
      Extent = "332 480";
      MinExtent = "8 2";
      canSave = "1";
      Visible = "1";
      hovertime = "1000";
      text = "AI Marker Editor";
      maxLength = "255";
      resizeWidth = "0";
      resizeHeight = "0";
      canMove = "1";
      canClose = "1";
      canMinimize = "1";
      canMaximize = "0";
      minSize = "50 50";
      closeCommand = "toggleAIMarkerEditor(1);";

      new GuiPopUpMenuCtrl(AIME_WeaponSelector) {
         canSaveDynamicFields = "0";
         Profile = "GuiPopUpMenuProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "15 265";
         Extent = "150 25";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Crossbow";
         maxLength = "255";
         maxPopupHeight = "200";
      };
      new GuiPopUpMenuCtrl(AIME_PathSelector) {
         canSaveDynamicFields = "0";
         Profile = "GuiPopUpMenuProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "15 310";
         Extent = "150 25";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "-NOT PATHED";
         maxLength = "255";
         maxPopupHeight = "200";
      };
      new GuiPopUpMenuCtrl(AIME_CharacterSelector) {
         canSaveDynamicFields = "0";
         Profile = "GuiPopUpMenuProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "15 220";
         Extent = "150 25";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "PlayerBody";
         maxLength = "255";
         maxPopupHeight = "200";
      };
      new GuiPopUpMenuCtrl(AIME_MarkerSelector) {
         canSaveDynamicFields = "0";
         Profile = "GuiPopUpMenuProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "15 126";
         Extent = "150 25";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         Command = "AIMarkerEditor.updateControls();";
         hovertime = "1000";
         text = "NULL";
         maxLength = "255";
         maxPopupHeight = "200";
      };
      new GuiPopUpMenuCtrl(AIME_SimGroupSelector) {
         canSaveDynamicFields = "0";
         Profile = "GuiPopUpMenuProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "175 220";
         Extent = "150 25";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "MissionGroup";
         maxLength = "255";
         maxPopupHeight = "200";
      };
      new GuiPopUpMenuCtrl(AIME_RangeSelector) {
         canSaveDynamicFields = "0";
         Profile = "GuiPopUpMenuProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "175 265";
         Extent = "150 25";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Not Ranged";
         maxLength = "255";
         maxPopupHeight = "200";
      };
      new GuiPopUpMenuCtrl(AIME_RespawnSelector) {
         canSaveDynamicFields = "0";
         Profile = "GuiPopUpMenuProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "15 362";
         Extent = "150 25";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Respawn";
         maxLength = "255";
         maxPopupHeight = "200";
      };
      new GuiPopUpMenuCtrl(AIME_BehaviorSelector) {
         canSaveDynamicFields = "0";
         Profile = "GuiPopUpMenuProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "176 311";
         Extent = "150 25";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Chase";
         maxLength = "255";
         maxPopupHeight = "200";
      };
      new GuiPopUpMenuCtrl(AIME_ModeSelector) {
         canSaveDynamicFields = "0";
         Profile = "GuiPopUpMenuProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "15 62";
         Extent = "150 25";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Create a New Marker";
         maxLength = "255";
         maxPopupHeight = "200";
      };
      new GuiTextEditCtrl(txtLifetimeVarianceMS) {
         canSaveDynamicFields = "0";
         Profile = "GuiTextEditProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "209 367";
         Extent = "64 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "NULL";
         maxLength = "1024";
         historySize = "0";
         password = "0";
         tabComplete = "0";
         sinkAllKeyEvents = "0";
         password = "0";
         passwordMask = "*";
      };
      new GuiTextEditCtrl(txtLifetimeVarianceMS2) {
         canSaveDynamicFields = "0";
         Profile = "GuiTextEditProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "174 126";
         Extent = "133 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "NULL";
         maxLength = "1024";
         historySize = "0";
         password = "0";
         tabComplete = "0";
         sinkAllKeyEvents = "0";
         password = "0";
         passwordMask = "*";
      };
      new GuiTextEditCtrl(txtLifetimeVarianceMS3) {
         canSaveDynamicFields = "0";
         Profile = "GuiTextEditProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "175 174";
         Extent = "133 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "1 0 0 0";
         maxLength = "1024";
         historySize = "0";
         password = "0";
         tabComplete = "0";
         sinkAllKeyEvents = "0";
         password = "0";
         passwordMask = "*";
      };
      new GuiTextEditCtrl(txtLifetimeVarianceMS4) {
         canSaveDynamicFields = "0";
         Profile = "GuiTextEditProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "16 173";
         Extent = "133 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "0 0 0";
         maxLength = "1024";
         historySize = "0";
         password = "0";
         tabComplete = "0";
         sinkAllKeyEvents = "0";
         password = "0";
         passwordMask = "*";
      };
      new GuiButtonCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiButtonProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "126 439";
         Extent = "75 30";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         Command = "AIMarkerEditor.saveEffect();";
         hovertime = "1000";
         text = "Apply";
         groupNum = "-1";
         buttonType = "PushButton";
      };
      new GuiButtonCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiButtonProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "205 62";
         Extent = "75 30";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         Command = "AIMarkerEditor.saveCurrentSettings();";
         hovertime = "1000";
         text = "Save";
         groupNum = "-1";
         buttonType = "PushButton";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "206 347";
         Extent = "68 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Spawn Group";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "20 290";
         Extent = "21 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Path";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "20 245";
         Extent = "40 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Weapon";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "20 95";
         Extent = "153 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Select a marker to edit or to use";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "20 108";
         Extent = "138 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "as a base for a new marker.";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "20 200";
         Extent = "75 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Character Type";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "180 200";
         Extent = "47 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "SimGroup";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "75 408";
         Extent = "179 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "You need to save your mission using";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "48 421";
         Extent = "233 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "the mission editor after appling all changes here.";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "180 245";
         Extent = "31 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Range";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "20 342";
         Extent = "47 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Respawn";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "181 291";
         Extent = "43 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Behavior";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "16 32";
         Extent = "99 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Select a Mode: What";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "210 105";
         Extent = "61 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Object Name";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "16 44";
         Extent = "102 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "would you like to do?";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "185 33";
         Extent = "116 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Temporarily save which";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "176 44";
         Extent = "133 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "mode is currently selected?";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "64 155";
         Extent = "37 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Position";
         maxLength = "255";
      };
      new GuiTextCtrl() {
         canSaveDynamicFields = "0";
         Profile = "GuiTextProfile";
         HorizSizing = "right";
         VertSizing = "bottom";
         position = "221 156";
         Extent = "39 18";
         MinExtent = "8 2";
         canSave = "1";
         Visible = "1";
         hovertime = "1000";
         text = "Rotation";
         maxLength = "255";
      };
   };
};
//--- OBJECT WRITE END ---

About the author

Developer of The Universal AI Starter Kit and Twisty's Asylum Escapades.


#1
01/18/2009 (9:18 pm)
Due to a bug in the recent garagegames.com site updates, this was automatically made into a blog instead of a resource like I submitted it as. Also I just missed out on the ability to upload files to garagegames.com for hosting, which was permanently disabled as part of the update.
#2
01/19/2009 (7:49 am)
looks interesting, i have it in but do not have hte time to test it right now. will test it later today.

Thanks for the resource mate. looks good so far.
#3
01/20/2009 (1:24 am)
you do know of course, that the AI Guard and this resource work a treat in TGEA. I have them both working wonderfully with 1.7.1 thanks.
#4
01/25/2009 (4:23 pm)
@Twisted

With this added in, with the improved Ai Guard (which I mightr add, is GREAT!) can you set up Ai to just stand still, but rotate so they are looking at you?
-> am planing on using this with the Yack Pack!

From Max
#5
01/25/2009 (4:42 pm)
@Max
Unfortunately, no. That's not one of the things that can be changed with this resource, so for now you'll have to keep using the "Friendly AI Marker" resource that you wrote.

At some point I do plan to add even more features to my "Improved AI Guard Unit" resource, but currently I can't say what features I will add or when I will be updating it (so don't count on anything with that).

But, having said that, adding in an option for non-aggressive NPCs that can talk to you, is a possibility in the future (it's one of the many things on my huge AI to do list). Although I'm not using the Yack Pack, so it likely wouldn't work with that pack without at least a little modifying.
#6
01/25/2009 (7:06 pm)
@ Twisted

Well, can you just make them not run at you? Because if so, I can just make sure they aren't holding a crossbow, and there you have it, a non-agressive AI

From Max

Ps. what are the different Behaiviour options?
#7
01/26/2009 (11:09 am)
The "behavior" option here corresponds to the "doesReturn" dynamic variable in the Improved AI Guard Unit resource (check that resource for details).



I haven't tested this much so it may have bugs (and if it does have bugs, I don't have time to fix them right now).

In aiPlayer.cs, function AIPlayer::spawn()

Add the last two lines here under the first two which are already there:
//The bots starting attention level is set to half of it's range.
   attentionlevel = $AI_GUARD_MAX_ATTENTION/2;
   //sets wheither or not the bot should attack players
   passiveNPC = %obj.passive;

Then change:
//Sets the bot to begin thinking after waiting the length of $AI_GUARD_CREATION_DELAY
   		%player.schedule($AI_GUARD_CREATION_DELAY,"Think", %player);

To:
if (%obj.passive $= "")
   {
   		//Sets the bot to begin thinking after waiting the length of $AI_GUARD_CREATION_DELAY
   		%player.schedule($AI_GUARD_CREATION_DELAY,"Think", %player);
   }

And add the following variable to the marker (this will not work at all, in any way with this editor):
passive = "something";
#8
02/09/2009 (10:15 pm)
Hey Twisted,

I have been trying to get an aiWheeledVechile going (using TGE 1.5.2) with no luck, so i was wondering, can you incoperate the buggy into this marker system?

from max
#9
03/06/2009 (1:22 pm)
I don't have creator/main.cs in TGEA... where do I have to apply changes? Thanks and sorry for the noob question =].
#10
03/06/2009 (2:03 pm)
Try: tools/missionEditor/main.cs

And change the paths to:
exec("./gui/AIMarkerEditor.gui");
exec("./scripts/AIMarkerEditor.cs");

And then put them in the correct folders.

Hope that works. I'm currently using TGE 1.5.2, so this is just based on the TGEA demo.
#11
03/10/2009 (1:30 pm)
For TGEA:

After the line:
useLightingOcclusion = "1";

Add:
Enabled = "1";
#12
09/23/2009 (1:27 am)
I am no longer supporting this resource at all. For future updates please purchase The Universal AI Starter Kit. The UAISK contains a vastly improved version of this editor, in addition to many other things.
#13
01/02/2012 (9:12 pm)
If I buy the UAISK will I be able to avoid trying to implement the above resource? Will it install and function with T3D 1.2? Thanks. I'm finally ready to add a bad guy to shoot at that shoots back(-:

Thanks

Robert
#14
01/02/2012 (9:19 pm)
Yes. The UAISK contains drag and drop files that are already setup to work in T3D 1.2. Having enemies that actually shoot back makes a world of difference.
#15
01/03/2012 (4:38 am)
Thanks so much. I plan to order it this week.

Robert
#16
01/03/2012 (5:33 pm)
I just bought the UAISK but wont be able to get the AFX2.O until a few weeks. Which Download should I down load. The top two saw AFX2.0 + UAISK Interop. Will those work even though I don't have Arcane Effects yet?

This probably a stupid question but I'm kinda new(-:

Thanks

Robert
#17
01/03/2012 (6:04 pm)
The current newest non-AFX version is labeled as "Universal AI Starter Kit 1.9.0".

EDIT: Also you can post any further questions in The UAISK's private forum.
#18
01/03/2012 (6:08 pm)
Thanks a lot. I will. At least in a few weeks when I get Arcane Effects I will already know which one to DL. LOL. Have a good night.

Robert