///////////////////////////////////////////////////////////////////////////////
// npcact_p_trans - NPC ACTIVITIES 6.0 Professions - Transporter
// By Deva Bryson Winblood.  09/12/2004
// Last Modified By: Deva Bryson Winblood. 02/02/2005
//-----------------------------------------------------------------------------
// This profession carries goods from one location to another
///////////////////////////////////////////////////////////////////////////////
#include "npcact_h_prof"
#include "npcact_h_money"
/////////////////////////////
// PROTOTYPES
/////////////////////////////


// PURPOSE: check to see if oMe requires a pack animal.  If it does require
// a pack animal and it does not have one it will return 0.  If it has one it
// will return 1.  If it returns -1 then that means it does not need one.
int fnProfCheckForPackAnimal(object oMe=OBJECT_SELF);

// PURPOSE: calls the follow the master function for the pack animal
void fnFollowMaster(object oMaster);

// PURPOSE: To check for droppable items marked as transported and drop them
// it returns TRUE if an item was dropped
int fnProfDropItems(object oMe=OBJECT_SELF);

// PURPOSE: To pickup items for transport
void fnProfPickupItems(object oMe=OBJECT_SELF);

///////////////////////////////////////////////////////////////////////// MAIN
void main()
{
   object oMe=OBJECT_SELF;
   object oOb;
   string sS;
   int nN;
   int nState=GetLocalInt(oMe,"nProfState");
   int nSpeed=GetLocalInt(oMe,"nGNBStateSpeed");
   int nCurrency=GetLocalInt(oMe,"nCurrency");
   if (nSpeed<1) nSpeed=6;
   if (GetObjectType(oMe)==OBJECT_TYPE_CREATURE)
   { // is a creature
     SetLocalInt(oMe,"nGNBProfessions",TRUE);
     SetLocalInt(oMe,"nGNBProfFail",nSpeed+3);
     SetLocalInt(oMe,"nGNBProfProc",1);
     switch(nState)
     { // main transporter state
       case 0: { // check for pack animal
         nN=fnProfCheckForPackAnimal(oMe);
         if (nN==1||nN==-1) { SetLocalInt(oMe,"nProfState",4); }
         else {
          sS=GetLocalString(oMe,"sProfTXSayNeedPackAnimal");
          if (GetStringLength(sS)>0) AssignCommand(oMe,SpeakString(sS));
          SetLocalInt(oMe,"nProfState",1);
         }
         break;
       } // check for pack animal
       case 1: { // Go to get pack animal location
         sS=GetLocalString(oMe,"sProfTXGetPackAnimal");
         if (GetStringLength(sS)>0)
         { // location info entered
           oOb=GetNearestObjectByTag(sS,oMe,1);
           if (GetIsObjectValid(oOb)==FALSE) oOb=GetObjectByTag(sS);
           if (GetIsObjectValid(oOb))
           { // valid destination
             if (GetArea(oMe)!=GetArea(oOb)||GetDistanceBetween(oMe,oOb)>2.5)
             { // move to destination
               fnMoveToDestination(oMe,oOb);
             } // move to destination
             else { SetLocalInt(oMe,"nState",2); }
           } // valid destination
           else { // error
             AssignCommand(oMe,SpeakString("ERROR: I cannot find destination '"+sS+"' in variable sProfTXGetPackAnimal!"));
             SetLocalInt(oMe,"nProfState",2);
           } // error
         } // location info entered
         else { SetLocalInt(oMe,"nProfState",2); }
         break;
       } // go to get pack animal location
       case 2: { // pay for pack animal
         if (GetLocalInt(oMe,"nProfTXPackAnimalCost")>0)
         { // Pack Animal costs
           nN=GetLocalInt(oMe,"nProfTXPackAnimalCost");
           if (GetWealth(oMe,nCurrency)>=nN)
           { // have enough gold
             sS=GetLocalString(oMe,"sProfTXPayForPackAnimal");
             if (GetStringLength(sS)>0)
             { // person to pay specified
               oOb=GetNearestObjectByTag(sS,oMe,1);
               if (GetIsObjectValid(oOb)==FALSE) oOb=GetObjectByTag(sS);
               if (GetIsObjectValid(oOb))
               { // person found
                 AssignCommand(oOb,TakeCoins(oMe,nN,"ANY",nCurrency));
                 SetLocalInt(oMe,"nProfState",3);
               } // person found
               else
               { // error
                 AssignCommand(oMe,SpeakString("ERROR: The object with tag '"+sS+"' does not exist as defined on sProfTXPayForPackAnimal."));
                 SetLocalInt(oMe,"nProfState",3);
                 AssignCommand(oMe,TakeCoins(oMe,nN,"ANY",nCurrency,TRUE));
               } // error
             } // person to pay specified
             else
             { // no specific target
               AssignCommand(oMe,TakeCoins(oMe,nN,"ANY",nCurrency,TRUE));
               SetLocalInt(oMe,"nProfState",3);
             } // no specific target
           } // have enough gold
           else
           { // not enough gold
             nN=d4();
             if (nN<3) AssignCommand(oMe,SpeakString("I can nah work.  I have no gold for a pack animal."));
             else { AssignCommand(oMe,SpeakString("I need more gold for a pack animal."));   }
             SetLocalInt(oMe,"nProfState",15);
           } // not enough gold
         } // Pack animal costs
         else { SetLocalInt(oMe,"nProfState",3); }
         break;
       } // pay for pack animal
       case 3: { // create pack animal
         sS=GetLocalString(oMe,"sProfTXPackAnimalRes");
         if (GetStringLength(sS)>0)
         { // res ref exists
           oOb=CreateObject(OBJECT_TYPE_CREATURE,sS,GetLocation(oMe));
           if (GetIsObjectValid(oOb))
           { // pack animal created
             SetLocalObject(oMe,"oProfTXPackAnimal",oOb);
             AssignCommand(oOb,fnFollowMaster(oMe));
             SetLocalInt(oMe,"nProfState",4);
             sS=GetLocalString(oMe,"sProfTXSayGetPackAnimal");
             if (GetStringLength(sS)>0) AssignCommand(oMe,SpeakString(sS));
           } // pack animal created
           else
           { // error
             AssignCommand(oMe,SpeakString("ERROR: Pack animal was not created with ResRef '"+sS+"' on variable sProfTXPackAnimalRes."));
             SetLocalInt(oMe,"nProfState",15);
           } // error
         } // res ref exists
         else
         { // error
           AssignCommand(oMe,SpeakString("ERROR: The sProfTXPackAnimalRes variable is NOT defined.  It requires a value to create a pack animal."));
           SetLocalInt(oMe,"nProfState",15);
         } // error
         break;
       } // create pack animal
       case 4: { // go to transport location 1
         sS=GetLocalString(oMe,"sProfTXLocation1");
         if (GetStringLength(sS)>0)
         { // location specified
           oOb=GetNearestObjectByTag(sS,oMe,1);
           if (GetIsObjectValid(oOb)==FALSE) oOb=GetObjectByTag(sS);
           if (GetIsObjectValid(oOb))
           { // valid destination
             if (GetArea(oMe)!=GetArea(oOb)||GetDistanceBetween(oMe,oOb)>2.5)
             { // move
               fnMoveToDestination(oMe,oOb);
             } // move
             else
             { // arrived
               SetLocalInt(oMe,"nProfState",5);
             } // arrived
           } // valid destination
           else
           { // error
             AssignCommand(oMe,SpeakString("ERROR: I cannot find '"+sS+"' as specified in sProfTXLocation1!"));
             SetLocalInt(oMe,"nProfState",15);
           } // error
         } // location specified
         else
         { // error
           AssignCommand(oMe,SpeakString("ERROR: sProfTXLocation1 MUST be defined for the Transport profession."));
           SetLocalInt(oMe,"nProfState",15);
         } // error
         break;
       } // go to transport location 1
       case 5: { // if carrying items for transport drop them off
         nN=fnProfDropItems(oMe);
         if (nN==TRUE)
         { // items were dropped
           sS=GetLocalString(oMe,"sProfTXSayDeliver");
           if (GetStringLength(sS)>0) AssignCommand(oMe,SpeakString(sS));
           nN=GetLocalInt(oMe,"nProfTXWagePerDelivery");
           if (nN>0)
           { // award wage
             GiveCoins(oMe,nN,"ANY",nCurrency);
           } // award wage
         } // items were dropped
         SetLocalInt(oMe,"nProfState",6);
         break;
       } // if carrying items for transport drop them off
       case 6: { // check for pack animal
         nN=fnProfCheckForPackAnimal(oMe);
         if (nN==1||nN==-1) { SetLocalInt(oMe,"nProfState",7); }
         else {
          sS=GetLocalString(oMe,"sProfTXSayNeedPackAnimal");
          if (GetStringLength(sS)>0) AssignCommand(oMe,SpeakString(sS));
          SetLocalInt(oMe,"nProfState",1);
         }
         break;
       } // check for pack animal
       case 7: { // pickup items for transport
         fnProfPickupItems(oMe);
         if (GetLocalInt(oMe,"nPickup")>0)
         { SetLocalInt(oMe,"nProfState",16); }
         else { SetLocalInt(oMe,"nProfState",8); }
         break;
       } // pickup items for transport
       case 8: { // go to transport location 2
         sS=GetLocalString(oMe,"sProfTXLocation2");
         if (GetStringLength(sS)>0)
         { // location specified
           oOb=GetNearestObjectByTag(sS,oMe,1);
           if (GetIsObjectValid(oOb)==FALSE) oOb=GetObjectByTag(sS);
           if (GetIsObjectValid(oOb))
           { // valid destination
             if (GetArea(oMe)!=GetArea(oOb)||GetDistanceBetween(oMe,oOb)>2.5)
             { // move
               fnMoveToDestination(oMe,oOb);
             } // move
             else
             { // arrived
               SetLocalInt(oMe,"nProfState",9);
             } // arrived
           } // valid destination
           else
           { // error
             AssignCommand(oMe,SpeakString("ERROR: I cannot find '"+sS+"' as specified in sProfTXLocation2!"));
             SetLocalInt(oMe,"nProfState",15);
           } // error
         } // location specified
         else
         { // error
           AssignCommand(oMe,SpeakString("ERROR: sProfTXLocation2 MUST be defined for the Transport profession."));
           SetLocalInt(oMe,"nProfState",15);
         } // erro
         break;
       } // go to transport location 2
       case 9: { // if carrying items for transport drop them off
         nN=fnProfDropItems(oMe);
         if (nN==TRUE)
         { // items were dropped
           sS=GetLocalString(oMe,"sProfTXSayDeliver");
           if (GetStringLength(sS)>0) AssignCommand(oMe,SpeakString(sS));
           nN=GetLocalInt(oMe,"nProfTXWagePerDelivery");
           if (nN>0)
           { // award wage
             GiveGoldToCreature(oMe,nN);
           } // award wage
         } // items were dropped
         SetLocalInt(oMe,"nProfState",10);
         break;
       } // if carrying items for transport drop them off
       case 10: { // check for pack animal
         nN=fnProfCheckForPackAnimal(oMe);
         if (nN==1||nN==-1) { SetLocalInt(oMe,"nProfState",11); }
         else {
          sS=GetLocalString(oMe,"sProfTXSayNeedPackAnimal");
          if (GetStringLength(sS)>0) AssignCommand(oMe,SpeakString(sS));
          SetLocalInt(oMe,"nProfState",1);
         }
         break;
       } // check fo pack animal
       case 11: { // check for end of shift
         nN=GetLocalInt(oMe,"nProfTXShift");
         if (nN<GetLocalInt(oMe,"nProfTXNumDeliveries"))
         { // still more to do
           SetLocalInt(oMe,"nProfState",12);
           SetLocalInt(oMe,"nProfTXShift",nN+1);
         } // still more to do
         else { if (fnProfCheckForPackAnimal(oMe)==1)
                   SetLocalInt(oMe,"nProfState",13);
                else { SetLocalInt(oMe,"nProfState",15); }
         }
         break;
       } // check for end of shift
       case 12: { // pickup items for transport
         fnProfPickupItems(oMe);
         if (GetLocalInt(oMe,"nPickup")>0)
         { SetLocalInt(oMe,"nProfState",17); }
         else { SetLocalInt(oMe,"nProfState",4); }
         break;
       } // pickup items for transport
       case 13: { // Go to Pack animal return location
         sS=GetLocalString(oMe,"sProfTXReturnPackAnimal");
         if (GetStringLength(sS)>0)
         { // return location specified
           oOb=GetNearestObjectByTag(sS,oMe,1);
           if (GetIsObjectValid(oOb)==FALSE) oOb=GetObjectByTag(sS);
           if (GetIsObjectValid(oOb))
           { // valid destination
             if (GetArea(oMe)!=GetArea(oOb)||GetDistanceBetween(oMe,oOb)>2.5)
             { // move
               fnMoveToDestination(oMe,oOb);
             } // move
             else
             { // arrived
               SetLocalInt(oMe,"nProfState",14);
             } // arrived
           } // valid destination
           else
           { // error
             AssignCommand(oMe,SpeakString("ERROR: I cannot find '"+sS+"' as specified in sProfTXReturnPackAnimal!"));
             SetLocalInt(oMe,"nProfState",14);
           } // error
         } // return location specified
         else { SetLocalInt(oMe,"nProfState",14); }
         break;
       } // Go to Pack Animal return location
       case 14: { // return pack animal
         sS=GetLocalString(oMe,"sProfTXSayReturnPackAnimal");
         if (GetStringLength(sS)>0) { AssignCommand(oMe,SpeakString(sS)); }
         oOb=GetLocalObject(oMe,"oProfTXPackAnimal");
         DelayCommand(3.0,DestroyObject(oOb));
         SetLocalInt(oMe,"nProfState",15);
         break;
       } // return pack animal
       case 15: { // end shift and cleanup
         DeleteLocalInt(oMe,"nProfState");
         DeleteLocalInt(oMe,"nPickup");
         DeleteLocalInt(oMe,"nProfTXShift");
         nN=GetLocalInt(oMe,"nProfTXWage");
         if (nN>0)
         { // pay wage
           GiveGoldToCreature(oMe,nN);
           SetLocalInt(oMe,"nGNBProfessions",FALSE);
         } // pay wage
         break;
       } // end shift and cleanup
       case 16: { // wait state
         sS=GetLocalString(oMe,"sProfTXSayTransport");
         if (GetLocalInt(oMe,"nPickup")<1) {
           SetLocalInt(oMe,"nProfState",8);
           if (GetStringLength(sS)>0) AssignCommand(oMe,SpeakString(sS));
         }
         break;
       } // wait state
       case 17: { // wait state
         sS=GetLocalString(oMe,"sProfTXSayTransport");
         if (GetLocalInt(oMe,"nPickup")<1) {
           SetLocalInt(oMe,"nProfState",4);
           if (GetStringLength(sS)>0) AssignCommand(oMe,SpeakString(sS));
         }
         break;
       } // wait state
       default: { SetLocalInt(oMe,"nProfState",0); break; }
     } // main transporter state
     if (nState!=15) { DelayCommand(IntToFloat(nSpeed),ExecuteScript("npcact_p_trans",oMe)); }
   } // is a creature
}
///////////////////////////////////////////////////////////////////////// MAIN

