//::///////////////////////////////////////////////
//:: Name sc_guard_hb
//:: FileName sc_guard_hb.nss
//:: Copyright (c) 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
NPC Guard Heartbeat Script
Tag parameters:
OFF         Guard is an officer (there should not be more than one officer in an area)

    NW_FLAG_HEARTBEAT_EVENT        //OPTIONAL BEHAVIOR - Fire User Defined Event 1001
    NW_FLAG_PERCIEVE_EVENT         //OPTIONAL BEHAVIOR - Fire User Defined Event 1002
    NW_FLAG_ATTACK_EVENT           //OPTIONAL BEHAVIOR - Fire User Defined Event 1005
    NW_FLAG_DAMAGED_EVENT          //OPTIONAL BEHAVIOR - Fire User Defined Event 1006
    NW_FLAG_DISTURBED_EVENT        //OPTIONAL BEHAVIOR - Fire User Defined Event 1008
    NW_FLAG_END_COMBAT_ROUND_EVENT //OPTIONAL BEHAVIOR - Fire User Defined Event 1003
    NW_FLAG_ON_DIALOGUE_EVENT      //OPTIONAL BEHAVIOR - Fire User Defined Event 1004
    NW_FLAG_DEATH_EVENT            //OPTIONAL BEHAVIOR - Fire User Defined Event 1007
*/
//:://////////////////////////////////////////////
//:: Created By: Pad O'Lion
//:: Created On: 07/03/2002
//:://////////////////////////////////////////////

//#include "array_api"
#include "rpo_inc"
#include "NW_I0_GENERIC"
#include "sc_walkwaypoints"

void Init();
void DoIdle();
void DoPatrol();
void DoAle();
void DoRest();
void DoConversation();
void DoTraining();
void DoCombat();
void DoImprison();
void DoPursue();

void Arm(int nArm);
int CheckSchedule();

int GetState();
int GetSubState();
void SetState(int nState);
void SetSubState(int nState);
int GetIsOfficer();
void SetDummyEnemy(object oDummy, int nEnemy);
void DoOfficerTrainingTalk();
void DoRandomAction();

int GetFreePrison();
void LockPrison(int nNum);

void DebugString(string sDebug);

    int NPC_GRD_INIT = 0;    //state when spawned
    int NPC_GRD_IDLE = 1;    //not doing anything atm
    int NPC_GRD_PATROL = 2;  //is patroulling
    int NPC_GRD_TRAINING = 3;        //is training or is getting trained
    int NPC_GRD_ALE = 4;     //is at the tavern
    int NPC_GRD_REST = 5;    //rests
    int NPC_GRD_CONVERSATION = 6;
    int NPC_GRD_COMBAT = 7;
    int NPC_GRD_IMPRISON = 8;
    int NPC_GRD_PURSUE = 9;

    int NPC_GRD_SUB_ONPATROL = 12;
    int NPC_GRD_SUB_ISTRAINING = 13;
    int NPC_GRD_SUB_ISDRINKING = 14;
    int NPC_GRD_SUB_ISRESTING = 15;
    int NPC_GRD_SUB_INCONVERSATION = 16;
    int NPC_GRD_SUB_ISINCOMBAT = 17;
    int NPC_GRD_SUB_ISIMPRISONING = 18;
    int NPC_GRD_SUB_ISPURSUEING = 19;

