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
DaLaw- 05-27-2006
Okay so that makes it compile
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 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
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