/////////////////////////////
// FUNCTIONS
/////////////////////////////

void fnPickItUp(object oItem)
{ // PURPOSE: pickup the item
  int nN;
  if (GetItemPossessor(oItem)!=OBJECT_SELF&&GetObjectType(GetItemPossessor(oItem))!=OBJECT_TYPE_CREATURE)
  { // pick it up
    AssignCommand(OBJECT_SELF,ActionPickUpItem(oItem));
  } // pick it up
  else
  { // picked it up
    nN=GetLocalInt(OBJECT_SELF,"nPickup");
    nN=nN-1;
    SetLocalInt(OBJECT_SELF,"nPickup",nN);
  } // picked it up
} // fnPickItUp()

int fnProfItemRestriction(object oItem)
{ // PURPOSE: return TRUE if this item is on the restriction list
  int bRet=FALSE;
  string sS;
  int nC=1;
  string sTag=GetTag(oItem);
  sS=GetLocalString(OBJECT_SELF,"sProfTXItemRestrict"+IntToString(nC));
  while(GetStringLength(sS)>0&&!bRet)
  { // check for restrictions
    if (sTag==sS) bRet=TRUE;
    nC++;
    sS=GetLocalString(OBJECT_SELF,"sProfTXItemRestrict"+IntToString(nC));
  } // check for restrictions
  return bRet;
} // fnProfItemRestriction()