void main()
{
    int nUser = GetUserDefinedEventNumber();

    if (GetLocalInt(OBJECT_SELF, "Init") == FALSE)
        Init();

    if (nUser == 1001)  //NW_FLAG_HEARTBEAT_EVENT
    {
        if (GetIsInCombat() && GetIsObjectValid(GetLastAttacker()))
            if (GetLastAttacker() != GetLocalObject(OBJECT_SELF, "Dummy"))
                SetState(NPC_GRD_COMBAT);

        if (GetIsObjectValid(GetPrisonerToImprison()))
            SetState(NPC_GRD_IMPRISON);


        DebugString(GetName(OBJECT_SELF) + " state: " + IntToString(GetState()));

       if (!IsInConversation(OBJECT_SELF))
       {

        switch (GetState())
        {
            case 1: DoIdle(); break;
            case 2: DoPatrol(); break;
            case 3: DoPatrol(); break;
            case 4: DoAle(); break;
            case 5: DoRest(); break;
            case 6: DoConversation(); break;
            case 7: DoCombat(); break;
            case 8: DoImprison(); break;
            case 9: DoPursue(); break;
        }
        }
        }
    if (nUser == 1002)  //NW_FLAG_PERCIEVE_EVENT
    {
        object oPerceived = GetLastPerceived();
        if (GetIsPC(oPerceived))
        {
            DebugString(GetName(OBJECT_SELF) + " perceived " + GetName(oPerceived));
            DebugString(GetName(oPerceived) + " State: " + IntToString(GetLocalInt(oPerceived, "State")));
            DebugString(GetName(oPerceived) + " Reputation: " + IntToString(GetLocalInt(oPerceived, "RPO_Reputation")));
        }
/*
          object oHostile = GetLastHostileActor();
          if (GetIsObjectValid(oHostile))
            if ((GetObjectSeen(oHostile) || GetObjectHeard(oHostile)) && GetLocalInt(oHostile, "PlayerState") != PWS_PLAYER_STATE_PRISON)
            {
                DebugString(GetName(OBJECT_SELF) + " witnessed a crime by " + GetName(oHostile));
                //AdjustReputation(oHostile, OBJECT_SELF, -50);
                ActionMoveToObject(oHostile);
                SpeakString("Hold! In the name of justice, stop right there!", TALKVOLUME_SHOUT);
                SetState(NPC_GRD_PURSUE);
            }
*/
        if (!GetIsObjectValid(GetLocalObject(OBJECT_SELF, "Perceived")))
        {
            int nChance = Random(100) + 1;
            if (GetIsObjectValid(oPerceived))
            {
                if (GetState() == NPC_GRD_PATROL)
                {
                    string sTag = GetTag(oPerceived);
                    if ((FindSubString(sTag, "OFF") >= 0 || FindSubString(sTag, "Guard") >= 0)
                        && !IsInConversation(oPerceived) && !GetIsInCombat() && nChance <= 30 )
                    {
                        ClearAllActions();
                        DebugString(GetName(OBJECT_SELF) + " Perceived: " + GetName(oPerceived));
                        //added this in
                        ActionMoveToObject(oPerceived);
                        SetLocalObject(OBJECT_SELF, "Perceived", oPerceived);
                        ActionDoCommand(SetLocalInt(OBJECT_SELF, "GuardState", NPC_GRD_CONVERSATION));

                        if (!GetIsObjectValid(GetLocalObject(oPerceived, "Perceived")))
                        {
                            SetLocalObject(oPerceived, "Perceived", OBJECT_SELF);
                            event ePerceived = EventUserDefined(10001);
                            SignalEvent(oPerceived, ePerceived);
                        }
                    }
                }
            }
        }
    }
    if (nUser == 1004) // OnDialogEvent
    {
        if (!GetIsInCombat() && !GetIsObjectValid(GetLastAttacker()))
        {
            if (IsInConversation(OBJECT_SELF))
                SetState(NPC_GRD_CONVERSATION);
            else
                SetState(NPC_GRD_IDLE);

            DebugString(GetName(OBJECT_SELF) + " OnDialogEvent State: " + IntToString(GetState()));
        }
    }
    if (nUser == 1003) // OnCombatRoundEnd
    {
        object oLastAttacker = GetLastAttacker();
        if (GetIsObjectValid(oLastAttacker))
        {
            if (GetTag(oLastAttacker) == "MeleeDummy")
            {
                SetDummyEnemy(oLastAttacker, FALSE);
                SetDummyEnemy(oLastAttacker, TRUE);
                DebugString("OnCombatRoundEnd: Dummy enemy state reset for " + GetName(OBJECT_SELF));
            }
            else
            {
                SetDummyEnemy(GetLocalObject(OBJECT_SELF, "Dummy"), FALSE);
                if (GetIsObjectValid(oLastAttacker))
                {
                    SetState(NPC_GRD_COMBAT);
                    if (GetIsObjectValid(oLastAttacker) && GetIsPC(oLastAttacker))
                    {
                        if (!GetIsObjectValid(GetLocalObject(oLastAttacker, "Prisoner")))
                        {
                            //SetLocalInt(oLastAttacker, "RPO_Reputation", RPO_PLAYER_REPUTATION_CRIMINAL);
                            DebugString(GetName(oLastAttacker) + " reputation set to RPO_PLAYER_REPUTATION_CRIMINAL! (OnCombatRoundEnd)");
                            //AddPrisoner(oLastAttacker);
                        }
                    }
                }
            }
        }
    }
    if (nUser == 1005) // OnAttacked
    {
        object oLastAttacker = GetLastAttacker();
        if (GetIsObjectValid(oLastAttacker))
        {
            if (GetTag(oLastAttacker) == "MeleeDummy")
                DebugString(GetName(OBJECT_SELF) + " got attacked by MeleeDummy!");
            else
            {
                if (GetIsPC(oLastAttacker))
                {
                    DebugString(GetName(OBJECT_SELF) + " got attacked by " + GetName(oLastAttacker));
                    ClearAllActions();
                    SetState(NPC_GRD_COMBAT);
                    DetermineCombatRound(oLastAttacker);

                    DebugString(GetName(OBJECT_SELF) + " feels about " + GetName(oLastAttacker) + ": " + IntToString(GetReputation(OBJECT_SELF, oLastAttacker)));
                    //SetLocalInt(oLastAttacker, "RPO_REPUTATION", RPO_PLAYER_REPUTATION_CRIMINAL);
                    DebugString(GetName(oLastAttacker) + " reputation set to RPO_PLAYER_REPUTATION_CRIMINAL! (OnAttacked)");

                    if (!GetIsObjectValid(GetLocalObject(oLastAttacker, "Prisoner")))
                        AddPrisoner(oLastAttacker);

                    SpeakString("NW_ATTACK_MY_TARGET", TALKVOLUME_SILENT_TALK);
                    SpeakString("NW_I_WAS_ATTACKED", TALKVOLUME_SILENT_TALK);
                }
            }
        }
    }
    if (nUser == 1006) // OnDamaged
    {
        object oAttacker = GetLastDamager();

        if (GetTag(oAttacker) == "MeleeDummy")
        {
            DebugString(GetName(OBJECT_SELF) + " got attacked by MeleeDummy!");

            ClearAllActions();
            SetDummyEnemy(oAttacker, FALSE);
            SetDummyEnemy(oAttacker, TRUE);
            DebugString("OnDamaged: Dummy enemy state reset for " + GetName(OBJECT_SELF));
            DetermineCombatRound();

            // Heal guard, if it was damaged by the dummy
            int iCurrentHP = GetCurrentHitPoints();
            int iMaxHP = GetMaxHitPoints();
            effect eHeal = EffectHeal(iMaxHP - iCurrentHP);
            ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, OBJECT_SELF);
        }
        else
        {
            ClearAllActions();
            SetDummyEnemy(GetLocalObject(OBJECT_SELF, "Dummy"), FALSE);
            SetLocalObject(OBJECT_SELF, "Dummy", OBJECT_INVALID);
            if (GetLocalInt(oAttacker, "RPO_REPUTATION") != RPO_PLAYER_REPUTATION_CRIMINAL)
            {
                //SetLocalInt(oAttacker, "RPO_Reputation", RPO_PLAYER_REPUTATION_CRIMINAL);
                DebugString(GetName(oAttacker) + " reputation set to RPO_PLAYER_REPUTATION_CRIMINAL! (OnCombatRoundEnd)");
               // if (!GetIsObjectValid(GetLocalObject(oAttacker, "Prisoner")))
                //    AddPrisoner(oAttacker);
            }
        }
    }
    if (nUser == 1008) // OnDisturbed
    {
        object oLastDisturbed = GetLastDisturbed();
        if (!GetIsInCombat())
            ClearAllActions();

        SetState(NPC_GRD_PURSUE);
        ActionAttack(oLastDisturbed);
        SpeakString("Ey! How ya dare to pickpocket a guard?!");

        if (GetIsPC(oLastDisturbed) && GetLocalInt(oLastDisturbed, "RPO_REPUTATION") != RPO_PLAYER_REPUTATION_CRIMINAL)
            if (oLastDisturbed != GetLocalObject(OBJECT_SELF, "Dummy") &&
                !GetIsObjectValid(GetLocalObject(oLastDisturbed, "Prisoner")))
            {
                SetState(NPC_GRD_COMBAT);
                if (GetIsObjectValid(oLastDisturbed) && GetIsPC(oLastDisturbed))
                {
                   // SetLocalInt(oLastDisturbed, "RPO_Reputation", RPO_PLAYER_REPUTATION_CRIMINAL);
                    DebugString(GetName(oLastDisturbed) + " reputation set to RPO_PLAYER_REPUTATION_CRIMINAL! (OnDisturbed)");
                   // if (!GetIsObjectValid(GetLocalObject(oLastDisturbed, "Prisoner")))
                     //   AddPrisoner(oLastDisturbed);
                }
            }

    }
    if (nUser == 10001)  // NW_FLAG_PERCIEVE_EVENT
    {
        object oPerceived = GetLocalObject(OBJECT_SELF, "Perceived");
        if (GetIsObjectValid(oPerceived) && !GetIsInCombat())
        {
            ClearAllActions();
            ActionDoCommand(SetFacing(GetFacingFromLocation(GetLocation(oPerceived))));
            DebugString(GetName(OBJECT_SELF) + " Remote Perceived: " + GetName(oPerceived));
            ActionMoveToObject(oPerceived);
            ActionDoCommand(SetLocalInt(OBJECT_SELF, "GuardState", NPC_GRD_CONVERSATION));
        }
        else
        {
            if (!GetIsInCombat()) SetState(NPC_GRD_CONVERSATION);
        }
    }
}

