//-----------------------------------------------------------------------------
// Torque Game Engine 
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// PlayGui is the main TSControl through which the game is viewed.
// The PlayGui also contains the hud controls.
//-----------------------------------------------------------------------------

$PlayerHighlightImage = "assets/client/ui/hud/playerhighlight.jpg";
$NeutralHighlightImage = "assets/client/ui/hud/neutralhighlight.jpg";
$EnemyHighlightImage = "assets/client/ui/hud/bandithighlight.jpg";

//-Globals---------------------------------------------------------------------
// global selection access
new SLSelection(gSelection)
{
};

// Used for locator buttons
$HeroLocator        = 0;
$CombatLocator      = 1;
$JoblessLocator     = 2;
$CivilianLocator    = 3;
$BuildingLocator    = 4;
$TotalLocators      = 5;

$HeroLocatorIdx     = 0;
$CombatLocatorIdx   = 0;
$JoblessLocatorIdx  = 0;
$CivilianLocatorIdx = 0;
$BuildingLocatorIdx = 0;

// Locator buttons
$LocatorBtn[$HeroLocator]     = LocateHeroButton;
$LocatorBtn[$CombatLocator]   = LocateCombatUnitButton;
$LocatorBtn[$JoblessLocator]  = LocateJoblessUnitButton;
$LocatorBtn[$CivilianLocator] = LocateCivilianButton;
$LocatorBtn[$BuildingLocator] = LocateBuildingButton;

// Used to stop window scrolling
$Input::WindowScroll = true;
//-----------------------------------------------------------------------------

function PlayGui::onStart(%this)
{
   // sets up selection and highlighting groups in the scene
   unloadSelectionGroups();
   loadSelectionGroups();
}

function PlayGui::onWake(%this)
{
  // Turn off any shell sounds...
  // alxStop( ... );
  
  $enableDirectInput = "1";
  activateDirectInput();
  
  // Message hud dialog
  //FL// Canvas.pushDialog( MainChatHud );
  //chatHud.attach(HudMessageVector);
  
  // just update the action map here
  moveMap.push();
    
  // hack city - these controls are floating around and need to be clamped
  schedule(0, 0, "refreshCenterTextCtrl");
  schedule(0, 0, "cursorOn");
}

function PlayGui::onSleep(%this)
{
   //FL//Canvas.popDialog( MainChatHud  );
   
   // pop the keymaps
   moveMap.pop();
}

function zoomOut()
{
   if ($serverCamera)
   {
     %component = $serverCamera.getCameraCmp();
     if (%component)
     {
        %position = %component.getZoomPos();
        if ($ZoomLevelEnabled == true || %position < $ZoomLevelPos)
        {
           %component.zoomOut();
        }
     }
   }
}

function zoomIn()
{
   if ($serverCamera)
   {
     %component = $serverCamera.getCameraCmp();
     if (%component)
     {
        %component.zoomIn();
     }
   }
}

function PlayGui::onMouseWheelDown(%this)
{
   zoomOut();
}

function PlayGui::onMouseWheelUp(%this)
{
   zoomIn();
}

function PlayGui::onSleep(%this)
{
   $mvForwardAction = 0;
   $mvBackwardAction = 0;
   $mvLeftAction = 0;
   $mvRightAction = 0;
}

$dragMouseOffset = 1;
$mouseLastXPos = 0;
$mouseLastYPos = 0;
$updateMousePos = true;

