Full Version : Make creatures only attackable by questers
xmlspawner >>XMLSpawner - How do I? >>Make creatures only attackable by questers


<< Prev | Next >>

ArteGordon- 05-07-2006
The following modifications to PlayerMobile.cs and BaseCreature.cs will allow you to spawn creatures that can only be attacked by players carrying a specified named item, such as a questholder.

Once you have made these changes, to create a creature that can only be attacked by a quester, simply spawn them with an XmlData attachment named "RestrictAttack" with the Data assigned the name of the item the player must be carrying to attack it. Like this spawn entry

dragon/ATTACH/xmldata,RestrictAttack,Dragon Quest

This dragon can now only be attacked by, and will only attack players carrying the item named "Dragon Quest".

In the CanBeHarmful method in PlayerMobile.cs, make the following changes around line 780

QUOTE

  public override bool CanBeHarmful( Mobile target, bool message, bool ignoreOurBlessedness )
  {
  // ARTEGORDONMOD
  // allow quest specific attack status for mobs
  // if the mob has a RestrictAttack xmldata attachment, then the data on that attachment
  // will give the name of the carried item that will allow the creature to be attacked

  XmlData a = (XmlData)XmlAttach.FindAttachment(target, typeof(XmlData), "RestrictAttack");

  if (a != null)
  {
    // if you have the item then you can attack the target, otherwise you cant
    return (BaseXmlSpawner.SearchMobileForItem(this, a.Data, null, false) != null);
  }

  if ( m_DesignContext != null || (target is PlayerMobile && ((PlayerMobile)target).m_DesignContext != null) )
    return false;

  if ( (target is BaseVendor && ((BaseVendor)target).IsInvulnerable) || target is PlayerVendor || target is TownCrier )
  {
    if ( message )
    {
    if ( target.Title == null )
      SendMessage( "{0} the vendor cannot be harmed.", target.Name );
    else
      SendMessage( "{0} {1} cannot be harmed.", target.Name, target.Title );
    }

    return false;
  }

  return base.CanBeHarmful( target, message, ignoreOurBlessedness );
  }



and in BaseCreature.cs make a similar change around line 4108

QUOTE

  public override bool CanBeHarmful( Mobile target, bool message, bool ignoreOurBlessedness )
  {
  // ARTEGORDONMOD
  // allow quest specific attack status for mobs
  // if the mob has a RestrictAttack xmldata attachment, then the data on that attachment
  // will give the name of the carried item that will allow the creature to be attacked

  XmlData a = (XmlData)XmlAttach.FindAttachment(this, typeof(XmlData), "RestrictAttack");

  if (a != null && target is PlayerMobile)
  {
    // if the target player is carrying the named item then it can be attacked, otherwise it cant
    return (BaseXmlSpawner.SearchMobileForItem(target, a.Data, null, false) != null);
  }

 
  // dont allow restricted creatures to attack pets unless the master has the named item
  if (a != null && target is BaseCreature)
  {
    Mobile master = null;
    BaseCreature btarget = (BaseCreature)target;

    if (btarget.Controled)
    master = btarget.ControlMaster;
    else
    if (btarget.Summoned)
    master = btarget.SummonMaster;
    else
    if (btarget.BardProvoked)
    master = btarget.BardMaster;

    if (master is PlayerMobile)
      // if the master is carrying the named item then it can be attacked, otherwise it cant
      return (BaseXmlSpawner.SearchMobileForItem(master, a.Data, null, false) != null);
  }

  // make a check on pets to prevent them from attacking mobs that are restricted unless the master has the named item
  if (Controled || Summoned || BardProvoked)
  {
    XmlData atarget = (XmlData)XmlAttach.FindAttachment(target, typeof(XmlData), "RestrictAttack");

    if (atarget != null)
    {
    Mobile master = null;

    if (Controled)
      master = ControlMaster;
    else
    if (Summoned)
      master = SummonMaster;
    else
    if (BardProvoked)
      master = BardMaster;

    if (master is PlayerMobile)
      // if the master has the item then it can attack the target, otherwise it cant
      return (BaseXmlSpawner.SearchMobileForItem(master, atarget.Data, null, false) != null);
    }
  }

  if ( target is BaseFactionGuard )
    return false;

  if ( (target is BaseVendor && ((BaseVendor)target).IsInvulnerable) || target is PlayerVendor || target is TownCrier )
  {
    if ( message )
    {
    if ( target.Title == null )
      SendMessage( "{0} the vendor cannot be harmed.", target.Name );
    else
      SendMessage( "{0} {1} cannot be harmed.", target.Name, target.Title );
    }

    return false;
  }

  return base.CanBeHarmful( target, message, ignoreOurBlessedness );
  }


The example XML file below will spawn a dragon that can only be attacked by a player with the "Dragon Quest" questholder that spawns nearby.
If you do not have the questholder, then the dragon will not attack you, and you cannot attack the dragon.