void Init()
{
    string sTag = GetTag(OBJECT_SELF);
    int nRandom = d100();

    // Check if we are an officer
    if (FindSubString(sTag, "OFF") >= 0)
        SetLocalInt(OBJECT_SELF, "GuardOfficer", TRUE);
    //  Check if we got nightshift
    if (nRandom < 30)
        SetLocalInt(OBJECT_SELF, "Nightshift", TRUE);
    else
        SetLocalInt(OBJECT_SELF, "Nightshift", FALSE);

    // Create the torch to be used at night
    object oTorch = CreateItemOnObject("nw_it_torch001", OBJECT_SELF);
    SetLocalObject(OBJECT_SELF, "Torch", oTorch);

    // Store the items held in hands (armed)
    SetLocalObject(OBJECT_SELF, "LeftHandObject", GetItemInSlot(INVENTORY_SLOT_LEFTHAND));
    SetLocalObject(OBJECT_SELF, "RightHandObject", GetItemInSlot(INVENTORY_SLOT_RIGHTHAND));
    SetLocalObject(OBJECT_SELF, "HeadObject", GetItemInSlot(INVENTORY_SLOT_HEAD));
    // Stores the bench on which to sit at the tavern
    SetLocalObject(OBJECT_SELF,"Bench",OBJECT_INVALID);
    // Stores the person perceived
    SetLocalObject(OBJECT_SELF,"Perceived",OBJECT_INVALID);
    // Stores the training dummy to be used at trainings
    SetLocalObject(OBJECT_SELF,"Dummy",OBJECT_INVALID);

    ClearAllActions();
    DebugString(GetName(OBJECT_SELF) + " initialized!");

    SetSummonHelpIfAttacked();

    SetState(NPC_GRD_IDLE);
    SetLocalInt(OBJECT_SELF,"Init", TRUE);
}