function handleHighlight(%mouseX, %mouseY)
{
   if (PlayGui.hasObject() == true)
   {
      %object = PlayGui.getObject();

      gSelection.removeAllFromGroup($HIGHLIGHT_ID);

      %component = slgQueryInterface(%object, $CID_TARGETBUILDING);
      if (isObject(%component) == true)
      {
         %datablock = %component.getDataBlock();
         if (%datablock.targetRadius != 0)
         {
            gSelection.updateGroupFromTargetObjects($TARGET_HIGHLIGHT,
               %object, %datablock.targetRadius);
         }
         
         %addedList = gSelection.getAddedGroup($TARGET_HIGHLIGHT);
         for (%index = 0; %index < %addedList.getSize(); %index++)
         {
            %highlight = %addedList.getID(%index);
            %datablock = %highlight.getDataBlock();
            if (%datablock.highlight)
            {
               %highlight.setHighlight(%datablock.highlight);
            }
            else
            {
               %highlight.setHighlight($DEFAULT_HIGHLIGHT);
            }
         }
      }
   }
   
   if (PlayGui.hasObject() == false)
   {
      gSelection.removeAllFromGroup($TARGET_HIGHLIGHT);
      
      // update the last position of the mouse
      if ($updateMousePos == true)
      {
         $mouseLastXPos = PlayGui.getMouse2DXPos();
         $mouseLastYPos = PlayGui.getMouse2DYPos();
         $mouseLast3DPos = PlayGui.getMouse3DPos();
      }

      %xMouseDiff = $mouseLastXPos - %mouseX;
      %yMouseDiff = $mouseLastYPos - %mouseY;

      // since the cursor has moved, check if the area selection or drag should start
      checkCursorSelectionChange(%xMouseDiff, %yMouseDiff);

      // left mouse button has been clicked
      if (%xMouseDiff >= -$dragMouseOffset && %xMouseDiff <= $dragMouseOffset &&
         %yMouseDiff >= -$dragMouseOffset && %yMouseDiff <= $dragMouseOffset)
      {
         // handle the point collision, then update the selection group
         PlayGui.pointRollover($pointSelectionLength, $TypeMasks::BuildingObjectType +
            $TypeMasks::PropObjectType + $TypeMasks::CharacterObjectType);
         gSelection.updateGroupFromPt($HIGHLIGHT_ID);
         
         %addedList = gSelection.getAddedGroup($HIGHLIGHT_ID);
         if (%addedList.getSize() != 0)
         {
            %link = %addedList.getID(0);
            if (%link.isLinkObj() == true && %link.IsFirstLinkObj() == false)
            {
               // since the highlight group will need to be modified, the
               // remove list should be looked at before the list is modified
               // to remove any objects that were once a part of the highlight
               // that are no longer a part of the highlight
               %removedList = gSelection.getRemovedGroup($HIGHLIGHT_ID);
               for (%index = 0; %index < %removedList.getSize(); %index++)
               {
                  %unhighlight = %removedList.getID(%index);
                  if (isObject(%unhighlight) == true)
                  {
                     %unhighlight.clearHighlight();
                     
                     // remove the health bar from the unhighlighted object
                     DestroyHealthBar(%unhighlight);
                  }
               }
               
               gSelection.removeFromGroup($HIGHLIGHT_ID, %link);
               %temp = %link.getFirstLinkObj();
               if (%temp.getTeam() == $OST_PLAYER)
               {
                  gSelection.addToGroup($HIGHLIGHT_ID, %temp);
               }
            }
            else if (%link.isLinkObj() == true && %link.getTeam() != $OST_PLAYER)
            {
               gSelection.removeFromGroup($HIGHLIGHT_ID, %link);
            }
         }
      }
      // left mouse button has been dragged
      else
      {
         %xPos = getWord($mouseLast3DPos, 0);
         %yPos = getWord($mouseLast3DPos, 1);
         %zPos = getWord($mouseLast3DPos, 2);
         PlayGui.areaRollover(%xPos, %yPos, %zPos,
           $TypeMasks::BuildingObjectType + $TypeMasks::PropObjectType +
           $TypeMasks::CharacterObjectType);
         gSelection.updateGroupFromArea($TEMPSELECT_ID, 1);

         // if more than one building, prop, or character is selected, weed out
         // the props and look for only buildings and characters
         %group = gSelection.getSelectedGroup($TEMPSELECT_ID);
         if (%group.getSize() > 1)
         {
            // cycle through the objects to treat all link objects
            // with the same first object as the same object
            %link = 0;
            for (%index = 0; %index < %group.getSize(); %index++)
            {
               %object = %group.getId(%index);
               if (%object.isLinkObj() == true)
               {
                  %value = %object.getFirstLinkObj();
                  if (%link == 0) %link = %value;
                  else if (%link != %value)
                  {
                     %link = 0;
                     break;
                  }
               }
               else
               {
                  %link = 0;
                  break;
               }
            }
            
            if (%link == 0)
            {
               %xPos = getWord($mouseLast3DPos, 0);
               %yPos = getWord($mouseLast3DPos, 1);
               %zPos = getWord($mouseLast3DPos, 2);
               PlayGui.areaRollover(%xPos, %yPos, %zPos,
                  $TypeMasks::BuildingObjectType + $TypeMasks::CharacterObjectType);
               gSelection.updateGroupFromArea($TEMPSELECT_ID, 1);

               %group = gSelection.getSelectedGroup($TEMPSELECT_ID);
               if (%group.getSize() > 1)
               {
                  // cycle through the objects to treat all link objects
                  // with the same first object as the same object
                  %link = 0;
                  for (%index = 0; %index < %group.getSize(); %index++)
                  {
                     %object = %group.getId(%index);
                     if (%object.isLinkObj() == true)
                     {
                        %value = %object.getFirstLinkObj();
                        if (%link == 0) %link = %value;
                        else if (%link != %value)
                        {
                           %link = 0;
                           break;
                        }
                     }
                     else
                     {
                        %link = 0;
                        break;
                     }
                  }
                  
                  if (%link == 0)
                  {
                     %xPos = getWord($mouseLast3DPos, 0);
                     %yPos = getWord($mouseLast3DPos, 1);
                     %zPos = getWord($mouseLast3DPos, 2);
                     PlayGui.areaRollover(%xPos, %yPos, %zPos,
                        $TypeMasks::CharacterObjectType);
                  }
               }
            }
         }

         gSelection.updateGroupFromArea($HIGHLIGHT_ID, 1);
         %group = gSelection.getSelectedGroup($HIGHLIGHT_ID);
         if (%group.getSize() > 0)
         {
            %link = %group.getId(0);
            if (%link.isLinkObj() == true)
            {
               // since the highlight group will need to be modified, the
               // remove list should be looked at before the list is modified
               // to remove any objects that were once a part of the highlight
               // that are no longer a part of the highlight
               %removedList = gSelection.getRemovedGroup($HIGHLIGHT_ID);
               for (%index = 0; %index < %removedList.getSize(); %index++)
               {
                  %unhighlight = %removedList.getID(%index);
                  if (isObject(%unhighlight) == true)
                  {
                     %unhighlight.clearHighlight();
                     
                     // remove the health bar from the unhighlighted object
                     DestroyHealthBar(%unhighlight);
                  }
               }
               
               %link = %link.getFirstLinkObj();
               gSelection.removeAllFromGroup($HIGHLIGHT_ID);
               if (%link.getTeam() == $OST_PLAYER)
               {
                  gSelection.addToGroup($HIGHLIGHT_ID, %link);
               }
            }
         }
      }

      %addedList = gSelection.getAddedGroup($HIGHLIGHT_ID);
      for (%index = 0; %index < %addedList.getSize(); %index++)
      {
         %highlight = %addedList.getID(%index);
         %datablock = %highlight.getDataBlock();
         if (%datablock.highlight)
         {
            %highlight.setHighlight(%datablock.highlight);
         }
         else
         {
            %highlight.setHighlight($DEFAULT_HIGHLIGHT);
         }
         
         // highlights the arrow icon
         if (%highlight.selectIcon != 0)
         {
           %highlight.selectIcon.setHighlightImage();
         }
         
         // create a health bar for the highlighted object
         CreateHealthBar(%highlight);
         
         %team = %highlight.getTeam();
         if (%team == $OST_PLAYER)
         {
            CursorHighlight.bitmap = $PlayerHighlightImage;
         }
         else if (%team == $OST_NEUTRAL)
         {
            CursorHighlight.bitmap = $NeutralHighlightImage;
         }
         else if (%team > $OST_PLAYER)
         {
            CursorHighlight.bitmap = $EnemyHighlightImage;
         }
         else
         {
            CursorHighlight.visible = false;
         }
      }
   }
   
   %removedList = gSelection.getRemovedGroup($TARGET_HIGHLIGHT);
   for (%index = 0; %index < %removedList.getSize(); %index++)
   {
      %unhighlight = %removedList.getID(%index);
      if (isObject(%unhighlight) == true)
      {
         %unhighlight.clearHighlight();
         
         // unhighlights the arrow icon
         if (%unhighlight.selectIcon != 0)
         {
           %unhighlight.selectIcon.setUnhighlightImage();
         }
      }
   }

   %removedList = gSelection.getRemovedGroup($HIGHLIGHT_ID);
   for (%index = 0; %index < %removedList.getSize(); %index++)
   {
      %unhighlight = %removedList.getID(%index);
      if (isObject(%unhighlight) == true)
      {
         if (%unhighlight.selectIcon == 0 ||
            %unhighlight.selectIcon.hasHighlight() == false)
         {         
            // unhighlights the arrow icon
            if (%unhighlight.selectIcon != 0)
            {
              %unhighlight.selectIcon.setUnhighlightImage();
            }
            
            %unhighlight.clearHighlight();
            
            // remove the health bar from the unhighlighted object
            DestroyHealthBar(%unhighlight);
         }
         else
         {
            gSelection.addToGroup($HIGHLIGHT_ID, %unhighlight);
         }
      }
   }
   
   updateHighlight($HIGHLIGHT_ID);
   
   /*
   // check the drag state and update the cursor
   if ($canDragCommand == false)
   {
      %selected = gSelection.getSelectedGroup($SELECT_ID);
      %highlight = gSelection.getSelectedGroup($HIGHLIGHT_ID);
      
      %target = 0;
      // get the target object
      if (%highlight.getSize() > 0)
      {
         %target = %highlight.getID(0);
      }
      // get the target position
      else
      {
         %target = Terrain.getId();
      }
      
      %command = CmdInterpreter.interpretCommand(%target, %selected);
      csUpdateCursor(%command);
   }
   */
}

