//---------------------------------------------------------------------------
// File: svr_carryover.cs
//
//
// Author: Michael Felice
//---------------------------------------------------------------------------

$CarryForwardCount = 0;
$CarryFowardList = 0;
$CarryBackCount = 0;
$CarryBackList = 0;
$CarryOverIndex = 1;
$LoadCarryBackData = false;


// this determines all objects that should be carried forward from
// the current map to the next map (based on a scenario), when these
// objects are added to the carry forward list, the carry over ids
// are initialized
function GetCarryForwardList(%scenario)
{
   // the citizen list is the list of characters that are citizens
   // and is used for the random citizen carry forward characters
   %citizenList = new SLGameObjList();
   
   // get the characters that exist and find all of the citizens and
   // non-citizen carry forward objects
   %list = slgGetServerCharacterList();
   %count = %list.getSize();
   $CarryForwardCount = 0;
   for (%index = 0; %index < %count; %index++)
   {
      // get the character object
      %object = %list.getID(%index);
      if (isObject(%object) == false)
      {
         continue;
      }
      
      // only player character objects can be carried forward
      if (%object.getTeam() != $OST_PLAYER)
      {
         continue;
      }
      
      // ensure that this is a character object (should never fail)
      %component = slgQueryInterface(%object, $CID_CHARACTER);
      if (isObject(%component) == false)
      {
         continue;
      }
      
      // skip the hero (automatically carries forward)
      %datablock = %component.getDataBlock();
      if (%datablock.isHero == true)
      {
         continue;
      }
      
      // find out if the character is, nice, tough, or neutral
      %nice = %datablock.initHappiness > 0;
      %tough = %datablock.initHappiness < 0;
      %neutral = %datablock.initHappiness == 0;
      
      // if a lawman, check the lawman carry forward
      if (%datablock.canReformDrunk == true)
      {
         if (%scenario.niceLawmen == true && %nice == true ||
            %scenario.toughLawmen == true && %tough == true ||
            %scenario.neutralLawmen == true && %neutral == true)
         {
            AddCarryForwardObject(%object);
         }
         continue;
      }
      
      // if a not a lawman but a combat unit, check the carry forward
      %combat = slgQueryInterface(%object, $CID_COMBAT);
      if (isObject(%combat) == true)
      {
         if (%scenario.niceGunslinger == true && %nice == true ||
            %scenario.toughGunslinger == true && %tough == true ||
            %scenario.neutralGunslinger == true && %neutral == true)
         {
            AddCarryForwardObject(%object);
         }
         continue;
      }
      
      // all other objects are citizens and go in the citizen list
      %citizenList.addObject(%object);
   }

   
   // after the citizens are found, determine which citizens should
   // be carried forward
   if (%scenario.partCitizen > 1) %scenario.partCitizen = 1;
   if (%scenario.partCitizen < 0) %scenario.partCitizen = 0;
   %citizenCount = %scenario.partCitizen * %citizenList.getSize();
   if (%citizenCount < %scenario.minCitizen)
   {
      %citizenCount = %scenario.minCitizen;
      if (%citizenCount > %citizenList.getSize())
      {
         %citizenCount = %citizenList.getSize();
      }
   }
   if (%citizenCount > %scenario.maxCitizen)
   {
      %citizenCount = %scenario.maxCitizen;
   }
   
   // randomly add the citizens to the carry over group
   for (%citizenIndex = 0; %citizenIndex < %citizenCount; %citizenIndex++)
   {
      %count = %citizenList.getSize();
      %index = getRandom(0, %count - 1);
      %object = %citizenList.getID(%index);
      %citizenList.removeObject(%object);
      
      AddCarryForwardObject(%object);
   }
   
   %citizenList.delete();
}

// this function takes all found carry forward objects and places
// them on the map.  it also generates the carry back list based
// on the objects that were placed.  after placement, the carry
// forward list is cleared
function PlaceCarryForwardList()
{
   // find the spawn position for the carry forward objects (randomly
   // pick from a spawn point if one exists)
   %pointCount = slgGetSpawnCount($Point::Scenario);
   %position = "-379.5, -377.5";
   if (%pointCount > 0)
   {
      %index = getRandom(0, %pointCount - 1);
      %point = slgGetSpawnPt($Point::Scenario, %index).position;
      %position = getWord(%point, 0) @ " " @ getWord(%point, 1);
   }
   
   // for every carry forward object, make an object that will
   // replace it
   %posX = getWord(%position, 0);
   %posY = getWord(%position, 1);
   for (%index = 0; %index < $CarryForwardCount; %index++)
   {
      // parse the data that was saved for carrying forward objects
      %info = $CarryFowardList[%index];
      %carryID = getWord(%info, 0);
      %datablock = getWord(%info, 1);
      %health = getWord(%info, 2);
      %amigo = getWord(%info, 3);
      %torqueName = getWord(%info, 4);
      %internalName = getWord(%info, 5);
      %total = getWordCount(%info);
      %name = getWords(%info, 6, %total - 1);
      
      // create the object
      %object = CreateSaveObject(%datablock, "", $OST_PLAYER);
      
      // load the carry forward info
      %object.carryOverID = %carryID;
      %object.name = %name;
      %object.setName(%torqueName);
      %object.setInternalName(%internalName);
      %object.health = %health;
      %object.setPosition(%posX, %posY);
      %object.amigo = %amigo;
      if (%amigo == true)
      {
         %object.removeHat = false;
         %object.mountImage(Sombrero, 0);
      }
      
      // add the carry forward object to the carry back list
      AddCarryBackObject(%carryID, %health);
   }
   
   // clear the carry forward list
   $CarryForwardCount = 0;
}