QUOTE

<Spawns>
  <Points>
    <Name>DragonQuest</Name>
    <UniqueId>4c592d6f-2da6-4079-8954-9b36a9c8cf15</UniqueId>
    <Map>Felucca</Map>
    <X>5439</X>
    <Y>1135</Y>
    <Width>10</Width>
    <Height>10</Height>
    <CentreX>5444</CentreX>
    <CentreY>1140</CentreY>
    <CentreZ>0</CentreZ>
    <Range>5</Range>
    <MaxCount>2</MaxCount>
    <MinDelay>5</MinDelay>
    <MaxDelay>10</MaxDelay>
    <DelayInSec>False</DelayInSec>
    <Duration>0</Duration>
    <DespawnTime>0</DespawnTime>
    <ProximityRange>-1</ProximityRange>
    <ProximityTriggerSound>500</ProximityTriggerSound>
    <TriggerProbability>1</TriggerProbability>
    <InContainer>False</InContainer>
    <MinRefractory>0</MinRefractory>
    <MaxRefractory>0</MaxRefractory>
    <TODStart>0</TODStart>
    <TODEnd>0</TODEnd>
    <TODMode>0</TODMode>
    <KillReset>1</KillReset>
    <ExternalTriggering>False</ExternalTriggering>
    <SequentialSpawning>-1</SequentialSpawning>
    <AllowGhostTriggering>False</AllowGhostTriggering>
    <SpawnOnTrigger>False</SpawnOnTrigger>
    <SmartSpawning>False</SmartSpawning>
    <Team>0</Team>
    <Amount>1</Amount>
    <IsGroup>False</IsGroup>
    <IsRunning>True</IsRunning>
    <IsHomeRangeRelative>True</IsHomeRangeRelative>
    <Objects2>dragon/name/OnlyForYou/ATTACH/xmldata,RestrictAttack,Dragon Quest:MX=1:SB=0:RT=0:TO=0:KL=0:RK=0:CA=1:DN=-1:DX=-1:SP=1:PR=-1:OBJ=questholder/name/Dragon Quest/objective1/KILLNAMED,OnlyForYou,dragon:MX=1:SB=0:RT=0:TO=0:KL=0:RK=0:CA=1:DN=-1:DX=-1:SP=1:PR=-1</Objects2>
  </Points>
</Spawns>


DaLaw- 05-27-2006
Great stuff, just want to add this to the post aswell;
remeber to add
"using Server.Engines.XmlSpawner2;"
To both BaseCreature and PlayerMobile smile.gif

DaLaw- 05-27-2006
Okay so that makes it compile tongue.gif
But for I can attack the npc and it can attack me even if I dont have the nececary item, even after adding the stuff to the scripts ;/
Any ideas? :<

ArteGordon- 05-27-2006
QUOTE (DaLaw @ May 27, 2006 07:06 pm)
Okay so that makes it compile tongue.gif
But for I can attack the npc and it can attack me even if I dont have the nececary item, even after adding the stuff to the scripts ;/
Any ideas? :<

what kind of npc is it? If it isnt derived from a basecreature then those mods wont have any effect.

Also, how did you add the xmldata attachment to the npc? Make sure that you name the xmldata attachment "RestrictAttack" with the proper capitalization, just like in the example

dragon/ATTACH/xmldata,RestrictAttack,Dragon Quest

DaLaw- 05-27-2006
Well, to make sure it wasnt a type or anything, I used the DragonQuest above, and that one didnt work either

ArteGordon- 05-27-2006
if you post your CanBeHarmful methods from your basecreature.cs and playermobile.cs I can take a look.