int CheckSchedule()
{
    int nState;
    int nHour = GetTimeHour();

    switch (nHour)
    {
        case 0: nState = NPC_GRD_PATROL;break;
        case 1: nState = NPC_GRD_REST;break;
        case 2: nState = NPC_GRD_REST; break;
        case 3: nState = NPC_GRD_REST; break;
        case 4: nState = NPC_GRD_REST; break;
        case 5: nState = NPC_GRD_ALE; break;
        case 6: nState = NPC_GRD_ALE; break;
        case 7: nState = NPC_GRD_TRAINING; break;
        case 8: nState = NPC_GRD_TRAINING; break;
        case 9: nState = NPC_GRD_PATROL; break;
        case 10: nState = NPC_GRD_PATROL; break;
        case 11: nState = NPC_GRD_PATROL; break;
        case 12: nState = NPC_GRD_ALE; break;
        case 13: nState = NPC_GRD_PATROL; break;
        case 14: nState = NPC_GRD_PATROL; break;
        case 15: nState = NPC_GRD_PATROL; break;
        case 16: nState = NPC_GRD_TRAINING; break;
        case 17: nState = NPC_GRD_TRAINING; break;
        case 18: nState = NPC_GRD_ALE; break;
        case 19: nState = NPC_GRD_ALE; break;
        case 20: nState = NPC_GRD_PATROL; break;
        case 21: nState = NPC_GRD_PATROL; break;
        case 22: nState = NPC_GRD_PATROL; break;
        case 23: nState = NPC_GRD_PATROL; break;
        case 24: nState = NPC_GRD_PATROL; break;
    }

    return nState;
}


void DoIdle()
{
    SetSubState(0);
    SetState(CheckSchedule());
}