function SetHighlightOnObject(%object)
{
   %highlightList = gSelection.getSelectedGroup($HIGHLIGHT_ID);
   if (%highlightList.contains(%object) == false)
   {
      gSelection.addToGroup($HIGHLIGHT_ID, %object);
   }
   
   %datablock = %object.getDataBlock();
   if (%datablock.highlight)
   {
      %object.setHighlight(%datablock.highlight);
   }
   else
   {
      %object.setHighlight($DEFAULT_HIGHLIGHT);
   }
   
   %team = %object.getTeam();
   if (%team == $OST_PLAYER)
   {
      CursorHighlight.bitmap = $PlayerHighlightImage;
   }
   else if (%team == $OST_NEUTRAL)
   {
      CursorHighlight.bitmap = $NeutralHighlightImage;
   }
   else if (%team > $OST_PLAYER)
   {
      CursorHighlight.bitmap = $EnemyHighlightImage;
   }
   else
   {
      CursorHighlight.visible = false;
   }
   
   // create the health bar from the highlighted object
   CreateHealthBar(%object);
}

function SetUnhighlightOnObject(%object)
{
   %highlightList = gSelection.getSelectedGroup($HIGHLIGHT_ID);
   if (%highlightList.contains(%object) == true)
   {
      gSelection.removeFromGroup($HIGHLIGHT_ID, %object);
   }

   %object.clearHighlight();
   
   // remove the health bar from the unhighlighted object
   DestroyHealthBar(%object);
}