void fnProfPickupItems(object oMe=OBJECT_SELF)
{ // PURPOSE: To pickup items
  int nC=1;
  int nPickup=0;
  object oItem=GetNearestObject(OBJECT_TYPE_ITEM,oMe,nC);
  while (oItem!=OBJECT_INVALID&&GetDistanceBetween(oMe,oItem)<6.0)
  { // found a pile of items
    if (GetLocalInt(oMe,"bTransported"+GetTag(oMe)+GetName(oMe))!=TRUE)
    { // not an item I have transported before
      if (fnProfItemRestriction(oItem)!=TRUE)
      { // not a restricted item
        nPickup++;
        SetLocalInt(oMe,"nPickup",nPickup);
        DelayCommand(2.0,fnPickItUp(oItem));
      } // not a restricted item
    } // not an item I have transported before
    nC++;
    oItem=GetNearestObject(OBJECT_TYPE_ITEM,oMe,nC);
  } // found a pile of items
} // fnProfPickupItems()

void fnDropIt(object oItem)
{ // PURPOSE: make sure the NPC drops the item
  if (GetItemPossessor(oItem)==OBJECT_SELF)
  { // drop it
    AssignCommand(OBJECT_SELF,ActionPutDownItem(oItem));
    DelayCommand(2.0,fnDropIt(oItem));
  } // drop it
} // fnDropIt()