void DoPatrol()
{
    if (GetSubState() != NPC_GRD_SUB_ONPATROL && !GetIsInCombat())
    {
        // Patrol mode not yet initialized
        DebugString(GetName(OBJECT_SELF) + " Patrolmode initialized!");
        ClearAllActions();
        //ActionDoCommand(PlayAnimation(ANIMATION_LOOPING_PAUSE_TIRED));
        Arm(TRUE);

        if (CheckWayPoints() == TRUE)
        {
            if (GetIsOfficer() == TRUE)
                SpeakString("Lets do a few rounds.");
            else
                SpeakString("I guess it's time to continue my patrol.");
        }
        else
            SpeakString ("I have no route to walk Captain!");

        //ActionDoCommand(SetLocalInt(OBJECT_SELF, "GuardSubState", NPC_GRD_SUB_ONPATROL));
        SetSubState(NPC_GRD_SUB_ONPATROL);
        if (GetArea(OBJECT_SELF) != GetArea(GetWaypointByTag("WP_" + GetTag(OBJECT_SELF) + "_01")))
        {
            DebugString(GetName(OBJECT_SELF) + " Waypoints not in same area ... forcing move!");
            ActionForceMoveToObject(GetNearestObject(OBJECT_TYPE_WAYPOINT, GetWaypointByTag("WP_" + GetTag(OBJECT_SELF) + "_01"), d6(1)));
        }
    }
    else
    {
       // Patrol mode already initialized
       if (GetTimeSecond() < 10) DebugString(GetName(OBJECT_SELF) + " Patrouling!");
       ActionDoCommand(IWalkWayPoints(FALSE, 2.0f, "", 1, Random(3) + 1));
       if (GetState() != NPC_GRD_CONVERSATION)
            SetState (CheckSchedule());
    }
}

void DoTraining()
{
    if (GetSubState() != NPC_GRD_SUB_ISTRAINING && !GetIsInCombat())
    {
        DebugString(GetName(OBJECT_SELF) + " Trainingmode initialized!");

        ClearAllActions();
        //SpeakString("Time fer training!");

        ActionMoveToObject(GetWaypointByTag("WP_GRD_TRAINING"), TRUE);
        if (!GetIsOfficer())
        {
            object oDummy = GetNearestObjectByTag("MeleeDummy");
            if (GetIsObjectValid(oDummy))
            {
                //SetPlotFlag(oDummy, TRUE);
                //ActionDoCommand(ActionMoveToObject(oDummy, TRUE));
                //ActionDoCommand(SetDummyEnemy(oDummy, TRUE));
                //ActionDoCommand(DoPlaceableObjectAction(oDummy,PLACEABLE_ACTION_BASH));
            }
        }
        ActionDoCommand(SetLocalInt(OBJECT_SELF, "GuardSubState", NPC_GRD_SUB_ISTRAINING));
        //SetSubState(NPC_GRD_SUB_ISTRAINING);
    }
    else
    {
        // Training mode already initialized
       if (GetIsOfficer() == TRUE  && !GetIsInCombat())
       {
           ClearAllActions();
           DoOfficerTrainingTalk();
           PlayImmobileAmbientAnimations();
       }
       SetState (CheckSchedule());
       if (GetState() != NPC_GRD_TRAINING)
           SetPlotFlag(GetLocalObject(OBJECT_SELF, "Dummy"), FALSE);
    }
}

void DoAle()
{
    if (GetSubState() != NPC_GRD_SUB_ISDRINKING && (!GetIsInCombat() || !GetIsObjectValid(GetLastAttacker())))
    {
        // Drinking state not yet initialized
        DebugString(GetName(OBJECT_SELF) + " Alemode initialized!");
        SetDummyEnemy(GetLocalObject(OBJECT_SELF, "Dummy"), FALSE);

        ClearAllActions();
        Arm(FALSE);
        SetLocalObject(OBJECT_SELF, "Bench", OBJECT_INVALID);
        //SpeakString("Ah finally some break!");
        ActionMoveToObject(GetWaypointByTag("WP_GRD_TABLE"));
        ActionDoCommand(SetLocalInt(OBJECT_SELF, "GuardSubState", NPC_GRD_SUB_ISDRINKING));

    }
    else
    {
        // Drinking state already initialized
        if (!GetIsInCombat())
        {
            DebugString(GetName(OBJECT_SELF) + " should be going to the tavern!");
            object oBench = GetLocalObject(OBJECT_SELF, "Bench");
            if (GetIsObjectValid(oBench))
            {
                if (!GetIsObjectValid(GetSittingCreature(oBench)))
                    ActionSit(oBench);
                else
                    SetLocalObject(OBJECT_SELF, "Bench", GetFreeBench(OBJECT_SELF, GetArea(GetObjectByTag("WP_GRD_TABLE"))));
            }
            else
            {
                // Ack, no bench yet?
                SetLocalObject(OBJECT_SELF, "Bench", GetFreeBench(OBJECT_SELF, GetArea(GetObjectByTag("WP_GRD_TABLE"))));
            }
        }
    }
    SetState (CheckSchedule());
    if (GetState() != NPC_GRD_ALE)
        Arm(TRUE);
}

void DoRest()
{
    if (GetSubState() != NPC_GRD_SUB_ISRESTING  && !GetIsInCombat())
    {
        DebugString(GetName(OBJECT_SELF) + " Restmode initialized!");
        ClearAllActions();
        ActionDoCommand(SetLocalInt(OBJECT_SELF, "GuardSubState", NPC_GRD_SUB_ISRESTING));
    }
    else
    {
        SetState (CheckSchedule());
    }
}