// this function is intended to only be called from handleHighlight
// (it will make sure that any prop that is to be highlighted is only
function updateHighlight(%id)
{
   %selectedList = gSelection.getSelectedGroup(%id);
   
   if (CmdStateTracker.isInState($CSS_SELECT) == true)
   {
      for (%index = 0; %index < %selectedList.getSize(); %index++)
      {
         %object = %selectedList.getID(%index);
         if (slgIsProp(%object) == true)
         {
            %component = slgQueryInterface(%object, $CID_PROP);
            if (%component.isJobProp() == false &&
               %component.isPickUpProp() == false)
            {
               %object.clearHighlight();
               gSelection.removeFromGroup(%id, %object);
               return;
            }
         }
      }
   }
   else
   {
      for (%index = 0; %index < %selectedList.getSize(); %index++)
      {
         %object = %selectedList.getID(%index);
         if (slgIsProp(%object) == true)
         {
            %object.clearHighlight();
            gSelection.removeFromGroup(%id, %object);
            return;
         }
      }
   }
}

$MoveForwardShortcut1 = 0;
$MoveBackwardShortcut1 = 0;
$MoveLeftShortcut1 = 0;
$MoveRightShortcut1 = 0;
$MoveForwardShortcut2 = 0;
$MoveBackwardShortcut2 = 0;
$MoveLeftShortcut2 = 0;
$MoveRightShortcut2 = 0;
$MoveForwardMouse = 0;
$MoveBackwardMouse = 0;
$MoveLeftMouse = 0;
$MoveRightMouse = 0;

// when a shortcut key is used to move the camera forward
function shortcutCameraForward1(%input)
{
   if (%input == true) $MoveForwardShortcut1 = $movementSpeed / 5;
   else $MoveForwardShortcut1 = 0;
   
   // update the camera movement
   updateShortcutCamera();
}

// when a shortcut key is used to move the camera backward
function shortcutCameraBackward1(%input)
{
   if (%input == true) $MoveBackwardShortcut1 = $movementSpeed / 5;
   else $MoveBackwardShortcut1 = 0;
   
   // update the camera movement
   updateShortcutCamera();
}

// when a shortcut key is used to move the camera left
function shortcutCameraLeft1(%input)
{
   if (%input == true) $MoveLeftShortcut1 = $movementSpeed / 5;
   else $MoveLeftShortcut1 = 0;
   
   // update the camera movement
   updateShortcutCamera();
}

// when a short key is used to move the camera right
function shortcutCameraRight1(%input)
{
   if (%input == true) $MoveRightShortcut1 = $movementSpeed / 5;
   else $MoveRightShortcut1 = 0;
   
   // update the camera movement
   updateShortcutCamera();
}

// when a shortcut key is used to move the camera forward
function shortcutCameraForward2(%input)
{
   if (%input == true) $MoveForwardShortcut2 = $movementSpeed / 5;
   else $MoveForwardShortcut2 = 0;
   
   // update the camera movement
   updateShortcutCamera();
}

// when a shortcut key is used to move the camera backward
function shortcutCameraBackward2(%input)
{
   if (%input == true) $MoveBackwardShortcut2 = $movementSpeed / 5;
   else $MoveBackwardShortcut2 = 0;
   
   // update the camera movement
   updateShortcutCamera();
}

// when a shortcut key is used to move the camera left
function shortcutCameraLeft2(%input)
{
   if (%input == true) $MoveLeftShortcut2 = $movementSpeed / 5;
   else $MoveLeftShortcut2 = 0;
   
   // update the camera movement
   updateShortcutCamera();
}

// when a short key is used to move the camera right
function shortcutCameraRight2(%input)
{
   if (%input == true) $MoveRightShortcut2 = $movementSpeed / 5;
   else $MoveRightShortcut2 = 0;
   
   // update the camera movement
   updateShortcutCamera();
}