int fnProfDropItems(object oMe=OBJECT_SELF)
{ // PURPOSE: Drop items
  int bRet=FALSE;
  object oItem=GetFirstItemInInventory(oMe);
  while(oItem!=OBJECT_INVALID)
  { // look at inventory
    if (GetLocalInt(oMe,"bTransported"+GetTag(oMe)+GetName(oMe))==TRUE)
    { // drop this item
      DelayCommand(1.0,fnDropIt(oItem));
      bRet=TRUE;
    } // drop this item
    oItem=GetNextItemInInventory(oMe);
  } // look at inventory
  return bRet;
} // fnProfDropItems()

void fnFollowMaster(object oMaster)
{ // PURPOSE: Pack animal follow
  object oMe=OBJECT_SELF;
  SetAILevel(oMe,AI_LEVEL_NORMAL);
  if (GetIsObjectValid(oMaster))
  { // master is valid
    if (GetArea(oMe)!=GetArea(oMaster))
    { // TELEPORT
      AssignCommand(oMe,JumpToObject(oMaster));
    } // TELEPORT
    else if (GetDistanceBetween(oMe,oMaster)>3.0)
    { // move
      ActionMoveToObject(oMaster,TRUE,2.0);
    } // move
    DelayCommand(5.0,fnFollowMaster(oMaster));
  } // master is valid
  else { DestroyObject(oMe); }
} // fnFollowMaster()



int fnProfCheckForPackAnimal(object oMe=OBJECT_SELF)
{ // PURPOSE: Check for pack animal needs
  // 0 = need one, 1 = have one, -1 = don not need one
  int nRet=-1;
  if(GetLocalInt(oMe,"bProfTXHasPackAnimal")==TRUE)
  { // requires pack animal
    if (GetLocalObject(oMe,"oProfTXPackAnimal")!=OBJECT_INVALID) nRet=1;
    else { nRet=0; }
  } // requires pack animal
  return nRet;
} // fnProfCheckForPackAnimal()