//------------------------------------------------------------------------------
// File: client_cmdhud.cs
// This file is used for all HUD related functions tied to the command system
// Author: Matthew Rudge
//------------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
//! Called to update the command buttons and the HUD
////////////////////////////////////////////////////////////////////////////////
function slgPopulateCmdBtns()
{
   // Reset HUD
   BuildingHud.Visible   = false;
   CharacterHud.Visible  = false;
   Build1Tab1.selected   = false;
   Build2Tab1.selected   = false;
   Build3Tab1.selected   = false;
   Build1Tab2.selected   = false;
   Build2Tab2.selected   = false;
   Build3Tab2.selected   = false;
   Build1Tab3.selected   = false;
   Build2Tab3.selected   = false;
   Build3Tab3.selected   = false;
   BuildHud1.Visible     = false;
   BuildHud2.Visible     = false;
   BuildHud3.Visible     = false;
   ToolHud.Visible       = false;
   PortraitHud.Visible   = false;
   BldgStatusHud.Visible = false;
      
   // Get selected group
   %selList = gSelection.getSelectedGroup($SELECT_ID);
   if(!isObject(%selList)) {
      return;
   }
   
   // For now, get first object in group and fill HUD
   %obj = %selList.getID(0);
   if(!isObject(%obj))
      return;
 
   csResetCmdBtns(%obj);
   csResetCmdBtnText(%obj);
     
   // Show correct HUD for objects
   %bBldg = false;
   %bChar = false;
   if (%selList.getSize() == 1)
   {
      PortraitHud.Visible = true;
      if (%obj.getTeam() != $OST_PLAYER)
      {
         return;
      }
      
      if(slgIsBuilding(%obj))
      {
         BuildingHud.Visible  = true;
         %bBldg = true;
      }
      else if(slgIsCharacter(%obj))
      {
         CharacterHud.Visible = true;
         %bChar = true;
      }
   }
   
   // Fill selection panel with information
   if(%bBldg) {
      csFillBldgSelectionPanel(%obj);
   }
   else if(%bChar) {
      csFillCharSelectionPanel(%obj);
   }
   
    // If object is not on our team, break out
   if(!%obj.isOnTeam($OST_PLAYER)) {
      return;
   }
   
   // Get command component
   %cmdCmp = slgQueryInterface(%obj, $CID_COMMAND);
   if(!isObject(%cmdCmp))
      return;
      
   // Get command data and populate button
   for(%i = 0; %i < %cmdCmp.getCommandCount(); %i++) {
      %cmdData = %cmdCmp.getCommand(%i);
      %btnName = %cmdCmp.getCommandButton(%i);
      %cmdCmp.onSelect(%btnName);
      %cmdData.populateBtn(%btnName, %obj);
      %cmdData.setCurrentButton(%btnName);
      %cmdData.updateBtn(%cmdCmp, %btnName, %i);
      %cmdData.setSelection(%btnName, %obj);
      
      // Re-populate button if command data has changed
      if(%cmdCmp.getCommand(%i) != %cmdData) {
         %cmdData = %cmdCmp.getCommand(%i);
         %cmdCmp.onSelect(%btnName);
         %cmdData.populateBtn(%btnName, %obj);
         %cmdData.setCurrentButton(%btnName);
         %cmdData.setCommand(%btnName, %cmdCmp);
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Fills the building selection panel with building specific information
////////////////////////////////////////////////////////////////////////////////
function csFillBldgSelectionPanel(%obj)
{
   // Fill name and type strings
   BldgName.stateUp = %obj.name;
   BldgType.stateUp = slgGetObjectString(%obj.getType());
   
   // Update building panel
   %cmpBldg = slgQueryInterface(%obj, $CID_BUILDING);
   csUpdateBldgSelectionPanelEH(%obj);
   csUpdateBldgSelectionPanelPU(%cmpBldg);
   csUpdateBldgSelectionPanelStatus(%cmpBldg, %obj);
}

////////////////////////////////////////////////////////////////////////////////
//! Fills the character selection panel with character specific information
////////////////////////////////////////////////////////////////////////////////
function csFillCharSelectionPanel(%obj)
{
   // Fill name and type strings
   CharName.stateUp = %obj.name;
   CharType.stateUp = slgGetObjectString(%obj.getType());
   
   // Fill occupation
   %empstr = "";
   %cmpChar = slgQueryInterface(%obj, $CID_CHARACTER);
   if(%cmpChar.hasWork()) {
      %empstr = %cmpChar.getWork().getType();
   }
   else {
      %empstr = "no";
   }
   %empstr = %empstr @ "emp";
   CharOccupation.stateUp = slgGetObjectString(%empstr);
   
   // Fill status
   csUpdateCharSelectionPanelStatus(%cmpChar);
}

////////////////////////////////////////////////////////////////////////////////
//! Updates the building selection panel employmenet/housing elements
//! \param %cmpBldg Building component object
////////////////////////////////////////////////////////////////////////////////
function csUpdateBldgSelectionPanelEH(%object)
{
   %icon    = "EHIcon";
   %i       = 0;
   %cmpBldg = slgQueryInterface(%object, $CID_BUILDING);
   
   // Do only if on player team
   if(%object.isOnTeam($OST_PLAYER)) {
      // Decide on employment/housing
      if(%cmpBldg.getTenantMax() < %cmpBldg.getEmployeeMax()) {
         %max   = %cmpBldg.getEmployeeMax();
         %count = %cmpBldg.getEmployeeCount();
         %fill  = $EmployedIcon;
         %fillfocus = $EmployedIconFocus;
         %empty = $UnemployedIcon;
         %bEmp  = true;
      }
      else {
         %max   = %cmpBldg.getTenantMax();
         %count = %cmpBldg.getTenantCount();
         %fill  = $HousedIcon;
         %fillfocus = $HousedIconFocus;
         %empty = $UnhousedIcon;
         %bEmp  = false;
      }
      
      // Update employment/tenant icons
      for(%i = 0; %i < %max; %i++) {
         %iconName = %icon @ %i;
         %iconName.Visible = true;
         %iconName.bmpTimer = 0;
         if(%i < %count) {
            %iconName.stateUp = %fill;
            %iconName.stateFocus = %fillfocus;
            %iconName.stateDown = %fill;
            if(%bEmp) {
               %cmd = "selectObject(" @ %cmpBldg.getEmployee(%i).getId() @ ", 1, 1);";
            }
            else {
               %cmd = "selectObject(" @ %cmpBldg.getTenant(%i).getId() @ ", 1, 1);";
            }
            %iconName.Command = %cmd;
         }
         else {
            // If building has a timer, apply it to first empty icon
            if(%i == %count && isObject(%cmpBldg.houseTimer)) {
               %iconName.bmpTimer = %cmpBldg.houseTimer;
               %iconName.stateUp = %fill;
               %iconName.stateFocus = %fillfocus;
               %iconName.stateDown = %fill;
            }
            else {
               %iconName.stateUp = %empty;
               %iconName.stateFocus = %empty;
               %iconName.stateDown = %empty;
            }
            %iconName.Command = "";
         }
      }
   }
   
   // Hide rest of icons
   %iconName = %icon @ %i;
   while(isObject(%iconName)) {
      %iconName.Visible = false;
      %iconName.bmpTimer = 0;
      %iconName.Command = "";
      %iconName = %icon @ %i++;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Updates the production and upkeep for the building
////////////////////////////////////////////////////////////////////////////////
function csUpdateBldgSelectionPanelPU(%cmpBldg)
{
   %resource[0]     = $Resource::Gold;
   %resource[1]     = $Resource::Wood;
   %resource[2]     = $Resource::Food;
   %resource[3]     = $Resource::Water;
   %resourceicon[0] = "assets/client/ui/icons/gold.png";
   %resourceicon[1] = "assets/client/ui/icons/wood.png";
   %resourceicon[2] = "assets/client/ui/icons/food.png";
   %resourceicon[3] = "assets/client/ui/icons/water.png";
   
   BldgProduceText.Visible  = false;
   BldgProduceIcon.Visible  = false;
   BldgProduceArrow.Visible = false;
   BldgConsumeText.Visible  = false;
   BldgConsumeIcon.Visible  = false;
   BldgConsumeArrow.Visible = false;
   
   
   // For each resource do   
   for(%i = 0; %i < 4; %i++) {
      // If this building produces this resource then
      if(%cmpBldg.doesProduce(%resource[%i])) {
         // Get its true production
         %prod = %cmpBldg.getTrueProduction(%resource[%i]);
         BldgProduceText.stateUp = mFloor(%prod);
         BldgProduceIcon.stateUp = %resourceicon[%i];
         BldgProduceText.Visible = true;
         BldgProduceIcon.Visible = true;
         BldgProduceArrow.Visible = true;
      }
      
      // If this building consumes this resource then
      else if(%cmpBldg.doesConsume(%resource[%i])) {
         // Get its true consumption
         %cnsm = %cmpBldg.getTrueConsumption(%resource[%i]);
         BldgConsumeText.stateUp = mFloor(%cnsm);
         BldgConsumeIcon.stateUp = %resourceicon[%i];
         BldgConsumeText.Visible = true;
         BldgConsumeIcon.Visible = true;
         BldgConsumeArrow.Visible = true;
      }
   }
   
   // Town hall is special (YAY!)...have to treat it separately
   %object = slgGetAttachedObjId(%cmpBldg);
   if(%object.isOfType("TownHall")) {
      %amount  = %cmpBldg.getCurrentTaxAmount(slgGetClientCharacterList());
      BldgProduceText.stateUp = %amount;
      BldgProduceIcon.stateUp = %resourceicon[0];
      BldgProduceText.Visible = true;
      BldgProduceIcon.Visible = true;
      BldgProduceArrow.Visible = true;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Updates the building selection panel status elements
////////////////////////////////////////////////////////////////////////////////
function csUpdateBldgSelectionPanelStatus(%cmpBldg, %object)
{
   %bldgStatus  = "BldgStatus";
   %bldgMod     = "BldgStatusMod";
   %bldgIcon    = "BldgStatusIcon";
   %cmpBldgData = %cmpBldg.getDataBlock();
   
   // Reset all status lines
   BldgStatusMain.stateUp      = "";
   BldgStatusModMain.stateUp   = "";
   BldgStatusIconMain.Visible  = false;
   BldgStatusIconMain.selected = false;
   for(%line = 0; %line < $CS_MAXBLDGSTATUS; %line++) {
      %status = %bldgStatus @ %line;
      %mod    = %bldgMod @ %line;
      %icon   = %bldgIcon @ %line;
      %status.stateUp = "";
      %mod.stateUp = "";
      %icon.Visible = false;
      %icon.selected = false;
   }
   
   // Reset line to start at beginning
   %line    = 0;
   
   /******* Production related statuses *******/
   if(%cmpBldg.hasStatus($BuildingStatus::NoGold)) {
      csSetBldgStatusString(%line, "bldg_status_nogold");
      %line++;
   }
   else if(%cmpBldg.hasStatus($BuildingStatus::NoWood)) {
      csSetBldgStatusString(%line, "bldg_status_nowood");
      %line++;
   }
   
   // Needs employees
   else if(!%cmpBldg.getEmployeeCount() && %cmpBldg.getEmployeeMax() > 0) {
       csSetBldgStatusString(%line, "bldg_status_employees");
      %line++;
   }
   
   // Lacks some resource for production   
   else if(%cmpBldg.hasStatus($BuildingStatus::NeedWater)) {
      csSetBldgStatusString(%line, "bldg_status_nowater");
      %line++;
   }
   
   // Production bonus strings
   else {
      // Building is boosted by another
      if(%cmpBldgData.isBoosted()) {
         %boostername = slgGetObjectString(slgGetBooster(%object));
         csSetBldgStatusString(%line, "bldg_status_prodboost", %boostername);
         %line++;      
      }
      
      // Production is changed by happiness
      if(%cmpBldg.doesProduceResources()) {
         %happy = rsGetHappinessProductionAffect();
         if(%happy > 1) {
            csSetBldgStatusString(%line, "bldg_status_prodhappyhigh");
            %line++;
         }
         else if(%happy < 1) {
            csSetBldgStatusString(%line, "bldg_status_prodhappylow");
            %line++;
         }
      }
      
      // Production is affected by upgrade
      if(csIsCmdUpgradePurchasedLocal($CSUP_AXE)) {
         if(%object.isOfType("Woodhut")) {
            csSetBldgStatusString(%line, "bldg_status_axeup");
            %line++;
         }
      }
      if(csIsCmdUpgradePurchasedLocal($CSUP_PICK)) {
         if(%object.isOfType("Goldmine")) {
            csSetBldgStatusString(%line, "bldg_status_pickup");
            %line++;
         }
      }
      if(csIsCmdUpgradePurchasedLocal($CSUP_TRACK)) {
         if(%object.isOfType("trainstation")) {
            csSetBldgStatusString(%line, "bldg_status_trainup");
            %line++;
         }
      }
   }
   
   // Damaged
   if(%cmpBldg.hasStatus($BuildingStatus::Damaged)) {
      csSetBldgStatusString(%line, "bldg_status_damaged");
      csSetBldgStatusMod(%line, %cmpBldg.damageHappiness);
      csSetBldgStatusIcon(%line, true);
      %line++;
   }
   
   // On Fire
   if(%cmpBldg.hasStatus($BuildingStatus::Fire)) {
      csSetBldgStatusString(%line, "bldg_status_fire");
      %line++;
   }
   
   // Plague
   if(%cmpBldg.hasStatus($BuildingStatus::Plague)) {
      csSetBldgStatusString(%line, "bldg_status_plague");
      %line++;
   }
   
   // Generates happiness when built   
   if(%cmpBldgData.hasBuildHappiness()) {
      // This is a HACK, but it was the quickest way to get it working in the
      // little time we have
      // Get the server object and get a list of server buildings that match the
      // type of the object
      %svrObject = ServerConnection.getGhostID(%object);
      %svrObject = ClientGroup.getObject(0).resolveObjectFromGhostIndex(%svrObject);
      %bldgs = new SLGameObjList();
      slgGetServerBuildingListMatch(
         %svrObject.getType(), 
         $OST_PLAYER, 
         $BuildingState::Production, 
         %bldgs
         );
      
      // Loop through this building list and find the building index to get its
      // happiness value
      %happy = 0;
      %count = %bldgs.getSize();
      for(%i = 0; %i < %count; %i++) {
         %listobj = %bldgs.getID(%i);
         if(%listobj == %svrObject) {
            %happy = %cmpBldgData.getBuildHappiness(%i);
            break;
         }
      }
      %bldgs.delete();
      
      // Set happiness
      if(%happy) {
         csSetBldgStatusString(%line, "bldg_status_happy");
         csSetBldgStatusMod(%line, %happy);
         if(%happy > 0) {
            csSetBldgStatusIcon(%line, false);
         }
         else if(%happy < 0) {
            csSetBldgStatusIcon(%line, true);
         }
      }     
      %line++;
   }
   
   // Normal (nothing else is shown)
   if(!%line) {
      csSetBldgStatusString(%line, "bldg_status_normal");
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Sets a building status string in the building selection panel
//! \param %line Line number of status string
//! \param %id String id of status string
////////////////////////////////////////////////////////////////////////////////
function csSetBldgStatusString(%line, %id, %format)
{
   %status = "BldgStatus" @ %line;
   %string = slgGetObjectString(%id);
   if(%format !$= "") {
      %string = slgFormatObjectString(%string, %format);
   }
   %status.stateUp = %string;
   if(!%line) {
      BldgStatusMain.stateUp = %status.stateUp;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Sets a building status mod in the building selection panel
//! \param %line Line number of status mod
//! \param %value Value of mod
////////////////////////////////////////////////////////////////////////////////
function csSetBldgStatusMod(%line, %value)
{
   %mod = "BldgStatusMod" @ %line;
   %mod.stateUp = %value;
   if(!%line) {
      BldgStatusModMain.stateUp = %value;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Sets a building status icon in the building selection panel
//! \param %line Line number of status icon
//! \param %selected True if the icon should be in the selected state
////////////////////////////////////////////////////////////////////////////////
function csSetBldgStatusIcon(%line, %selected)
{
   %icon = "BldgStatusIcon" @ %line;
   %icon.Visible  = true;
   %icon.selected = %selected;
   if(!%line) {
      BldgStatusIconMain.Visible  = true;
      BldgStatusIconMain.selected = %selected;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Toggles the building status hud
////////////////////////////////////////////////////////////////////////////////
function csToggleBldgStatusHud()
{
   // Hide building status hud
   if(BldgStatusHud.Visible) {
      BldgStatusHud.Visible = false;
      return;
   }
   // Show building status hud
   else {
      BldgStatusHud.Visible = true;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Updates the character selection panel status elements
//! \param %cmpChar Character component object
////////////////////////////////////////////////////////////////////////////////
function csUpdateCharSelectionPanelStatus(%cmpChar)
{
   // Initialize
   CharStatus.stateUp = "";
   %cmpData  = %cmpChar.getDataBlock();
   %strtemp  = "";
   %statestr = "";
 
   %object = slgGetAttachedObjId(%cmpChar);  
   if(!%object.isOnTeam($OST_PLAYER)) {
      return;
   }
   
   // Drunk
   if(%cmpChar.inState($CharacterState::Drunk)) {
      %strtemp  = slgGetObjectString("status_drunk");
      %strtemp  = slgFormatObjectString(%strtemp, %cmpData.drunkHappiness);
      %statestr = csConcatenateStateStr(%statestr, %strtemp);
   }
   
   // Homeless
   if(%cmpChar.inState($CharacterState::NoHomeStageOne)) {
      %strtemp  = slgGetObjectString("status_homeless");
      %strtemp  = slgFormatObjectString(%strtemp, %cmpData.homelessHappiness);
      %statestr = csConcatenateStateStr(%statestr, %strtemp);
   }
   else if(%cmpChar.inState($CharacterState::NoHomeStageTwo)) {
      %strtemp  = slgGetObjectString("status_homeless");
      %statemod = %cmpData.homelessHappiness * 2;
      %strtemp  = slgFormatObjectString(%strtemp, %statemod);
      %statestr = csConcatenateStateStr(%statestr, %strtemp);
   }
   
   // Jobless
   if(%cmpChar.inState($CharacterState::NoWorkStageOne)) {
      %strtemp  = slgGetObjectString("status_jobless");
      %strtemp  = slgFormatObjectString(%strtemp, %cmpData.joblessHappiness);
      %statestr = csConcatenateStateStr(%statestr, %strtemp);
   }
   else if(%cmpChar.inState($CharacterState::NoWorkStageTwo)) {
      %strtemp  = slgGetObjectString("status_jobless");
      %statemod = %cmpData.joblessHappiness * 2;
      %strtemp  = slgFormatObjectString(%strtemp, %statemod);
      %statestr = csConcatenateStateStr(%statestr, %strtemp);
   }
   else if(%cmpChar.inState($CharacterState::NoWorkStageThree)) {
      %strtemp  = slgGetObjectString("status_jobless");
      %statemod = %cmpData.joblessHappiness * 3;
      %strtemp  = slgFormatObjectString(%strtemp, %statemod);
      %statestr = csConcatenateStateStr(%statestr, %strtemp);
   }
   
   // Hungry   
   if(%cmpChar.isHungry()) {
      %strtemp  = slgGetObjectString("status_hungry");
      %strtemp  = slgFormatObjectString(%strtemp, %cmpChar.getHunger());
      %statestr = csConcatenateStateStr(%statestr, %strtemp);
   }
   
   // Normal
   if(%statestr $= "") {
      %statestr = slgGetObjectString("status_char_normal");
   }
   
   // Set text
   CharStatus.stateUp = %statestr;
}

////////////////////////////////////////////////////////////////////////////////
//! Concatenates the state string for the status panel for characters and 
//! buildings
//! \param %statestr Current state string
//! \param %string String to concatenate
//! \retval string Concatenated string
////////////////////////////////////////////////////////////////////////////////
function csConcatenateStateStr(%statestr, %string)
{
   if(%statestr !$= "") {
      %statestr = %statestr @ ", ";
   }
   return %statestr @ %string;
}

////////////////////////////////////////////////////////////////////////////////
//! Resets all the command buttons of an object to default values
//! \param %obj Object that will have its command buttons reset
////////////////////////////////////////////////////////////////////////////////
function csResetCmdBtns(%obj)
{   
   // Reset buttons
   for(%i = 0; %i < $CS_MAXCMDBTNS; %i++) {
      %btnName = csGetCmdBtn(%obj, %i);
      csResetCmdBtn(%btnName);
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Resets all the command button text of an object to default values
//! \param %obj Object that will have its command button text reset
////////////////////////////////////////////////////////////////////////////////
function csResetCmdBtnText(%obj)
{
   // Reset button text
   for(%i = 0; %i < $CS_MAXCMDBTNTEXT; %i++) {
      %btnText = csGetCmdBtnText(%obj, %i);
      %btnText.stateUp = "";
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the command button for an object at the specified index
//! \param %obj Object who has command buttons
//! \param %index Index of command button
////////////////////////////////////////////////////////////////////////////////
function csGetCmdBtn(%obj, %index)
{
   if(slgIsCharacter(%obj)) {
      return csGetCharacterButton(%index);
   }
   else if(slgIsBuilding(%obj)) {
      return csGetBuildingButton(%index);
   }
   else {
      return "";
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the command button text for an object at the specified index
//! \param %obj Object who has command buttons
//! \param %index Index of command button
////////////////////////////////////////////////////////////////////////////////
function csGetCmdBtnText(%obj, %index)
{
   if(slgIsCharacter(%obj)) {
      return csGetCharacterBtnText(%index);
   }
   else if(slgIsBuilding(%obj)) {
      return csGetBuildingBtnText(%index);
   }
   else {
      return "";
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Resets the given button to default values
//! \param %btn Button to reset
////////////////////////////////////////////////////////////////////////////////
function csResetCmdBtn(%btn)
{
   %btn.Visible      = false;
   %btn.Command      = "";
   %btn.disabled     = false;
   %btn.input        = false;
   %btn.tempSelected = false;
}

////////////////////////////////////////////////////////////////////////////////
//! Used to create a bitmap timer for an object
//! \param %btn Button to place timer on
//! \param %bmpPath Path of bitmap to use for timer
//! \param %time Total time for bitmap timer
//! \retval int Id of bitmap timer
////////////////////////////////////////////////////////////////////////////////
function csCreateBmpTimer(%btn, %bmpPath, %time)
{   
   // Create timer
   %timer = new SLBmpTimer() {
      time         = %time;
      tickDistance = 1;
      renderExt    = %btn.Extent;
      texture      = %bmpPath;
   };
   
   return %timer;
}

////////////////////////////////////////////////////////////////////////////////
//! Used to update the cursor depending on command
//! \param %cmd Current command
////////////////////////////////////////////////////////////////////////////////
$LastCursor = $CSC_NONE;
$FlyingCursor = false;
function csUpdateCursor(%cmd)
{
   if (isObject(GameCamera) == true)
   {
      %camera = GameCamera.getCameraCmp();
      if (isObject(%camera) == true && %camera.isMovingToPos() == true)
      {
         if ($FlyingCursor == true)
         {
            $LastCursor = %cmd;
         }
         
         $FlyingCursor = true;
         Canvas.setCursor(FlyCursor);
         return;
      }
      else if ($FlyingCursor == true)
      {
         // force flying camera to turn off
         $FlyingCursor = false;
         //%cmd = $LastCursor;
         %cmd = $CSC_NONE;
      }
   }

   $LastCursor = %cmd;
   
   // Swap cursor on command   
   switch(%cmd) {
      case $CSC_MOVE:
         Canvas.setCursor(MoveCursor);
      case $CSC_EMPLOY:
         // Invalid cursor on employ at a building with no gold or wood left
         // to produce
         %cmpBldg = slgQueryInterface(CmdStateTracker.getObjTarget(), $CID_BUILDING);
         if(isObject(%cmpBldg)) {
            if(%cmpBldg.hasStatus($BuildingStatus::NoGold)
            || %cmpBldg.hasStatus($BuildingStatus::NoWood)) {
               Canvas.setCursor(NoActionCursor);
               return;
            }
         }
         csSetTeamCursor(EmployCursor);
      case $CSC_PICKUP:
         Canvas.setCursor(PickUpCursor);
      case $CSC_REPAIR:
         csSetTeamCursor(RepairCursor);
      case $CSC_BUILD:
         csSetTeamCursor(BuildCursor);
      case $CSC_ATTACK:
         Canvas.setCursor(AttackCursor);
      case $CSC_QUICKJOB:
         Canvas.setCursor(QuickJobCursor);
      case $CSC_FIGHTFIRE:
         csSetTeamCursor(FightFireCursor);
      case $CSC_REFORM:
         Canvas.setCursor(ReformCursor);
      default:
         Canvas.setCursor(DefaultCursor);
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Sets the cursor provided if target is on player's team. Otherwise set's
//! the invalid command cursor
////////////////////////////////////////////////////////////////////////////////
function csSetTeamCursor(%cursor)
{
   // Set icon based on team of target
   %target = CmdStateTracker.getObjTarget();
   if(isObject(%target)) {
      if(%target.isLinkObj()) {
         %target = %target.getFirstLinkObj();
      }
   }
   if(!isObject(%target)) {
      Canvas.setCursor(%cursor);
      return;
   }
   
   if(%target.isOnTeam($OST_PLAYER)) {
      Canvas.setCursor(%cursor);
   }
   else {
      Canvas.setCursor(NoActionCursor);
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Tests if a button should be selected, dependent on the object and what it is
//! producing and the selector string from the command data datablock
//! \param %selector Selector string
//! \param %obj Object
//! \param %btn Button in question
//! \retval bool True if the button should be selected
////////////////////////////////////////////////////////////////////////////////
function csIsButtonSelected(%selector, %obj, %btn)
{
   // Temporarily selected until server responds
   if(%btn.tempSelected) {
      return true;
   }
   
   // Get building component
   %cmpBldg = slgQueryInterface(%obj, $CID_BUILDING);
   if(!isObject(%cmpBldg)) {
      return false;
   }
   
   // If selector string is a resource selector then check building production
   if(csIsRsrcSelector(%selector)) {
      return (%cmpBldg.isProducing(csGetRsrcForRsrcSelector(%selector)));
   }
   
   // If selector string is a tax selector then check building tax level
   else if(csIsTaxSelector(%selector)) {
      return (%cmpBldg.taxLevel $= %selector);
   }
   
   // Else if selector string is a crop selector then check crop
   else if(csIsCropSelector(%selector)) {
      return (%cmpBldg.produce $= %selector);
   }
   
   // If selector string is a gunslinger selector then check for existence
   else if(csIsSlingerSelector(%selector)) {
      return isObject(%obj.recruitedSlinger[%btn.btnIndex]);
   }
   
   // If selector string is a sheriff selector then check for existence
   else if(csIsSheriffSelector(%selector)) {
      
      %cmpCmd = slgQueryInterface(%obj, $CID_COMMAND);
      if(isObject(%cmpCmd)) {
         %sheriff = %cmpCmd.getDataBlock().recruitedSheriff;
         if(!isObject(%sheriff)) {
            return false;
         }
         // Tough sheriff selector
         if(%selector $= "toughsheriff") {
            // Recruited sheriff is a tough sheriff
            if(%sheriff.isOfType("Toughsheriff")) {
               return true;
            }
            else {
               return false;
            }
         }
         // Weak sheriff selector
         else {
            // Recruited sheriff is a weak sheriff
            if(%sheriff.isOfType("Toughsheriff")) {
               return false;
            }
            else {
               return true;
            }
         }
      }
      else {
         return false;
      }
   }
   
   else if(csIsUpgradeSelector(%selector)) {
      return csIsCmdUpgradePurchasedLocal(csGetUpgradeForUpgradeSelector(%selector));
   }
   
   // Default is false
   else {
      return false;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Tests if the selector string is a crop selector
//! \param %selector Selector string
//! \retval bool True if the selector string is a crop selector
////////////////////////////////////////////////////////////////////////////////
function csIsCropSelector(%selector)
{
   // Selector must equal one of these items to be a crop selector
   return (%selector $= "wheat"     ||
           %selector $= "corn"      ||
           %selector $= "pumpkin"   ||
           %selector $= "chicken"   ||
           %selector $= "cow"       ||
           %selector $= "pig"       ||
           %selector $= "sunflower" ||
           %selector $= "sheep");
}

////////////////////////////////////////////////////////////////////////////////
//! Tests if the selector string is a slinger selector
//! \param %selector Selector string
//! \retval bool True if the selector string is a slinger selector
////////////////////////////////////////////////////////////////////////////////
function csIsSlingerSelector(%selector)
{
   return (%selector $= "slinger");
}

////////////////////////////////////////////////////////////////////////////////
//! Tests if the selector string is a sheriff selector
//! \param %selector Selector string
//! \retval bool True if the selector string is a sheriff selector
////////////////////////////////////////////////////////////////////////////////
function csIsSheriffSelector(%selector)
{
   return (%selector $= "toughsheriff" ||
           %selector $= "weaksheriff");
}

////////////////////////////////////////////////////////////////////////////////
//! Tests if the selector string is a resource selector
//! \param %selector Selector string
//! \retval bool True if the selector string is a resource selector
////////////////////////////////////////////////////////////////////////////////
function csIsRsrcSelector(%selector)
{
   // Selector must be one of these items to be a resource selector
   return (%selector $= "gold" ||
           %selector $= "wood" ||
           %selector $= "food");
}

////////////////////////////////////////////////////////////////////////////////
//! Tests if the selector string is a tax selector
//! \param %selector Selector string
//! \retval bool True if the selector string is a tax selector
////////////////////////////////////////////////////////////////////////////////
function csIsTaxSelector(%selector)
{
   // Selector must be one of these items to be a tax selector
   return (%selector $= "notax"  ||
           %selector $= "lowtax" ||
           %selector $= "hightax");
}

////////////////////////////////////////////////////////////////////////////////
//! Tests if the selector string is an upgrade selector
//! \param %selector Selector string
//! \retval bool True if the selector string is an upgrade selector
////////////////////////////////////////////////////////////////////////////////
function csIsUpgradeSelector(%selector)
{
   return (%selector $= "trackupgrade" ||
           %selector $= "pickupgrade" ||
           %selector $= "axeupgrade" ||
           %selector $= "gunupgrade" ||
           %selector $= "bldgupgrade");
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the resource integer for a resource selector
//! \param %selector Resource selector string
//! \retval int Resource integer or -1 if invalid selector string
////////////////////////////////////////////////////////////////////////////////
function csGetRsrcForRsrcSelector(%selector)
{
   switch$(%selector) {
      case "gold":
         return $Resource::Gold;
      case "wood":
         return $Resource::Wood;
      case "food":
         return $Resource::Food;
      default:
         return -1;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the upgrade integer for an upgrade selector
//! \param %selector Upgrade selector string
//! \retval int Upgrade integer or -1 if invalid selector string
////////////////////////////////////////////////////////////////////////////////
function csGetUpgradeForUpgradeSelector(%selector)
{
   switch$(%selector) {
      case "trackupgrade":
         return $CSUP_TRACK;
      case "pickupgrade":
         return $CSUP_PICK;
      case "axeupgrade":
         return $CSUP_AXE;
      case "gunupgrade":
         return $CSUP_GUN;
      case "bldgupgrade":
         return $CSUP_BLDG;
      default:
         return -1;
   }
}

$DynamiteBuilding = false;

//-Button Select Commands-------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
//! Building hud command button callback
////////////////////////////////////////////////////////////////////////////////
function shortcutBuildCommand()
{
   // if the character hud is visible, select the building button
   if (CharacterHud.visible == true)
   {
      // the button needs to be visible and enabled to select
      if (CharCmdButton0.visible == false ||
         CharCmdButton0.disabled == true)
      {
         return;
      }
      
      // if dynamite is being created for placement, build
      // cannot be selected
      if ($DynamiteBuilding == true)
      {
         return;
      }
      
      // select the build command
      csExecuteBldgHudCmdBtn();
   }
   // otherwise, rotate through the building tabs (1 goes to 2)
   else if (BuildHud1.visible == true)
   {
      Build1Tab2.buttonSelect();
   }
   // (2 goes to 3)
   else if (BuildHud2.visible == true)
   {
      Build2Tab3.buttonSelect();
   }
   // and (3 goes to 1)
   else if (BuildHud3.visible == true)
   {
      Build3Tab1.buttonSelect();
   }
}

function csExecuteBldgHudCmdBtn()
{   
   // Bring up building hud
   Build1Tab1.selected = true;
   Build2Tab1.selected = true;
   Build3Tab1.selected = true;
   Build1Tab2.selected = false;
   Build2Tab2.selected = false;
   Build3Tab2.selected = false;
   Build1Tab3.selected = false;
   Build2Tab3.selected = false;
   Build3Tab3.selected = false;
   BuildHud1.visible = true;
   CharacterHud.visible = false;
}

////////////////////////////////////////////////////////////////////////////////
//! Build command button callback
//! \param %type datablock name
//! \param %name object name
////////////////////////////////////////////////////////////////////////////////
function csExecuteBuildCmdBtn(%type, %name)
{
   // We are waiting for previous command to finish
   if(CmdStateTracker.isInState($CSS_EXECUTE) || $CSC_PENDING) {
      return;
   }
   
   // Clear previous building if we were building something
   csClearTargetState();
   
   // Create building for placement
   %object = getSelectedObject(0);
   %team = %object.getTeam();
   csBeginWaitForCmd();
   commandToServer('CreateForPlacement', %type, %name, %object.getTeam());
}

////////////////////////////////////////////////////////////////////////////////
//! Callback when the demolish command button has been pressed
////////////////////////////////////////////////////////////////////////////////
function csExecuteDemolishCmdBtn()
{
   // Notify server
   csExecuteCmdBtnOnTarget('OnDemolishCmdBtn');
}

////////////////////////////////////////////////////////////////////////////////
//! Callback when the recruit gunslinger command button has been pressed
//! \param %type Type of gunslinger to recruit
//! \param %index Index of button that issued request
////////////////////////////////////////////////////////////////////////////////
function csExecuteRecruitSlingerCmdBtn(%cmdData, %type, %index)
{
   %btn = csGetCmdBtn(getSelectedObject(0), %index);
   csExecuteCmdBtnOnTarget('OnRecruitCmdBtn', %cmdData.getId() SPC %type, 'OnSlingerRecruitCmdBtn', %btn);
}

////////////////////////////////////////////////////////////////////////////////
//! Callback when the recruit deputy command button has been pressed
//! \param %type Type of deputy to recruit
////////////////////////////////////////////////////////////////////////////////
function csExecuteRecruitDeputyCmdBtn(%cmdData, %type)
{
   // Stop recruit of deputy if we already have three
   %canRecruit = false;
   %tgt = getSelectedObject(0);
   for(%i = 0; %i < $CS_MAXDEPUTIES; %i++) {
      if(%tgt.recruitedDeputy[%i] $= "") {
         %canRecruit = true;
         break;
      }
   }
   
   if(%canRecruit) {   
      %btn = %cmdData.getCurrentButton();   
      csExecuteCmdBtnOnTarget('OnRecruitCmdBtn', %cmdData.getId() SPC %type, 'OnDeputyRecruitCmdBtn', %btn);
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Callback when the recruit sherriff command button has been pressed
//! \param %type Type of sherriff to recruit
////////////////////////////////////////////////////////////////////////////////
function csExecuteRecruitSheriffCmdBtn(%cmdData, %type)
{
   %btn = %cmdData.getCurrentButton();
   csExecuteCmdBtnOnTarget('OnRecruitCmdBtn', %cmdData.getId() SPC %type, 'OnSheriffRecruitCmdBtn', %btn);
}

////////////////////////////////////////////////////////////////////////////////
//! Callback when the quit job command button has been pressed
////////////////////////////////////////////////////////////////////////////////
function csExecuteQuitJobCmdBtn()
{   
   // Notify server that a unit is quitting a job
   csExecuteCmdBtnOnTarget('OnQuitJobCmdBtn');
}

////////////////////////////////////////////////////////////////////////////////
//! Callback when the dismiss hired unit command button has been pressed
////////////////////////////////////////////////////////////////////////////////
function csExecuteDismissCmdBtn()
{
   // Notify server that a unit is being dismissed
   csExecuteCmdBtnOnTarget('OnDismissCmdBtn');
}

////////////////////////////////////////////////////////////////////////////////
//! Callback when a crop swap button has been pressed
//! \param %produce New crop
//! \param %cmdData Datablocks affected by swap (for timer). First is datablock
//! that populated button with command
////////////////////////////////////////////////////////////////////////////////
function csExecuteProductionSwapCmdBtn(%produce, %cmdData)
{
   %tgt = getSelectedObject(0);
   if(!isObject(%tgt)) {
      return;
   }
   
   // Create bitmap timer
   %btn = %cmdData.getCurrentButton();
   %tgt.prodBmpTimer = csCreateBmpTimer(%btn, "assets/client/ui/icons/timerclock.png", 5.0);  
   
   // Execute command button
   csExecuteCmdBtnOnTarget('OnProductionSwapCmdBtn', %cmdData.getId() SPC %produce, "", %btn);
}

////////////////////////////////////////////////////////////////////////////////
//! Callback when a purchase item command button has been pressed
//! \param %cmdData Datablock name
//! \param %item Purchased item
////////////////////////////////////////////////////////////////////////////////
function csExecuteItemPurchaseCmdBtn(%cmdData, %item)
{
   csExecuteCmdBtn('OnItemPurchaseCmdBtn', %cmdData.getId() SPC %item);
}

////////////////////////////////////////////////////////////////////////////////
//! Callback when a use item command button has been pressed
//! \param %item Used item
////////////////////////////////////////////////////////////////////////////////
$PLACE_DYNAMITE = false;
function csExecuteItemUseCmdBtn(%item)
{
   // if dynamite is selected, do nothing if dynamite is already attached
   if (%item == $INV_DYNAMITE && $PLACE_DYNAMITE == true)
   {
      return;
   }
   
   // if dynamite is selected, do not allow the shortcut build button
   if (%item == $INV_DYNAMITE)
   {
      $DynamiteBuilding = true;
   }
   
   %slot = invGetSlotForItem(ServerConnection.getId(), %item);
   if(%slot != -1) {
      invClientSelectItem(%slot);
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Callback when a building upgrade command button has been pressed
//! \param %cmdData Command data for button
//! \param %type New building type
////////////////////////////////////////////////////////////////////////////////
function csExecuteBldgUpgradeCmdBtn(%cmdData, %type)
{
   csExecuteCmdBtnOnTarget('OnBldgUpgradeCmdBtn', %cmdData.getId() SPC %type);
}

////////////////////////////////////////////////////////////////////////////////
//! Callback when a resource trade command button has been pressed
//! \param %cmdData CommandData data block that is responsible for trade
////////////////////////////////////////////////////////////////////////////////
function csExecuteResourceTradeCmdBtn(%cmdData)
{
   csExecuteCmdBtn('OnResourceTradeCmdBtn', %cmdData.getId());
}

////////////////////////////////////////////////////////////////////////////////
//! Callback when a parade command button has been pressed
//! \param %cmdData CommandData data block that is responsible for parade
////////////////////////////////////////////////////////////////////////////////
function csExecuteParadeCmdBtn(%cmdData)
{
   %tgt = getSelectedObject(0);
   if(!isObject(%tgt)) {
      return;
   }
   
   // Create bitmap timer
   %btn = %cmdData.getCurrentButton();
   %tgt.paradeBmpTimer = csCreateBmpTimer(%btn, "assets/client/ui/icons/timerclock.png", 30.0);
   
   // Disable button now and put timer on button to stop from multiple clicks
   %btn.disabled = true;
   %btn.bmpTimer = %tgt.paradeBmpTimer;
   
   csExecuteCmdBtnOnTarget('OnParadeCmdBtn', %cmdData.getId());
}

////////////////////////////////////////////////////////////////////////////////
//! Callback when an upgrade command button has been pressed
//! \param %cmdData CommandData data block that is responsible for upgrade
//! \param %upgrade Upgrade type
//! \param %value Value for upgrade
////////////////////////////////////////////////////////////////////////////////
function csExecuteUpgradeCmdBtn(%cmdData, %upgrade, %value)
{
   %btn = %cmdData.getCurrentButton();
   csExecuteCmdBtn('PurchaseUpgrade', %cmdData.getId() SPC %upgrade SPC %value, %btn);
}

////////////////////////////////////////////////////////////////////////////////
//! Sends a command to the server after a command button has been pressed
//! \param %sServerCmd Name of command function on server
//! \param %param Optional parameter to pass to server. Contains any extra
//! necessary information
//! \param %btn Optional parameter. If a valid object then temporarily selected
////////////////////////////////////////////////////////////////////////////////
function csExecuteCmdBtn(%sServerCmd, %param, %btn)
{
   if(isObject(%btn)) {
      %tgt = getSelectedObject(0);
      if(!isObject(%tgt)) {
         return;
      }
      
      %btnText = csGetCmdBtnText(%tgt, %btn.btnIndex);
      %btn.selected     = true;
      %btnText.Visible  = false;
      %btn.tempSelected = true;
      %param = %param SPC %btn.btnIndex;
   }
      
   // Notify server of command
   commandToServer(%sServerCmd, %param);
}

////////////////////////////////////////////////////////////////////////////////
//! Sends a command to the server with the selected target after a command 
//! button has been pressed
//! \param %sServerCmd Name of command function on server
//! \param %param Optional parameter information to pass to server. Contains any 
//! extra necessary information that the server may need
//! \param %clCmd Optional parameter. Use if you wish the server to call a 
//! method back on the client after command has been executed
//! \param %btn Optional parameter. If a valid object then temporarily selected
////////////////////////////////////////////////////////////////////////////////
function csExecuteCmdBtnOnTarget(%sServerCmd, %param, %clCmd, %btn)
{
   %tgt = getSelectedObject(0);
   if(!isObject(%tgt)) {
      return;
   }
   
   if(isObject(%btn)) {
      %btnText = csGetCmdBtnText(%tgt, %btn.btnIndex);
      %btn.selected     = true;
      %btnText.Visible  = false;
      %btn.tempSelected = true;
      %param = %param SPC %btn.btnIndex;
   }
   
   // Notify server of command
   commandToServer(%sServerCmd, ServerConnection.getGhostID(%tgt), %param, %clCmd);
}
//------------------------------------------------------------------------------

//-Button Update Methods--------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
//! Used for gunslinger recruit command buttons. Button updated when a previous
//! gunslinger has died.
//! \param %cmdData Name of command data data block
////////////////////////////////////////////////////////////////////////////////
function csUpdateRecruitSlingerCmdBtn(%cmdData)
{
   %obj = getSelectedObject(0);
   %btn = %cmdData.getCurrentButton();
   
   %recruitee = %obj.recruitedSlinger[%btn.btnIndex];
   
   // Early catch
   if(%recruitee $= "") {
      return;
   }
   
   // If the gunslinger doesn't exist then
   if(isObject(%recruitee) == false) {
      // notify server that information has changed
      %ghostID = ServerConnection.getGhostID(%obj);
      commandToServer('ClearGunslinger', %ghostID, %btn.btnIndex);
      
      // Reset field and choose a new command
      %obj.recruitedSlinger[%btn.btnIndex] = "";
      %cmpCmd = slgQueryInterface(%obj, $CID_COMMAND);
      if(isObject(%cmpCmd)) {
         %cmpCmd.chooseCommands(%btn);
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Used for deputy recruit command buttons. Button is enabled until a maximum
//! amount of deputies have been recruited
//! \retval bool True if button should be enabled, false otherwise
////////////////////////////////////////////////////////////////////////////////
function csIsRecruitDeputyCmdBtnEnabled()
{
   %obj = getSelectedObject(0);
   for(%i = 0; %i < $CS_MAXDEPUTIES; %i++) {
      // No deputy stored
      if(%obj.recruitedDeputy[%i] $= "") {
         return true;
      }
      
      // Check if deputy is alive
      if(!isObject(%obj.recruitedDeputy[%i])) {
         // notify server that information has changed
         %ghostID = ServerConnection.getGhostID(%obj);
         commandToServer('ClearDeputy', %ghostID, %i);

         %obj.recruitedDeputy[%i] = "";
         return true;
      }
   }
   
   // All deputies are alive
   return false;
}

////////////////////////////////////////////////////////////////////////////////
//! Used for sheriff recruit command buttons. Button is enabled when there are
//! no sheriffs alive
//! \param %cmdData Command Data datablock for sheriff recruit
//! \retval bool True if button should be enabled, false otherwise
////////////////////////////////////////////////////////////////////////////////
function csIsRecruitSheriffCmdBtnEnabled(%cmdData)
{
   // Get command component datablock
   %obj = getSelectedObject(0);
   %cmpCmd = slgQueryInterface(%obj, $CID_COMMAND);
   if(!isObject(%cmpCmd)) {
      return true;
   }
   %cmpData = %cmpCmd.getDataBlock();
   
   // Early catch
   if(%cmpData.recruitedSheriff $= "") {
      return true;
   }
   
   // Check for sheriff existence
   if(!isObject(%cmpData.recruitedSheriff)) {
      // notify server that information has changed
      %ghostID = ServerConnection.getGhostID(%obj);
      commandToServer('ClearSheriff', %ghostID);

      %cmpData.recruitedSheriff = "";
      return true;
   }
   
   // Checking tough sheriff button
   if(%cmdData.btnSelector $= "toughsheriff") {
      // Tough sheriff recruited, button enabled
      if(%cmpData.recruitedSheriff.isOfType("Toughsheriff")) {
         return true;
      }
      // Weak sheriff recruited, button disabled
      else {
         return false;
      }
   }
   // Checking weak sheriff button
   else {
      // Tough sheriff recruited, button disabled
      if(%cmpData.recruitedSheriff.isOfType("Toughsheriff")) {
         return false;
      }
      // Weak sheriff recruite, buton enabled
      else {
         return true;
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Tests whether a resource requirement has been met
//! \param %rsrc Resource to test
//! \param %amnt Amount of resource for which to test
//! \retval bool True if the resource amount is available, false otherwise
////////////////////////////////////////////////////////////////////////////////
function csReqResource(%rsrc, %amnt)
{
   return (rsGetResourceCount(%rsrc) >= %amnt);
}

////////////////////////////////////////////////////////////////////////////////
//! Tests whether an upgrade requirement has been met
//! \param %upgrade Upgrade for which to test for availability
//! \retval bool True if the upgrade is available for purchase, false otherwise
////////////////////////////////////////////////////////////////////////////////
function csReqUpgradeAvail(%upgrade)
{
   return (!csIsCmdUpgradePurchasedLocal(%upgrade));
}

////////////////////////////////////////////////////////////////////////////////
//! Tests whether a button has an associated timer
//! \param %cmdData Command data that populated button
//! \retval bool True if the button has no timer
////////////////////////////////////////////////////////////////////////////////
function csReqNoTimer(%cmdData)
{
   return (%cmdData.getCurrentButton().bmpTimer == 0);
}

////////////////////////////////////////////////////////////////////////////////
//! Tests whether an item is available to be used
//! \param %item Item to be used
//! \retval bool True if there is an item to use
////////////////////////////////////////////////////////////////////////////////
function csReqToolAvailable(%item)
{
   %slot = invGetSlotForItem(ServerConnection.getId(), %item);
   if(%slot == -1) {
      return false;
   }
   return invCanPopItem(ServerConnection.getId(), %slot);
}

// tests if the object can be destroyed (in particular, if a character
// is on a bridge, the bridge cannot be destroyed)
function csReqBridgeDestroy()
{
   // get the selected object (if no object is selected, do nothing)
   %selected = getSelectedObject(0);
   if (isObject(%selected) == false)
   {
      return true;
   }
   
   // check if the object is a bridge (if not, do nothing)
   if (%selected.isLinkObj() == false)
   {
      return true;
   }
   
   // check if there are any characters on the bridge (if so, do
   // not allow the bridge to be destroyed)
   return %selected.canDemolish();
}

////////////////////////////////////////////////////////////////////////////////
//! Tests whether the currently selected object has employees
//! \retval bool True if object has employees
////////////////////////////////////////////////////////////////////////////////
function csReqHasEmployee()
{
   %sel = getSelectedObject(0);
   if(!isObject(%sel)) {
      return false;
   }
   
   return (%sel.hasEmployees());
}

////////////////////////////////////////////////////////////////////////////////
//! Tests whether the currently selected object can be employed or not
//! \param %bEmploy True if testing for employment, false otherwise
//! \retval bool True if object employ state matches query
////////////////////////////////////////////////////////////////////////////////
function csReqEmploy(%bEmploy)
{
   return (slgIsEmployed(getSelectedObject(0)) == %bEmploy);
}

////////////////////////////////////////////////////////////////////////////////
//! Tests if the currently selected object is protesting about their home or not
//! \retval bool True if object is not protesting, false if object is protesting
////////////////////////////////////////////////////////////////////////////////
function csReqNotProtestHome()
{
   %obj = getSelectedObject(0);
   if(!isObject(%obj)) {
      return true;
   }
   
   %cmpChar = slgQueryInterface(%obj, $CID_CHARACTER);
   if(!isObject(%obj)) {
      return true;
   }
   
   return (!%cmpChar.inState($CharacterState::HomeProtest));
}

////////////////////////////////////////////////////////////////////////////////
//! Tests whether or not a given object type exists
//! \param %type Type of object to test for
//! \param %number Number of objects necessary
//! \retval bool True if object type of number exists
////////////////////////////////////////////////////////////////////////////////
function csReqBldgExists(%type, %number)
{
   // Get building list
   %bldgs = slgGetClientBuildingList();
   if(!isObject(%bldgs)) {
      return false;
   }
   
   %cnt = 0;
   %size = %bldgs.getSize();
   for(%i = 0; %i < %size; %i++) {
      // Object must exist
      %bldg = %bldgs.getID(%i);
      if(!isObject(%bldg)) {
         continue;
      }
      
      // Must be of type
      if(!%bldg.isOfType(%type)) {
         continue;
      }
      
      // Must be on player team
      if(!%bldg.isOnTeam($OST_PLAYER)) {
         continue;
      }
      
      // Must be in the production state
      %cmpBldg = slgQueryInterface(%bldg, $CID_BUILDING);
      if(!isObject(%cmpBldg)) {
         continue;
      }
      if(%cmpBldg.getState() != $BuildingState::Production) {
         continue;
      }
      
      // Building needs employees
      if(%cmpBldg.getEmployeeCount() <= 0 && %cmpBldg.getEmployeeMax() > 0) {
         continue;
      }
      
      // Increment count
      %cnt++;
      if(%cnt >= %number) {
         return true;
      }
   }
   
   // Default is false
   return false;
}

////////////////////////////////////////////////////////////////////////////////
//! Tests if we've reached the max amount of items on the stack
//! \param %item Item to test
//! \retval True if item can be added to the stack
////////////////////////////////////////////////////////////////////////////////
function csReqCanPushItem(%item)
{
   %slot = invGetSlotForItem(ServerConnection.getId(), %item);
   return invCanPushItem(ServerConnection.getId(), %slot);
}

////////////////////////////////////////////////////////////////////////////////
//! Tests if the selected object is in the process of building
//! \retval True if not building
////////////////////////////////////////////////////////////////////////////////
function csReqNoBuild()
{
   %cmpChar = slgQueryInterface(getSelectedObject(0), $CID_CHARACTER);
   if(!isObject(%cmpChar)) {
      return true;
   }
   return !%cmpChar.inState($CharacterState::Build);
}

////////////////////////////////////////////////////////////////////////////////
//! Updates performed on the text associated with a use tool command button
//! \param %text Text to update
//! \param %item Tool item type
////////////////////////////////////////////////////////////////////////////////
function csUpdateToolText(%text, %item)
{
   %conn = ServerConnection.getId();
   %text.stateUp = invGetItemStackCount(%conn, invGetSlotForItem(%conn, %item));
}

////////////////////////////////////////////////////////////////////////////////
//! Updates the bitmap timer for the selected object by placing it on the button
//! \param %cmdData Datablock that is affecting button
////////////////////////////////////////////////////////////////////////////////
function csUpdateBmpTimer(%cmdData)
{
   %tgt = getSelectedObject(0);
   if(!isObject(%tgt)) {
      return;
   }
   
   // Early catch
   if(%tgt.prodBmpTimer $= "") {
      return;
   }
   
   if(isObject(%tgt.prodBmpTimer)) {
      if(%cmdData.getCurrentButton().bmpTimer != %tgt.prodBmpTimer) {
         %cmdData.getCurrentButton().bmpTimer = %tgt.prodBmpTimer;
      }
   }
   else {
      %tgt.prodBmpTimer = "";
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Updates the parade bitmap timer for the selected object by placing it on the
//! button
//! \param %cmdData Datablock that is affecting button
////////////////////////////////////////////////////////////////////////////////
function csUpdateParadeBmpTimer(%cmdData)
{
   %tgt = getSelectedObject(0);
   if(!isObject(%tgt)) {
      return;
   }
   
   // Early catch
   if(%tgt.paradeBmpTimer $= "") {
      return;
   }
   
   if(isObject(%tgt.paradeBmpTimer)) {
      if(%cmdData.getCurrentButton().bmpTimer != %tgt.paradeBmpTimer) {
         %cmdData.getCurrentButton().bmpTimer = %tgt.paradeBmpTimer;
      }
   }
   else {
      %tgt.paradeBmpTimer = "";
   }
}
//------------------------------------------------------------------------------

//-Server Command Replies-------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
//! Ties the object recruited to the command datablock that issued order
//! \param %recruiter Ghost id of object that recruited
//! \param %recruitee Ghost id of object recruited
//! \param %index Index for button that issued command
////////////////////////////////////////////////////////////////////////////////
function clientCmdOnSlingerRecruitCmdBtn(%recruiter, %recruitee, %index)
{
   // Get client objects
   %clRecruiter = ServerConnection.resolveGhostID(%recruiter);
   %clRecruitee = ServerConnection.resolveGhostID(%recruitee);
   if(!isObject(%clRecruitee) || !isObject(%clRecruiter)) {
      return;
   }
   
   // Notify server that slinger save information has changed
   commandToServer('RecruitGunslinger', %recruiter, %index, %recruitee);
   
   // Tie object recruited to object that issued command
   %clRecruiter.recruitedSlinger[%index] = %clRecruitee;
   
   // Reset temporary selection
   %btn = csGetCmdBtn(%clRecruiter, %index);
   %btn.tempSelected = false;
}

////////////////////////////////////////////////////////////////////////////////
//! Ties the object recruited to the command datablock that issued order
//! \param %recruiter Ghost id of object that recruited
//! \param %recruitee Ghost id of object recruited
//! \param %index Index for button that issued command
////////////////////////////////////////////////////////////////////////////////
function clientCmdOnDeputyRecruitCmdBtn(%recruiter, %recruitee, %index)
{
   // Get client objects
   %clRecruiter = ServerConnection.resolveGhostID(%recruiter);
   %clRecruitee = ServerConnection.resolveGhostID(%recruitee);
   if(!isObject(%clRecruitee) || !isObject(%clRecruiter)) {
      return;
   }
   
   %btn = csGetCmdBtn(%clRecruiter, %index);
   %btn.tempSelected = false;
   
   // Tie object recruited to object that issued command
   for(%i = 0; %i < $CS_MAXDEPUTIES; %i++) {
      if(%clRecruiter.recruitedDeputy[%i] $= "") {
         // notify server that slinger save information has changed
         %ghostIDer = ServerConnection.getGhostID(%clRecruiter);
         %ghostIDee = ServerConnection.getGhostID(%clRecruitee);
         commandToServer('RecruitDeputy', %ghostIDer, %i, %ghostIDee);
   
         %clRecruiter.recruitedDeputy[%i] = %clRecruitee;
         return;
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Ties the object recruited to the command datablock that issued order
//! \param %recruiter Ghost id of object that recruited
//! \param %recruitee Ghost id of object recruited
//! \param %index Index for button that issued command
////////////////////////////////////////////////////////////////////////////////
function clientCmdOnSheriffRecruitCmdBtn(%recruiter, %recruitee, %index)
{
    // Get client objects
   %clRecruiter = ServerConnection.resolveGhostID(%recruiter);
   %clRecruitee = ServerConnection.resolveGhostID(%recruitee);
   if(!isObject(%clRecruitee) || !isObject(%clRecruiter)) {
      return;
   }
   
   // Tie object recruited to object that issued command
   %clCmpCmd = slgQueryInterface(%clRecruiter, $CID_COMMAND);
   if(isObject(%clCmpCmd)) {
      %clCmpCmd.getDataBlock().recruitedSheriff = %clRecruitee;
   }
   
   // Reset temporary selection of button
   %btn = csGetCmdBtn(%clRecruiter, %index);
   %btn.tempSelected = false;
}

////////////////////////////////////////////////////////////////////////////////
//! Called when tax is set on the server
//! \param %cmpGhost Ghost id of component that received tax change
//! \param %taxlevel New tax level for building component
//! \param %currenttax Integer amount of tax for tax level
////////////////////////////////////////////////////////////////////////////////
function clientCmdOnTaxSet(%cmpGhost, %taxlevel, %currenttax)
{
   // Resolve ghost
   %cmpBldg = ServerConnection.resolveGhostID(%cmpGhost);
   if(!isObject(%cmpBldg)) {
      return;
   }
   
   // Store tax level in object
   %cmpBldg.taxLevel = %taxlevel;
   %cmpBldg.currentTax = %currenttax;
   
   // Update panel if selected
   %object = slgGetAttachedObjId(%cmpBldg);
   if(isSelected(%object)) {
      csUpdateBldgSelectionPanelPU(%cmpBldg);
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Call to create the house bitmap timer on the client
//! \param %cmpGhost Ghost of building component that will hold timer
//! \param %time Total time for timer (timer's time dynamically reset in 
//! building update)
//! \param %elapsedTime Elapsed time for timer (used during load creation)
////////////////////////////////////////////////////////////////////////////////
function clientCmdCreateHouseBmpTimer(%cmpGhost, %time, %elapsedTime, %count)
{
   // Resolve ghost
   %cmpBldg = ServerConnection.resolveGhostID(%cmpGhost);
   if(!isObject(%cmpBldg)) {
      return;
   }

   // Just in case check count
   %max = %cmpBldg.getTenantMax();
   if(%count >= %max) {
      return;
   }
   
   // Building already has timer??
   if(isObject(%cmpBldg.houseTimer)) {
      echo("!!House Bitmap Timer Create: Building already has timer!!");
      return;
   }
   
   // Get button to assign timer to
   %btn = "EHIcon" @ %count;
   if(!isObject(%btn)) {
      return;
   }
   
   // Create bitmap timer
   %cmpBldg.houseTimer = csCreateBmpTimer(%btn, $UnhousedIcon, %time);
   if(!isObject(%cmpBldg.houseTimer)) {
      return;
   }
   
   // Notify us when finished
   %cmpBldg.houseTimer.notifyOnFire("onHouseBmpTimerEnd", %cmpBldg);
   if(%elapsedTime > 0) {
      %cmpBldg.houseTimer.setElapsedTime(%elapsedTime);
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Call to destroy the bitmap timer prematurely on the client
//! \param %cmpGhost Ghost of building component that has timer
////////////////////////////////////////////////////////////////////////////////
function clientCmdDestroyHouseBmpTimer(%cmpGhost)
{
   // Resolve ghost
   %cmpBldg = ServerConnection.resolveGhostID(%cmpGhost);
   if(!isObject(%cmpBldg)) {
      return;
   }
   
   // Clear timer
   if(!isObject(%cmpBldg.houseTimer)) {
      return;
   }
   
   // Destroy timer
   %cmpBldg.houseTimer.delete();
   %cmpBldg.houseTimer = 0;
}

////////////////////////////////////////////////////////////////////////////////
//! Call to update the bitmap timer with a new time
//! \param %cmpGhost Ghost of building component that has timer
//! \param %time total time of the timer
////////////////////////////////////////////////////////////////////////////////
function clientCmdUpdateHouseBmpTimer(%cmpGhost, %time, %count)
{
   // Resolve ghost
   %cmpBldg = ServerConnection.resolveGhostID(%cmpGhost);
   if(!isObject(%cmpBldg)) {
      return;
   }
   
   // check if the timer has been created
   if(!isObject(%cmpBldg.houseTimer)) {
      return;
   }
   
   // update the timer
   %cmpBldg.houseTimer.setName("EHIcon" @ %count);
   %cmpBldg.houseTimer.time = %time;
}

////////////////////////////////////////////////////////////////////////////////
//! Used to notify the client if a command has failed or not
//! \param %index Index of button
//! \param %success True if command succeeded
////////////////////////////////////////////////////////////////////////////////
function clientCmdCmdBtnStatus(%index, %sucess)
{
   // Get commanding object
   %commander = getSelectedObject(0);
   
   // Get button that issued command
   %btn = csGetCmdBtn(%commander, %index);
   
   // Release temporary selection
   %btn.tempSelected = false;
}
//------------------------------------------------------------------------------

// End client_cmdhud.cs


// LOADING GUNSLINGER DATA
function clientCmdRecruitGunslinger(%ghostIDer, %index, %ghostIDee)
{
   %object = ServerConnection.resolveGhostID(%ghostIDer);
   %target = ServerConnection.resolveGhostID(%ghostIDee);
   %object.recruitedSlinger[%index] = %target;
}

// LOADING DEPUTY DATA
function clientCmdRecruitDeputy(%ghostIDer, %index, %ghostIDee)
{
   %object = ServerConnection.resolveGhostID(%ghostIDer);
   %target = ServerConnection.resolveGhostID(%ghostIDee);
   %object.recruitedDeputy[%index] = %target;
}