// this updates the actual movement of the camera based on the
// states of the shortcut keys and the cursor location
function updateShortcutCamera()
{
   if ($Input::WindowScroll == false)
   {
      $mvForwardAction = 0;
      $mvBackwardAction = 0;
      $mvLeftAction = 0;
      $mvRightAction = 0;
      return;
   }
   
   // update the forward action
   if ($MoveForwardMouse < $MoveForwardShortcut1 ||
      $MoveForwardMouse < $MoveForwardShortcut2)
   {
      // check which shortcut to use
      if ($MoveForwardShortcut1 < $MoveForwardShortcut2)
      {
         $mvForwardAction = $MoveForwardShortcut2;
      }
      else
      {
         $mvForwardAction = $MoveForwardShortcut1;
      }
   }
   else
   {
      $mvForwardAction = $MoveForwardMouse;
   }
   
   // update the backward action
   if ($MoveBackwardMouse < $MoveBackwardShortcut1 ||
      $MoveBackwardMouse < $MoveBackwardShortcut2)
   {
      // check which shortcut to use
      if ($MoveBackwardShortcut1 < $MoveBackwardShortcut2)
      {
         $mvBackwardAction = $MoveBackwardShortcut2;
      }
      else
      {
         $mvBackwardAction = $MoveBackwardShortcut1;
      }
   }
   else
   {
      $mvBackwardAction = $MoveBackwardMouse;
   }
   
   // update the left action
   if ($MoveLeftMouse < $MoveLeftShortcut1 ||
      $MoveLeftMouse < $MoveLeftShortcut2)
   {
      // check which shortcut to use
      if ($MoveLeftShortcut1 < $MoveLeftShortcut2)
      {
         $mvLeftAction = $MoveLeftShortcut2;
      }
      else
      {
         $mvLeftAction = $MoveLeftShortcut1;
      }
   }
   else
   {
      $mvLeftAction = $MoveLeftMouse;
   }
   
   // update the right action
   if ($MoveRightMouse < $MoveRightShortcut1 ||
      $MoveRightMouse < $MoveRightShortcut2)
   {
      // check which shortcut to use
      if ($MoveRightShortcut1 < $MoveRightShortcut2)
      {
         $mvRightAction = $MoveRightShortcut2;
      }
      else
      {
         $mvRightAction = $MoveRightShortcut1;
      }
   }
   else
   {
      $mvRightAction = $MoveRightMouse;
   }
}

// when the mouse is moved, check for window scrolling
function handleCameraMove(%mouseX, %mouseY, %scrnWidth, %scrnHeight)
{
   if ($Input::WindowScroll == false)
   {
      $mvForwardAction = 0;
      $mvBackwardAction = 0;
      $mvLeftAction = 0;
      $mvRightAction = 0;
      return;
   }
   
   %screenXMove = 3;
   %screenYMove = 3;
   
   $MoveForwardMouse = 0;
   $MoveBackwardMouse = 0;
   $MoveLeftMouse = 0;
   $MoveRightMouse = 0;
   
   // do not move if the control (window) is not active
   if (PlayGui.isActive() == false)
   {
      return;
   }
   
   // move forward
   if (%mouseY < %screenYMove)
   {
      $MoveForwardMouse = $movementSpeed / 5;
   }

   // move backward
   if (%mouseY >= %scrnHeight - %screenYMove)
   {
      $MoveBackwardMouse = $movementSpeed / 5;
   }
   
   // move left
   if (%mouseX < %screenXMove)
   {
      $MoveLeftMouse = $movementSpeed / 5;
   }
   
   // move right
   if (%mouseX >= %scrnWidth - %screenXMove)
   {
      $MoveRightMouse = $movementSpeed / 5;
   }
   
   updateShortcutCamera();
}

// handle mouse moves for camera movement
function PlayGui::onMouseMove(%this, %input)
{
   %mouseX = getWord(%input, 0);
   %mouseY = getWord(%input, 1);

   // handle updating the highlighted objects   
   handleHighlight(%mouseX, %mouseY);

   // handle planar camera movement based on the cursor
   %scrnWidth = getWord(%input, 2);
   %scrnHeight = getWord(%input, 3);
   
   handleCameraMove(%mouseX, %mouseY, %scrnWidth, %scrnHeight);
}

function PlayGui::selectFromPreSelected()
{
  ServerConnection.setSelectedObjFromPreSelected();
}

//-----------------------------------------------------------------------------

function refreshCenterTextCtrl()
{
   CenteredMessageText.position = "0 0";
}

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// InfoBox

function InfoBox::onWake(%this)
{
  ///echo("**** InfoBox WAKE **** " @ %this.getExtent());
}