// this function updates the saved health of all every carry back object
function UpdateCarryBackList()
{
   // loop through all of the carry back objects and update their health
   for (%index = 0; %index < $CarryBackCount; %index++)
   {
      // get the carry back information
      %info = $CarryBackList[%index];
      %carryID = getWord(%info, 0);
      
      // based on the existence and health of this carry back object,
      // set the health to zero or the object's current health
      %object = slgGetCarryObject(%carryID);
      if (isObject(%object) == false)
      {
         $CarryBackList[%index] = %carryID @ " 0";
      }
      else
      {
         $CarryBackList[%index] = %carryID @ " " @ %object.health;
      }
   }
}

// place the carry back objects on the map, looking for the characters
// that were loaded from the map
function PlaceCarryBackList(%scenario)
{
   // do not place carry back objects when moving to a satellite or
   // updating disasters on the current map
   if (%scenario.stack == true)
   {
      return;
   }
   
   // find all carry back objects
   for (%index = 0; %index < $CarryBackCount; %index++)
   {
      // get the carry back information
      %info = $CarryBackList[%index];
      %carryID = getWord(%info, 0);
      %health = getWord(%info, 1);
      
      // if the carry back object could not be found: do nothing
      // (this may need to be updated if we have satellite maps
      // that move into other satellite maps with different
      // carry forward objects-- depends on design, so skipping)
      %object = slgGetCarryObject(%carryID);
      if (isObject(%object) == false)
      {
         continue;
      }
      
      // if the carry back object died, destroy the object
      if (%health <= 0)
      {
         %object.deleteObject();
      }
      // otherwise, update the carry back object's health
      else
      {
         %object.health = %health;
      }
   }
}

function ClearCarryBackList(%scenario)
{
   // do not clear carry back objects when moving to a satellite or
   // updating disasters on the current map
   if (%scenario.stack == true)
   {
      return;
   }
   
   // clear the carry back list
   $CarryBackCount = 0;
}





// this adds a found object to the carry forward list
function AddCarryForwardObject(%object)
{
   // if the carry forward object is already being carried
   // back, that means that is has already been added and
   // should be ignored
   for (%index = 0; %index < $CarryBackCount; %index++)
   {
      %info = $CarryBackList[%index];
      %carryID = getWord(%info, 0);
      
      // if we have a carry over id match, this object has
      // already been carried to this map and is already
      // going to be carried back, so do not add the object
      if (%carryID == %object.carryOverID)
      {
         return;
      }
   }
   
   // check the carry ID, if it does not exist, give the object
   // a carry id
   %carryID = %object.carryOverID;
   if (%carryID == 0)
   {
      %object.carryOverID = $CarryOverIndex;
      %carryID = $CarryOverIndex;
      $CarryOverIndex++;
   }
   
   // get the data that should be saved to carry the object forward
   %datablock = %object.getDatablock().getName();
   %health = %object.health;
   %amigo = %object.amigo;
   %torqueName = %object.getName();
   %internalName = %object.getInternalName;
   %name = %object.name;
   
   // save this information to the carry forward list
   $CarryFowardList[$CarryForwardCount] = %carryID @ " " @
      %datablock @ " " @ %health @ " " @ %amigo @ " " @
      %torqueName @ " " @ %internalName @ " " @ %name;
   $CarryForwardCount++;
}

// this adds a carry back object to the carry back list
function AddCarryBackObject(%carryID, %health)
{
   // if the object is already in the carry back list, do nothing
   for (%index = 0; %index < $CarryBackCount; %index++)
   {
      %info = $CarryBackList[%index];
      %oldCarryID = getWord(%info, 0);
      if (%oldCarryID == %carryID)
      {
         return;
      }
   }
   
   // add the carry back object
   $CarryBackList[$CarryBackCount] = %carryID @ " " @ %health;
   $CarryBackCount++;
}



// this saves carry back information to a file
function CarryScenarioSaveToFile()
{
   // save the carry back data for each character
   slgSaveInt($CarryBackCount);
   for (%index = 0; %index < $CarryBackCount; %index++)
   {
      // save the data
      %info = $CarryBackList[%index];
      %carryID = getWord(%info, 0);
      %health = getWord(%info, 1);
      slgSaveInt(%carryID);
      slgSaveFloat(%health);
   }
}

// this loads carry back information from a file (only if the load
// is forced by the player from a save game, not switching between maps)
function CarryScenarioLoadFromFile()
{
   // only load carry back information when loading through menus
   %count = slgLoadInt();
   if ($LoadCarryBackData == true)
   {
      $CarryBackCount = %count;
   }
   
   // maintain the save file by loading the information, but only
   // save over old information if the player is loading from menus
   for (%index = 0; %index < %count; %index++)
   {
      // load the data
      %carryID = slgLoadInt();
      %health = slgLoadFloat();
      if ($LoadCarryBackData == true)
      {
         $CarryBackList[%index] = %carryID @ " " @ %health;
      }
   }
}