DaLaw- 05-27-2006
Base Creature.cs
CODE
 public override bool CanBeHarmful( Mobile target, bool message, bool ignoreOurBlessedness )
 {
 // ARTEGORDONMOD
 // allow quest specific attack status for mobs
 // if the mob has a RestrictAttack xmldata attachment, then the data on that attachment
 // will give the name of the carried item that will allow the creature to be attacked

 XmlData a = (XmlData)XmlAttach.FindAttachment(this, typeof(XmlData), "RestrictAttack");

 if (a != null && target is PlayerMobile)
 {
   // if the target player is carrying the named item then it can be attacked, otherwise it cant
   return (BaseXmlSpawner.SearchMobileForItem(target, a.Data, null, false) != null);
 }


 // dont allow restricted creatur
es to attack pets unless the master has the named item
 if (a != null && target is BaseCreature)
 {
   Mobile master = null;
   BaseCreature btarget = target as BaseCreature;

   if (btarget.Controled)
   master = btarget.ControlMaster;
   else
   if (btarget.Summoned)
   master = btarget.SummonMaster;
   else
   if (btarget.BardProvoked)
   master = btarget.BardMaster;

   if (master is PlayerMobile)
     // if the master is carrying the named item then it can be attacked, otherwise it cant
     return (BaseXmlSpawner.SearchMobileForItem(master, a.Data, null, false) != null);
 }

 // make a check on pets to prevent them from attacking mobs that are restricted unless the master has the named item
 if (Controled || Summoned || BardProvoked)
 {
   XmlData atarget = (XmlData)XmlAttach.FindAttachment(target, typeof(XmlData), "RestrictAttack");

   if (atarget != null)
   {
   Mobile master = null;

   if (Controled)
     master = ControlMaster;
   else
   if (Summoned)
     master = SummonMaster;
   else
   if (BardProvoked)
     master = BardMaster;

   if (master is PlayerMobile)
     // if the master has the item then it can attack the target, otherwise it cant
     return (BaseXmlSpawner.SearchMobileForItem(master, atarget.Data, null, false) != null);
   }
 }

 if ( target is BaseFactionGuard )
   return false;

 if ( (target is BaseVendor && ((BaseVendor)target).IsInvulnerable) || target is PlayerVendor || target is TownCrier )
 {
   if ( message )
   {
   if ( target.Title == null )
     SendMessage( "{0} the vendor cannot be harmed.", target.Name );
   else
     SendMessage( "{0} {1} cannot be harmed.", target.Name, target.Title );
   }

   return false;
 }

 return base.CanBeHarmful( target, message, ignoreOurBlessedness );
 }


PlayerMobile.cs
CODE
 public override bool CanBeHarmful( Mobile target, bool message, bool ignoreOurBlessedness )
 {
 // ARTEGORDONMOD
 // allow quest specific attack status for mobs
 // if the mob has a RestrictAttack xmldata attachment, then the data on that attachment
 // will give the name of the carried item that will allow the creature to be attacked

 XmlData a = (XmlData)XmlAttach.FindAttachment(target, typeof(XmlData), "RestrictAttack");

 if (a != null &&  target is PlayerMobile)
 {
   // if you have the item then you can attack the target, otherwise you cant
   return (BaseXmlSpawner.SearchMobileForItem(this, a.Data, null, false) != null);
 }

 if ( m_DesignContext != null || (target is PlayerMobile && ((PlayerMobile)target).m_DesignContext != null) )
   return false;

 if ( (target is BaseVendor && ((BaseVendor)target).IsInvulnerable) || target is PlayerVendor || target is TownCrier )
 {
   if ( message )
   {
   if ( target.Title == null )
     SendMessage( "{0} the vendor cannot be harmed.", target.Name );
   else
     SendMessage( "{0} {1} cannot be harmed.", target.Name, target.Title );
   }

   return false;
 }

 return base.CanBeHarmful( target, message, ignoreOurBlessedness );
 }


I basically just copied your whole method over mine.
Thanks smile.gif

ArteGordon- 05-27-2006
sorry, that was my mistake. This is the way the mod should look in playermobile.cs

QUOTE

public override bool CanBeHarmful(Mobile target, bool message, bool ignoreOurBlessedness)
  {
  // ARTEGORDONMOD
  // allow quest specific attack status for mobs
  // if the mob has a RestrictAttack xmldata attachment, then the data on that attachment
  // will give the name of the carried item that will allow the creature to be attacked

  XmlData a = (XmlData)XmlAttach.FindAttachment(target, typeof(XmlData), "RestrictAttack");

  if (a != null)
  {
    // if you have the item then you can attack the target, otherwise you cant
    return (BaseXmlSpawner.SearchMobileForItem(this, a.Data, null, false) != null);
  }

  if (m_DesignContext != null || (target is PlayerMobile && ((PlayerMobile)target).m_DesignContext != null))
    return false;

  if ((target is BaseVendor && ((BaseVendor)target).IsInvulnerable) || target is PlayerVendor || target is TownCrier)
  {
    if (message)
    {
    if (target.Title == null)
      SendMessage("{0} the vendor cannot be harmed.", target.Name);
    else
      SendMessage("{0} {1} cannot be harmed.", target.Name, target.Title);
    }

    return false;
  }

  return base.CanBeHarmful(target, message, ignoreOurBlessedness);
  }


it just changes this line

if (a != null && target is PlayerMobile)

to this

if (a != null)

(edit)

Fixed in the main post now. Thanks.

DaLaw- 05-27-2006
Awesome, thanks!
(and thanks for the usual, very quick response)

Vladimir- 01-23-2008
Heya

Just a quick note...

CODE
   if (btarget.Controled)


Seems to have changed to:

CODE
               if (btarget.Controlled)


Possibly as a result of an SVN update (I'm on 279 atm)

Controled appears 3 times in that BaseCreature CanBeHarmful message, just need to update them to Controlled.

Regards, Vlad

ArteGordon- 01-24-2008
thanks. Yeah, 'Controled' was in RunUO 1.0 and it was changed to 'Controlled' in 2.0