function InfoBox::onResize(%this, %width, %height)
{
  %txt_margin = 8;

  %this_pos = %this.getPosition(); 
  %pos_x = getWord(%this_pos,0); 
  %pos_y = getWord(%this_pos,1);

  %win_size = Canvas.getExtent();
  %win_wd = getWord(%win_size,0);
  %win_ht = getWord(%win_size,1);

  %box_wd = %width + 2*%txt_margin;
  %box_ht = %height + 2*%txt_margin;
  %box_x = %win_wd - (%box_wd + 8);
  %box_y = %win_ht - (%box_ht + 60 + 8);

  InfoBoxBackdrop.resize(%box_x, %box_y, %box_wd, %box_ht);
  %this.resize(%box_x + %txt_margin, %box_y + %txt_margin, %width, %height);
}

function clientCmdSetClientPlayer(%player_ghost)
{
  %player = ServerConnection.ResolveGhost(%player_ghost);
  ServerConnection.player = %player;
  //echo("PLAYER ON CLIENT " @ %player_ghost @ " " @ %player);
}

function clientCmdOpenWebPage(%title, %message, %page)
{
  MessageBoxYesNo(%title, %message, "gotoWebPage(\"" @ %page @ "\");", "");
}

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
//SAVE GAME FUNCTIONS
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
$desiredSlotToLoad = -1;

function SaveButton::buttonSelect(%this)
{
   $popDialogList = "saveGameGui ";
   Canvas.pushDialog(saveGameGui);
   slgPopulateSaveButtons();
   
   $CanCancelMenu = false;
}

$QuittingGame = false;
function slgSaveInSlot(%slot)
{
   $desiredSlotToLoad = %slot;
   %saveLoc = %file = slgGetSaveGamePath(%slot);
   if(!slgFileExists(%saveLoc))
   {
      // remove unneeded dialogs
      Canvas.popDialog(GameOverwriteGui);
      Canvas.popDialog(saveGameGui);
      
      // save the game and make sure the game is paused when
      // the save game is complete (no extension is used for
      // the base save game)
      slgSaveGameToSlot(%slot);
      %file = slgGetSaveGamePath(%slot);
      %function = "DoneSavingGame";
      if ($QuittingGame == true)
      {
         $QuittingGame = false;
         $GameMenuLoaded = false;
         %function = "DoneSavingAndExitGame " @ $GameState;
         
         Canvas.popDialog(GameQuitGui);
      }
      
      // do not use networking (multiple saves are bad)
      %client = ClientGroup.getObject(0);
      serverCmdSaveGame(%client, %slot, %file, %function);
      //commandToServer('SaveGame', %slot, %file, %function);
      
      // set up the load button to not be disabled
      LoadButton.disabled = false;
   }
   else
   {
      Canvas.pushDialog(GameOverwriteGui);
   }
}

function DoneAndExitGame()
{
   $GameMenuLoaded = false;
   slgUnpause();
   
   DisasterManager.popAll();
   while (GameResourceStack.getStackCount() > 0)
   {
      GameResourceStack.pop();
   }
   
   loadMenuMission($GameState);
}

function DoneSavingAndExitGame(%loadMission)
{
   slgStopWaiting();
   slgUnpause();
   
   DisasterManager.popAll();
   while (GameResourceStack.getStackCount() > 0)
   {
      GameResourceStack.pop();
   }
   
   slgGetSaveGameName($desiredSlotToLoad, true);
   loadMenuMission(%loadMission);
}

function DoneSavingGame()
{
   $CanCancelMenu = false;
   
   %message = slgGetUIString("id_save_game");
   %name = slgGetSaveGameName($desiredSlotToLoad, true);
   %message = slgFormatUIString(%message, %name);
   notificationWindow(%message, "CloseSavingGameGui();");
   
   // update the save information for the newly saved game
   %saveName = "SaveCtrl" @ $desiredSlotToLoad;
   %control = nameToId(%saveName);
   %control.textUp = %name;
   %control.textFocus = %name;
   %control.textDown = %name;
}

function CloseSavingGameGui()
{
   $CanCancelMenu = true;
   Canvas.popDialog(NotificationGui);
}

function slgDeleteAndSave()
{
   slgDeleteFile( slgGetSaveGamePath($desiredSlotToLoad));
   slgSaveInSlot($desiredSlotToLoad);
}

function slgCloseSaveGui()
{
   $QuittingGame = false;
   $CanCancelMenu = true;
   
   %count = getWordCount($popDialogList);
   for (%index = %count - 1; %index >= 0; %index--)
   {
      %dialog = getWord($popDialogList, %index);
      Canvas.popDialog(%dialog);
   }
}

function slgPopulateSaveButtons()
{
   for (%index = 0; %index < 6; %index++)
   {
      %saveName = "SaveCtrl" @ %index;
      %control = nameToId(%saveName);
      
      %name = "Empty";
      if (slgFileExists(slgGetSaveGamePath(%index)))
      {
         %name = slgGetSaveGameName(%index, false);
      }
      
      %control.textUp = %name;
      %control.textFocus = %name;
      %control.textDown = %name;
   }
}

function slgGetSaveScenarioPath()
{
   return slgGetProfileSaveGameLocation() @ "/mission.slg.dso";
}