void DoCombat()
{
    object oOpponent = GetLastAttacker();
    if (oOpponent == GetLocalObject(OBJECT_SELF, "Dummy"))
        SetState(CheckSchedule());

    oOpponent = GetLastDamager();
    if (oOpponent == GetLocalObject(OBJECT_SELF, "Dummy"))
        SetState(CheckSchedule());

    if (GetIsObjectValid(GetPrisonerToImprison()) && !GetIsInCombat())
    {
        ClearAllActions();
        SetState(NPC_GRD_IMPRISON);
        SetSubState(0);
        DoImprison();
    }
    else
        if (!GetIsInCombat()) SetState(CheckSchedule());
}

void DoImprison()
{
    int nFreePrison;
    string sPrisonTag;

    if (GetSubState() != NPC_GRD_SUB_ISIMPRISONING && (!GetIsInCombat() || GetAttackTarget() == GetLocalObject(OBJECT_SELF, "Dummy")))
    {
        object oPrisoner = GetPrisonerToImprison();
        if (GetIsObjectValid(oPrisoner) && GetIsDead(oPrisoner))
        {
            if (GetLocalInt(oPrisoner, "PlayerState") != PWS_PLAYER_STATE_PRISON &&
                !GetIsObjectValid(GetLocalObject(oPrisoner, "Prisoner")) ||
                GetLocalObject(oPrisoner, "Prisoner") == OBJECT_SELF)
            {
                ClearAllActions();
                //ClearAllFactionMembers (OBJECT_SELF, oPrisoner);
                DebugString("Going to imprison " + GetName(oPrisoner));

                ActionMoveToObject(oPrisoner, TRUE);
                ActionPlayAnimation(ANIMATION_LOOPING_GET_LOW, 1.0f, 5.0f);
                ActionDoCommand(SpeakString("Served ya well. Now to the prison with ya!"));

                nFreePrison = GetFreePrison();
                sPrisonTag = "GuardPrison_" + IntToString(nFreePrison);
                LockPrison(nFreePrison);

                SetLocalInt(oPrisoner, "PrisonCell", nFreePrison);

                ActionDoCommand(Imprison(oPrisoner, OBJECT_SELF, sPrisonTag));
                ActionJumpToLocation(GetLocation(GetObjectByTag("GuardPrisonPost_" + IntToString(nFreePrison))));
                ActionDoCommand(SetLocalInt(OBJECT_SELF, "GuardState", NPC_GRD_IMPRISON));
                ActionDoCommand(SetLocalInt(OBJECT_SELF, "GuardSubState", NPC_GRD_SUB_ISIMPRISONING));
                //ClearAllFactionMembers (OBJECT_SELF, oPrisoner);
            }
        }
        else
        {
            DebugString("No Prisoner found to imprison!");
            SetState(CheckSchedule());
        }
    }
    else
    {
        object oPrisoner = GetLocalObject(OBJECT_SELF, "Prisoner");
        if (GetIsObjectValid(oPrisoner) && !GetIsInCombat())
        {
            //SetLocalInt(oPrisoner, "PlayerState", PWS_PLAYER_STATE_PRISON);
            //SetLocalInt(oPrisoner, "RPO_REPUTATION", RPO_PLAYER_REPUTATION_CRIMINAL);

            RemovePrisoner(oPrisoner);
            AddPrisoner(oPrisoner, GetNearestObjectByTag("PrisonGuard"));

            ClearAllActions();
            if (GetIsOfficer())
                SpeakString("Didn't I warn ya to stay out of trouble! Ya'll stay here till I decide what to do with ya.");
            else
                SpeakString("Didn't the captain warn ya to stay out of trouble! Ya'll stay here till the captain decides what to do with ya.");

            if (GetIsObjectValid(GetPrisonerToImprison()))
                SpeakString("Now let me get the other so ya got company .. Harhar");

            SetSubState(0);
            SetState(CheckSchedule());
        }
        else if (!GetIsInCombat())
        {
            SetSubState(0);
            SetState(CheckSchedule());
        }
    }
}

void DoPursue()
{
}

