Author: Salina Magian
Author Website: exe@dei-mortali.de
Script Name: Guard Dog / Chicken Chase Dog
Description: Makes a dog (or other npc) acts like a guard dog and chase chickens.
Instructions on Use: Put script 1 below into the dogs OnHeartBeat event.
Author Comments: Features:
- No special items or triggers required!!!
- Every dog can have the same script!
- Different sizes of guarded area based on Tag (see example below)
- Dogs bark
- Every dog has it's own unique bark sound
- Dogs do some random walking in their zone while not busy
- NEW NEW NEW: Place some chickens around the dog and see what happens  (don't change chicken tag, no special scripts for chicken required)

Notes:
The radius of the guarded area is taken from the dogs tag. If no special tag is given it'll use the default (18 meters).

Examples:
"GUARDDOG_500" (upper case is important) would make the dog chase you around the whole area (500 meters radius).
"my_guard_doggy" would make the dog chase you around 18 meters (default).
"GUARDDOG_0" ignores the player and will only chase chickens.

Script 1 (OnHeartbeat):

// Guard Dog script by Salina Magian

void main()
{

  float fDefaultGuardRadius = 18.f;  // Default radius of guarded area
  float fChickenRadius = 18.f;  // Default radius of chickens chased

  int HasCreatedArea = GetLocalInt(OBJECT_SELF, "nDoOnce");
  int nBarkSound = GetLocalInt(OBJECT_SELF, "nBarkSound");
  int nChickens = GetLocalInt(OBJECT_SELF, "nChickens");
  float fGuardRadius = GetLocalFloat(OBJECT_SELF, "fGuardRadius");
  float fPCDistance;
  object oGuardArea;
  object oGuardDog = OBJECT_SELF;
  object oPC;
  object oTargetPC;
  object oChicken;


// Create a guarded area, generate bark sound, check Tag, search chickens
  if (!HasCreatedArea)
    {
    location lGuardDog = GetLocation(oGuardDog);
    string sSuffix;
    oChicken = GetNearestObjectByTag("NW_CHICKEN");
    CreateObject(OBJECT_TYPE_PLACEABLE, "plc_invisobj", lGuardDog);
    if (GetStringLeft(GetTag(oGuardDog),9) == "GUARDDOG_")
    {
      sSuffix = GetSubString( GetTag(oGuardDog), 9, GetStringLength( GetTag(oGuardDog)) - 9);
      fGuardRadius = StringToFloat(sSuffix);
    }
    else fGuardRadius = fDefaultGuardRadius;
    SetLocalInt(oGuardDog, "nDoOnce", 1);
    SetLocalInt(oGuardDog, "nBarkSound", (d6(1) + 1));
    SetLocalObject(oGuardDog, "oGuardArea", GetNearestObject( OBJECT_TYPE_PLACEABLE ));
    SetLocalFloat(oGuardDog, "fGuardRadius", fGuardRadius);
    while(GetIsObjectValid(oChicken)
      &&(GetDistanceBetween(oChicken, oGuardDog) < fChickenRadius))
    {
      nChickens++;
      oChicken = GetNearestObjectByTag("NW_CHICKEN", oGuardDog, nChickens);
    }
    SetLocalInt(oGuardDog, "nChickens", nChickens - 1);
  }

// Get the PC who's deepest in guarded area
  oGuardArea = GetLocalObject(oGuardDog, "oGuardArea");
  fPCDistance = 999.f;
  oPC = GetFirstPC();
  oTargetPC = OBJECT_INVALID;
  while (GetIsObjectValid(oPC))
  {
    if ((GetDistanceBetween(oPC, oGuardArea) < fGuardRadius)
      &&(GetDistanceBetween(oPC, oGuardArea) < fPCDistance))
    {
       oTargetPC = oPC;
       fPCDistance = GetDistanceBetween(oPC, oGuardArea);
    }
    oPC = GetNextPC();
  }

// Follows PC or returns to guarded area to chase chickens
  if (GetIsObjectValid(oTargetPC))
  {
    ClearAllActions();
    ActionMoveToObject(oTargetPC, TRUE);
    ActionForceFollowObject(oTargetPC);
    AssignCommand(oTargetPC, PlaySound("as_an_dogbark" + IntToString(nBarkSound)));
  }
  else
  {
     ClearAllActions();
     oChicken = GetNearestObjectByTag("NW_CHICKEN", oGuardArea, Random(nChickens) + 1);
     if ((nChickens > 0) && (GetDistanceBetween(oChicken, oGuardArea) < fChickenRadius))
     {
       ActionForceFollowObject(oChicken);
       AssignCommand(oChicken, ClearAllActions());
       AssignCommand(oChicken, ActionMoveAwayFromObject(oGuardDog,0,10.f));
       AssignCommand(oChicken, ActionMoveToObject(oGuardArea));
       AssignCommand(oChicken, ActionRandomWalk());
       int i;
       for(i = 0; i < nChickens; i++)
       {
         oChicken = GetNearestObjectByTag("NW_CHICKEN", oGuardArea, i+1);
         AssignCommand(oChicken, ActionMoveToObject(oGuardArea));
         AssignCommand(oChicken, ActionRandomWalk());
       }
     }
     else {ActionMoveToObject(oGuardArea); ActionRandomWalk();}
  }
}