function slgGetSaveGamePath(%slot)
{
   return slgGetProfileSaveGameLocation() @ "/Slot " @ %slot @ "/mission.slg.dso";
}

function slgGetSaveProfilePath()
{
   %file = slgGetProfileSaveGameLocation();
   if (%file $= "")
   {
      return "";
   }
   
   return %file @ "/profile.slg";
}

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
//LOAD GAME FUNCTIONS
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//
//Load Game Button
function LoadButton::buttonSelect(%this)
{
   Canvas.pushDialog(loadGameGui);
   slgPopulateLoadButtons();
   
   $CanCancelMenu = false;
}

function EndScenarioLoadBtn::buttonSelect(%this)
{
   Canvas.pushDialog(loadGameGui);
   slgPopulateLoadButtons();
}

function slgLoadFromSlot(%slot)
{
   $CanCancelMenu = true;
   
   // do not use networking- problems with double-clicks
   %file = slgGetSaveGamePath(%slot);
   %client = ClientGroup.getObject(0);
   serverCmdLoadGame(%client, %slot, %file, "slgUnpauseGame", true);
   //commandToServer('LoadGame', %slot, %file, "slgUnpauseGame", true);
}

function slgCloseLoadGui()
{
   if($PlayingGame)
   {
      Canvas.popDialog(GameLoadingGui);
      Canvas.popDialog(loadGameGui);
      slgUnpause();
   }
   else
   {
      prevMenuState(loadGameGui);
   }
   
   $CanCancelMenu = true;
}

function slgCanLoadGame()
{
   for (%index = 0; %index < 6; %index++)
   {
      %saveName = "LoadCtrl" @ %index;
      %control = nameToId(%saveName);
      
      if (slgFileExists(slgGetSaveGamePath(%index)))
      {
         return true;
      }
   }
   
   return false;
}