void DoConversation()
{

    object oPerceived = GetLocalObject(OBJECT_SELF, "Perceived");

    if (GetSubState() != NPC_GRD_SUB_INCONVERSATION  && !GetIsInCombat())
    {
        ClearAllActions();
        DebugString(GetName(OBJECT_SELF) + " Conversationmode initialized!");



        if (GetIsObjectValid(oPerceived))
        {
          SetLocalObject(OBJECT_SELF,"oFriend",oPerceived);

            if (GetIsOfficer())
            {
                PlaySound("as_pl_officerm4");
                SpeakString("Come on over here " + GetName(oPerceived) + " ... ");
                AssignCommand(oPerceived,ClearAllActions());
                AssignCommand(oPerceived,ActionMoveToObject(OBJECT_SELF));
            }
            else
                if (GetLocalInt(oPerceived, "Officer") == TRUE)
                    SpeakString("Hail Captain!");
                else
                    SpeakString("Hail " + GetName(oPerceived));

            ActionDoCommand(PlayAnimation(ANIMATION_FIREFORGET_SALUTE));
            ActionMoveToObject(oPerceived);
            SetLocalInt(OBJECT_SELF, "GuardSubState", NPC_GRD_SUB_INCONVERSATION);
        }
        else
        {
            DebugString(GetName(OBJECT_SELF) + " Conversationmode cancelled!");
            SetState (CheckSchedule());
        }
    }
    else
    {
        int nConvCount = GetLocalInt(OBJECT_SELF, "GuardConvCount");
        if (nConvCount > 2)
        {
            nConvCount = 0;
            SetLocalObject(OBJECT_SELF, "Perceived", OBJECT_INVALID);
            SetState (CheckSchedule());
        }
        else
        {
            nConvCount++;
            if (!GetIsInCombat())
            {
                //ActionStartConversation(GetLocalObject(OBJECT_SELF, "Perceived"), "cv_guards");
                SetFacingPoint(GetPosition(oPerceived));
                ActionDoCommand(DoRandomAction());
                ActionDoCommand(PlayImmobileAmbientAnimations());
            }
        }
        SetLocalInt(OBJECT_SELF, "GuardConvCount", nConvCount);
    }
}

void DoOfficerTrainingTalk()
{
    //ActionDoCommand(PlayAnimation(ANIMATION_LOOPING_TALK_FORCEFUL, 1.0f, 3.0f));
    //int nRandom = d4();
    //switch (nRandom)
   // {
       // case 1: ActionDoCommand(PlaySound("as_pl_officerm1")); break;
       // case 2: ActionDoCommand(PlaySound("as_pl_officerm2")); break;
       // case 3: ActionDoCommand(PlaySound("as_pl_officerm3")); break;
      //  case 4: ActionDoCommand(PlaySound("as_pl_officerm4")); break;
   // }
   // ActionDoCommand(ActionSit(GetObjectByTag("OfficerBench")));
}


void Arm(int nArm)
{
    object oLeft;
    object oRight;
    object oHead;

    if (nArm == TRUE)
    {
        oRight = GetLocalObject(OBJECT_SELF, "RightHandObject");
        if (GetIsDusk() || GetIsNight())
            oLeft = GetLocalObject(OBJECT_SELF, "Torch");
        else
            oLeft = GetLocalObject(OBJECT_SELF, "LeftHandObject");

        if (GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_LEFTHAND)))
            if (GetItemInSlot(INVENTORY_SLOT_LEFTHAND) != oLeft)
                ActionDoCommand(ActionUnequipItem(oLeft));

        oHead = GetLocalObject(OBJECT_SELF, "HeadObject");

        if (GetIsObjectValid(oLeft))
            if (!GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_LEFTHAND)))
                ActionDoCommand(ActionEquipItem(oLeft, INVENTORY_SLOT_LEFTHAND));
        if (GetIsObjectValid(oRight))
            if (!GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND)))
                ActionDoCommand(ActionEquipItem(oRight, INVENTORY_SLOT_RIGHTHAND));
        if (GetIsObjectValid(oHead))
            if (!GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_HEAD)))
               ActionDoCommand(ActionEquipItem(oHead, INVENTORY_SLOT_HEAD));
    }
    else
    {
        oLeft = GetItemInSlot(INVENTORY_SLOT_LEFTHAND);
        oRight = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND);
        oHead = GetItemInSlot(INVENTORY_SLOT_HEAD);

        if (GetIsObjectValid(oLeft))
            if (GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_LEFTHAND)))
                ActionDoCommand(ActionUnequipItem(oLeft));
        if (GetIsObjectValid(oRight))
            if (GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND)))
                ActionDoCommand(ActionUnequipItem(oRight));
        if (GetIsObjectValid(oHead))
            if (GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_RIGHTHAND)))
                ActionDoCommand(ActionUnequipItem(oHead));

        if (GetIsDusk() || GetIsNight())
        {
            oLeft = GetLocalObject(OBJECT_SELF, "Torch");
            if (GetIsObjectValid(oLeft))
                if (!GetIsObjectValid(GetItemInSlot(INVENTORY_SLOT_LEFTHAND)))
                    ActionDoCommand(ActionEquipItem(oLeft, INVENTORY_SLOT_LEFTHAND));
        }
    }
}