function slgPopulateLoadButtons()
{
   for (%index = 0; %index < 6; %index++)
   {
      %saveName = "LoadCtrl" @ %index;
      %control = nameToId(%saveName);
      
      %name = "Empty";
      if (slgFileExists(slgGetSaveGamePath(%index)))
      {
         %name = slgGetSaveGameName(%index, false);
         %control.disabled = false;
      }
      else
      {
         %control.disabled = true;
      }
      
      %control.textUp = %name;
      %control.textFocus = %name;
      %control.textDown = %name;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the list of currently selected objects
//! \retval SLGameObjList List of selected objects
////////////////////////////////////////////////////////////////////////////////
function slgGetCurrentSelection()
{
   return gSelection.getSelectedGroup($SELECT_ID);
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the list of currently highlighted objects
//! \retval SLGameObjList List of highlighted objects
////////////////////////////////////////////////////////////////////////////////
function slgGetCurrentHighlights()
{
   return gSelection.getSelectedGroup($HIGHLIGHT_ID);
}

////////////////////////////////////////////////////////////////////////////////
//! Updates the various locator buttons on the hud
////////////////////////////////////////////////////////////////////////////////
function slgUpdateLocatorButtons()
{
   // No need to update hero locator
   for(%i = 1; %i < $TotalLocators; %i++) {
      %index = slgLocateUnit(0, %i, false);
      if(%index == -1) {
         $LocatorBtn[%i].disabled = true;
      }
      else {
         $LocatorBtn[%i].disabled = false;
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Moves camera to current hero
////////////////////////////////////////////////////////////////////////////////
function shortcutLocateHero()
{
   // first make sure the button can be selected
   if (LocateHeroButton.disabled == true)
   {
      return;
   }
   
   // locate the hero
   csClearTargetState();
   slgLocateHero();
}

function slgLocateHero()
{
   // We should always locate the hero
   $HeroLocatorIdx = slgLocateUnit($HeroLocatorIdx, $HeroLocator, true);
   if($HeroLocatorIdx == -1) {
      $HeroLocatorIdx = 0;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Moves to next combat unit
////////////////////////////////////////////////////////////////////////////////
function shortcutLocateCombatUnit()
{
   // first make sure the button can be selected
   if (LocateCombatUnitButton.disabled == true)
   {
      return;
   }
   
   // locate a combat unit
   csClearTargetState();
   slgLocateCombatUnit();
}

function slgLocateCombatUnit()
{
   $CombatLocatorIdx = slgLocateUnit($CombatLocatorIdx, $CombatLocator, true);
   $CombatLocatorIdx++;
}

////////////////////////////////////////////////////////////////////////////////
//! Moves to next jobless unit
////////////////////////////////////////////////////////////////////////////////
function shortcutLocateJoblessUnit()
{
   // first make sure the button can be selected
   if (LocateJoblesstUnitButton.disabled == true)
   {
      return;
   }
   
   // locate a jobless unit
   csClearTargetState();
   slgLocateJoblessUnit();
}

function slgLocateJoblessUnit()
{
   $JoblessLocatorIdx = slgLocateUnit($JoblessLocatorIdx, $JoblessLocator, true);
   $JoblessLocatorIdx++;
}

////////////////////////////////////////////////////////////////////////////////
//! Moves to next civilian unit
////////////////////////////////////////////////////////////////////////////////
function shortcutLocateCivilian()
{
   // first make sure the button can be selected
   if (LocateCivilianButton.disabled == true)
   {
      return;
   }
   
   // locate a civilian
   csClearTargetState();
   slgLocateCivilian();
}

function slgLocateCivilian()
{
   $CivilianLocatorIdx = slgLocateUnit($CivilianLocatorIdx, $CivilianLocator, true);
   $CivilianLocatorIdx++;
}

////////////////////////////////////////////////////////////////////////////////
//! Moves to next building unit
////////////////////////////////////////////////////////////////////////////////
function shortcutLocateBuilding()
{
   // first make sure the button can be selected
   if (LocateBuildingButton.disabled == true)
   {
      return;
   }
   
   // locate a building
   csClearTargetState();
   slgLocateBuilding();
}

function slgLocateBuilding()
{
   $BuildingLocatorIdx = slgLocateUnit($BuildingLocatorIdx, $BuildingLocator, true);
   $BuildingLocatorIdx++;
}
////////////////////////////////////////////////////////////////////////////////
//! Locates the next unit in the list
//! \param %locatorindex Index to start search at
//! \param %locatortype Type of unit we are trying to locate
//! \param %bSelect True to select unit
//! \retval int Index of next locator or -1 if no locator type is found
////////////////////////////////////////////////////////////////////////////////
function slgLocateUnit(%locatorindex, %locatortype, %bSelect)
{
   // Get unit list
   if(%locatortype == $BuildingLocator) {
      %list = slgGetClientBuildingList();
   }
   else {
      %list = slgGetClientCharacterList();
   }
   if(!isObject(%list)) {
      return;
   }
   
   // Get size of list
   %size = %list.getSize();
   
   // If the index is larger then the size then reset the index
   if(%locatorindex >= %size) {
      %locatorindex = 0;
   }
   
   // Starting at previous index do
   for(%i = %locatorindex; %i < %size; %i++) {
      // Get the object
      %obj = %list.getID(%i);
      if(%obj.isOnTeam($OST_PLAYER)) {
         // If object found then
         if(slgUnitLocated(%locatortype, %obj)) {
            // Move camera to object
            if(%bSelect) {
               commandToServer('MoveCameraToObject', ServerConnection.getGhostID(%obj), true);
               selectObject(%obj);
            }
            
            // Return new locator index
            return %i;
         }
      }
      
      // Reset index if next index is equal to size
      if(%i + 1 == %size) {
         %i = -1;
      }
      
      // Break out of loop if next index is equal to where we started
      if(%i + 1 == %locatorindex) {
         return -1;
      }
   }
   
   // Default will always be this
   return -1;
}

////////////////////////////////////////////////////////////////////////////////
//! Tests if the desired unit has been located
//! \param %locator Locator type
//! \param %obj Object to test
////////////////////////////////////////////////////////////////////////////////
function slgUnitLocated(%locator, %obj)
{
   if (%obj.isCollisionEnabled() == false) {
      return false;
   }
   
   %found = false;
   switch(%locator) {
         // Is this object our hero?
      case $HeroLocator:
         %found = %obj.isOfType($HeroObject[$SLGHERO_CURRENT]);
         
         // Is this object a combat object?
      case $CombatLocator:
         if(!%obj.isOfType($HeroObject[$SLGHERO_CURRENT])) {
            %found = isObject(slgQueryInterface(%obj, $CID_COMBAT));
         }
         
         // Is this object a jobless object?
      case $JoblessLocator:
         %cmpChar = slgQueryInterface(%obj, $CID_CHARACTER);
         if(isObject(%cmpChar)) {
            %found = (!%cmpChar.hasWork() && %cmpChar.getDataBlock().canWork);
         }
         
         // Is this a civilian object?
      case $CivilianLocator:
         %found = (%obj.isOfType("MaleCiv") || %obj.isOfType("FemaleCiv"));
      
         // Is this a building object that can be located?
      case $BuildingLocator:
         %cmpBldg = slgQueryInterface(%obj, $CID_BUILDING);
         if(isObject(%cmpBldg)) {
            if(%cmpBldg.getState() == $BuildingState::Production) {
               %found = %cmpBldg.getDatablock().canLocate();
            }
         }
   }
   return %found;
}

////////////////////////////////////////////////////////////////////////////////
//! Resets the locator indexes to zero
////////////////////////////////////////////////////////////////////////////////
function slgResetLocatorIndexes()
{
   $HeroLocatorIdx     = 0;
   $CombatLocatorIdx   = 0;
   $JoblessLocatorIdx  = 0;
   $CivilianLocatorIdx = 0;
   $BuildingLocatorIdx = 0;
}