void SetDummyEnemy(object oDummy, int nEnemy)
{
    if (GetIsObjectValid(oDummy))
        if (nEnemy == TRUE)
        {
            SetLocalObject(OBJECT_SELF, "Dummy", oDummy);
            SetIsTemporaryEnemy(oDummy, OBJECT_SELF);
        }
        else
        {
            AdjustReputation(oDummy, OBJECT_SELF, 100);
            ClearAllFactionMembers (OBJECT_SELF, oDummy);
            SetLocalObject(OBJECT_SELF, "Dummy", OBJECT_INVALID);
        }
}

// ----------------------------- Random Speech and Animations --------------------------------
void DoRandomAction()
{
    object oFriend;
    int nRandom = Random(6) + 1;
    switch (GetSubState())
    {
        case 16:    //RD_SUB_INCONVERSATION

            oFriend=GetLocalObject(OBJECT_SELF,"oFriend");
            SetFacingPoint(GetPosition(oFriend));

            switch (nRandom)
            {
                case 1: PlayImmobileAmbientAnimations(); break;
                case 2: PlayImmobileAmbientAnimations(); break;
                case 3: PlayImmobileAmbientAnimations(); break;
                case 4: PlayImmobileAmbientAnimations(); break;
                case 5: PlayImmobileAmbientAnimations(); break;
                case 6: PlayImmobileAmbientAnimations(); break;
             }

             //ActionDoCommand(SpeakOneLinerConversation("cv_guards", GetLocalObject(OBJECT_SELF, "Perceived")));
             break;
        case 12:                     // NPC_GRD_ONPATROL
            switch (nRandom)
            {
                case 1: PlaySound("as_pl_whistle1");break;
                case 2: PlaySound("as_pl_whistle2");break;
                case 3: PlaySound("as_pl_coughm1");break;
                case 4: PlaySound("as_pl_yawningm1");break;
                case 5: PlaySound("as_pl_coughm2");break;
                case 6: PlaySound("as_pl_yawningm1");break;
             }
             break;
        case 13:                     // NPC_GRD_ISTRAINING
            switch (nRandom)
            {
                case 1: PlayAnimation(ANIMATION_LOOPING_LISTEN,1.0,5.0); break;
                case 2: SpeakString("Ya sure about that?"); break;
                case 3: PlaySound("as_pl_comtalk3"); break;
                case 4: PlaySound("as_pl_comtalk2"); break;
                case 5: SpeakString("Phew!"); break;
                case 6: break;
             }
             break;
        case 14:                     // NPC_GRD_ISDRINKING
            switch (nRandom)
            {
                case 1: PlaySound("as_pl_comtalk3"); break;
                case 2: PlaySound("as_pl_comtalk3"); break;
                case 3: PlaySound("as_pl_comtalk3"); break;
                case 4: PlaySound("as_pl_comtalk2"); break;
                case 5: PlaySound("as_pl_comtalk2"); break;
                case 6: PlaySound("as_pl_comtalk2"); break;
             }
             break;
    }
}
// ----------------------------- STATES --------------------------------
int GetState()
{
    return GetLocalInt(OBJECT_SELF, "GuardState");
}

void SetState(int nState)
{
    SetLocalInt(OBJECT_SELF, "GuardState", nState);
}
int GetSubState()
{
    return GetLocalInt(OBJECT_SELF, "GuardSubState");
}

void SetSubState(int nState)
{
    SetLocalInt(OBJECT_SELF, "GuardSubState", nState);
}
int GetIsOfficer()
{
    return GetLocalInt(OBJECT_SELF, "GuardOfficer");
}

int GetFreePrison()
{
    object oSamir = GetNearestObjectByTag("PrisonGuard");
    int nNum = 0;

    while (nNum < GetIntArraySize("Prisons", oSamir))
    {
        DebugString("Checking Prison: " + IntToString(nNum));
        if (GetIntArray("Prisons", nNum, oSamir) == TRUE)
            return nNum;

        nNum++;
    }
    return 0;
}

void LockPrison(int nNum)
{
    object oSamir = GetNearestObjectByTag("PrisonGuard");
    SetIntArray("Prisons", nNum, FALSE, oSamir);
    DebugString("Locking Prison #" + IntToString(nNum));
    AssignCommand(oSamir, ActionCloseDoor(GetObjectByTag("PrisonDoor_" + IntToString(nNum))));
    //AssignCommand(oSamir, ActionLockObject(GetObjectByTag("PrisonDoor_" + IntToString(nNum))));
}