/Scripts/Engines/AI/Creature/BaseCreature.cs
C# | 4750 lines | 3594 code | 997 blank | 159 comment | 913 complexity | 1afd62a65d5182fc73a5cee6e9e74830 MD5 | raw file
- using System;
- using System.Collections;
- using Server;
- using Server.Regions;
- using Server.Targeting;
- using Server.Network;
- using Server.Spells;
- using Server.Misc;
- using Server.Items;
- using Server.Mobiles;
- using Server.ContextMenus;
- using Server.Engines.Quests;
- using Server.Engines;
- using System.Collections.Generic;
- namespace Server.Mobiles
- {
- /// <summary>
- /// Summary description for MobileAI.
- /// </summary>
- ///
- public enum FightMode
- {
- None, // Never focus on others
- Agressor, // Only attack agressors
- Strongest, // Attack the strongest
- Weakest, // Attack the weakest
- Closest, // Attack the closest
- Evil // Only attack aggressor -or- negative karma
- }
- public enum OrderType
- {
- None, //When no order, let's roam
- Come, //"(All/Name) come" Summons all or one pet to your location.
- Drop, //"(Name) drop" Drops its loot to the ground (if it carries any).
- Follow, //"(Name) follow" Follows targeted being.
- //"(All/Name) follow me" Makes all or one pet follow you.
- Friend, //"(Name) friend" Allows targeted player to confirm resurrection.
- Guard, //"(Name) guard" Makes the specified pet guard you. Pets can only guard their owner.
- //"(All/Name) guard me" Makes all or one pet guard you.
- Attack, //"(All/Name) kill",
- //"(All/Name) attack" All or the specified pet(s) currently under your control attack the target.
- Patrol, //"(Name) patrol" Roves between two or more guarded targets.
- Release, //"(Name) release" Releases pet back into the wild (removes "tame" status).
- Stay, //"(All/Name) stay" All or the specified pet(s) will stop and stay in current spot.
- Stop, //"(All/Name) stop Cancels any current orders to attack, guard or follow.
- Transfert //"(Name) transfer" Transfers complete ownership to targeted player.
- }
- [Flags]
- public enum FoodType
- {
- Meat = 0x0001,
- FruitsAndVegies = 0x0002,
- GrainsAndHay = 0x0004,
- Fish = 0x0008,
- Eggs = 0x0010,
- Gold = 0x0020
- }
- [Flags]
- public enum PackInstinct
- {
- None = 0x0000,
- Canine = 0x0001,
- Ostard = 0x0002,
- Feline = 0x0004,
- Arachnid = 0x0008,
- Daemon = 0x0010,
- Bear = 0x0020,
- Equine = 0x0040,
- Bull = 0x0080
- }
- public enum ScaleType
- {
- Red,
- Yellow,
- Black,
- Green,
- White,
- Blue,
- All
- }
- public enum MeatType
- {
- Ribs,
- Bird,
- LambLeg,
- Chicken
- }
- public enum HideType
- {
- Regular,
- Spined,
- Horned,
- Barbed
- }
- public enum PetLoyalty
- {
- None,
- Confused,
- ExtremelyUnhappy,
- RatherUnhappy,
- Unhappy,
- SomewhatContent,
- Content,
- Happy,
- RatherHappy,
- VeryHappy,
- ExtremelyHappy,
- WonderfullyHappy
- }
- public class DamageStore : IComparable
- {
- public Mobile m_Mobile;
- public int m_Damage;
- public bool m_HasRight;
- public DamageStore(Mobile m, int damage)
- {
- m_Mobile = m;
- m_Damage = damage;
- }
- public int CompareTo(object obj)
- {
- DamageStore ds = (DamageStore)obj;
- return ds.m_Damage - m_Damage;
- }
- }
- [Description("PNJ")]
- public class BaseCreature : Mobile
- {
- private BaseAI m_AI; // THE AI
- private AIType m_CurrentAI; // The current AI
- private AIType m_DefaultAI; // The default AI
- private Mobile m_FocusMob; // Use focus mob instead of combatant, maybe we don't whan to fight
- private FightMode m_FightMode; // The style the mob uses
- private LootPackLevel m_LootLevel; // The loot pack level of the mob
- private int m_iRangePerception; // The view area
- private int m_iRangeFight; // The fight distance
- private bool m_bDebugAI; // Show debug AI messages
- private int m_iTeam; // Monster Team
- private double m_dActiveSpeed; // Timer speed when active
- private double m_dPassiveSpeed; // Timer speed when not active
- private double m_dCurrentSpeed; // The current speed, lets say it could be changed by something;
- private Point3D m_pHome; // The home position of the creature, used by some AI
- private int m_iRangeHome = 10; // The home range of the creature
- ArrayList m_arSpellAttack; // List of attack spell/power
- ArrayList m_arSpellDefense; // Liste of defensive spell/power
- private bool m_bControled; // Is controled
- private Mobile m_ControlMaster; // My master
- private Mobile m_ControlTarget; // My target mobile
- private Point3D m_ControlDest; // My target destination (patrol)
- private OrderType m_ControlOrder; // My order
- private PetLoyalty m_Loyalty;
- private double m_dMinTameSkill;
- private bool m_bTamable;
- private bool m_bSummoned = false;
- private DateTime m_SummonEnd;
- private int m_iControlSlots = 1;
- private bool m_bBardProvoked = false;
- private bool m_bBardPacified = false;
- private Mobile m_bBardMaster = null;
- private Mobile m_bBardTarget = null;
- private DateTime m_timeBardEnd;
- private WayPoint m_CurrentWayPoint = null;
- private Point2D m_TargetLocation = Point2D.Zero;
- private Mobile m_SummonMaster;
- private int m_HitsMax = -1;
- private int m_StamMax = -1;
- private int m_ManaMax = -1;
- private int m_DamageMin = -1;
- private int m_DamageMax = -1;
- private int m_PhysicalResistance, m_PhysicalDamage = 100;
- private int m_FireResistance, m_FireDamage;
- private int m_ColdResistance, m_ColdDamage;
- private int m_PoisonResistance, m_PoisonDamage;
- private int m_EnergyResistance, m_EnergyDamage;
- private ArrayList m_Owners;
- private Hashtable m_FearLove;
- private Hashtable m_Hate;
- private bool m_IsSystemInitialized = false;
- protected TimeSpan m_SayingsDelay = TimeSpan.FromSeconds(30);
- protected DateTime m_NextSaying;
- protected bool m_SayingsEnabled = false;
- protected int m_SayingsSecondsDelay = 30;
- protected string m_Saying1 = "";
- protected string m_Saying2 = "";
- protected string m_Saying3 = "";
- protected string m_Saying4 = "";
- protected string m_Saying5 = "";
- private bool m_ShowNameTag = true;
- private bool m_IsStabled;
- private bool m_HasGeneratedLoot; // have we generated our loot yet?
- public virtual InhumanSpeech SpeechType { get { return null; } }
- public bool IsStabled
- {
- get { return m_IsStabled; }
- set { m_IsStabled = value; }
- }
- #region Bonding
- public const bool BondingEnabled = true;
- public virtual bool IsBondable { get { return (BondingEnabled && !Summoned); } }
- public virtual TimeSpan BondingDelay { get { return TimeSpan.FromDays(7.0); } }
- public virtual TimeSpan BondingAbandonDelay { get { return TimeSpan.FromDays(1.0); } }
- public override bool CanRegenHits { get { return !m_IsDeadPet && base.CanRegenHits; } }
- public override bool CanRegenStam { get { return !m_IsDeadPet && base.CanRegenStam; } }
- public override bool CanRegenMana { get { return !m_IsDeadPet && base.CanRegenMana; } }
- public override bool IsDeadBondedPet { get { return m_IsDeadPet; } }
- private bool m_IsBonded;
- private bool m_IsDeadPet;
- private DateTime m_BondingBegin;
- private DateTime m_OwnerAbandonTime;
- [CommandProperty(AccessLevel.GameMaster)]
- public bool IsBonded
- {
- get { return m_IsBonded; }
- set { m_IsBonded = value; InvalidateProperties(); }
- }
- public bool IsDeadPet
- {
- get { return m_IsDeadPet; }
- set { m_IsDeadPet = value; }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public DateTime BondingBegin
- {
- get { return m_BondingBegin; }
- set { m_BondingBegin = value; }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public DateTime OwnerAbandonTime
- {
- get { return m_OwnerAbandonTime; }
- set { m_OwnerAbandonTime = value; }
- }
- #endregion
- public virtual double WeaponAbilityChance { get { return 0.4; } }
- public virtual WeaponAbility GetWeaponAbility()
- {
- return null;
- }
- public override int BasePhysicalResistance { get { return m_PhysicalResistance; } }
- public override int BaseFireResistance { get { return m_FireResistance; } }
- public override int BaseColdResistance { get { return m_ColdResistance; } }
- public override int BasePoisonResistance { get { return m_PoisonResistance; } }
- public override int BaseEnergyResistance { get { return m_EnergyResistance; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public bool ShowNameTag { get { return m_ShowNameTag; } set { m_ShowNameTag = value; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public bool SayingsEnabled { get { return m_SayingsEnabled; } set { m_SayingsEnabled = value; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public int SayingsSecondsDelay { get { return m_SayingsSecondsDelay; } set { m_SayingsSecondsDelay = value; m_SayingsDelay = TimeSpan.FromSeconds(value); } }
- [CommandProperty(AccessLevel.GameMaster)]
- public string Saying1 { get { return m_Saying1; } set { m_Saying1 = value; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public string Saying2 { get { return m_Saying2; } set { m_Saying2 = value; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public string Saying3 { get { return m_Saying3; } set { m_Saying3 = value; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public string Saying4 { get { return m_Saying4; } set { m_Saying4 = value; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public string Saying5 { get { return m_Saying5; } set { m_Saying5 = value; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public int PhysicalResistanceSeed { get { return m_PhysicalResistance; } set { m_PhysicalResistance = value; UpdateResistances(); } }
- [CommandProperty(AccessLevel.GameMaster)]
- public int FireResistSeed { get { return m_FireResistance; } set { m_FireResistance = value; UpdateResistances(); } }
- [CommandProperty(AccessLevel.GameMaster)]
- public int ColdResistSeed { get { return m_ColdResistance; } set { m_ColdResistance = value; UpdateResistances(); } }
- [CommandProperty(AccessLevel.GameMaster)]
- public int PoisonResistSeed { get { return m_PoisonResistance; } set { m_PoisonResistance = value; UpdateResistances(); } }
- [CommandProperty(AccessLevel.GameMaster)]
- public int EnergyResistSeed { get { return m_EnergyResistance; } set { m_EnergyResistance = value; UpdateResistances(); } }
- [CommandProperty(AccessLevel.GameMaster)]
- public int PhysicalDamage { get { return m_PhysicalDamage; } set { m_PhysicalDamage = value; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public int FireDamage { get { return m_FireDamage; } set { m_FireDamage = value; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public int ColdDamage { get { return m_ColdDamage; } set { m_ColdDamage = value; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public int PoisonDamage { get { return m_PoisonDamage; } set { m_PoisonDamage = value; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public int EnergyDamage { get { return m_EnergyDamage; } set { m_EnergyDamage = value; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public LootPackLevel LootLevel { get { return m_LootLevel; } set { m_LootLevel = value; } }
- public virtual FoodType FavoriteFood { get { return FoodType.Meat; } }
- public virtual PackInstinct PackInstinct { get { return PackInstinct.None; } }
- public ArrayList Owners { get { return m_Owners; } }
- public virtual bool AllowMaleTamer { get { return true; } }
- public virtual bool AllowFemaleTamer { get { return true; } }
- public virtual bool SubdueBeforeTame { get { return false; } }
- public virtual bool Commandable { get { return true; } }
- public virtual Poison HitPoison { get { return null; } }
- public virtual double HitPoisonChance { get { return 0.5; } }
- public virtual Poison PoisonImmune { get { return null; } }
- public virtual bool BardImmune { get { return false; } }
- public virtual bool Unprovokable { get { return BardImmune || m_IsDeadPet; } }
- public virtual bool Uncalmable { get { return BardImmune || m_IsDeadPet; } }
- public virtual double DispelDifficulty { get { return 0.0; } } // at this skill level we dispel 50% chance
- public virtual double DispelFocus { get { return 20.0; } } // at difficulty - focus we have 0%, at difficulty + focus we have 100%
- #region Breath ability, like dragon fire breath
- private DateTime m_NextBreathTime;
- // Must be overriden in subclass to enable
- public virtual bool HasBreath { get { return false; } }
- // Base damage given is: CurrentHitPoints * BreathDamageScalar
- public virtual double BreathDamageScalar { get { return (Core.AOS ? 0.16 : 0.05); } }
- // Min/max seconds until next breath
- public virtual double BreathMinDelay { get { return 10.0; } }
- public virtual double BreathMaxDelay { get { return 15.0; } }
- // Creature stops moving for 1.0 seconds while breathing
- public virtual double BreathStallTime { get { return 1.0; } }
- // Effect is sent 1.3 seconds after BreathAngerSound and BreathAngerAnimation is played
- public virtual double BreathEffectDelay { get { return 1.3; } }
- // Damage is given 1.0 seconds after effect is sent
- public virtual double BreathDamageDelay { get { return 1.0; } }
- public virtual int BreathRange { get { return RangePerception; } }
- // Damage types
- public virtual int BreathPhysicalDamage { get { return 0; } }
- public virtual int BreathFireDamage { get { return 100; } }
- public virtual int BreathColdDamage { get { return 0; } }
- public virtual int BreathPoisonDamage { get { return 0; } }
- public virtual int BreathEnergyDamage { get { return 0; } }
- // Effect details and sound
- public virtual int BreathEffectItemID { get { return 0x36D4; } }
- public virtual int BreathEffectSpeed { get { return 5; } }
- public virtual int BreathEffectDuration { get { return 0; } }
- public virtual bool BreathEffectExplodes { get { return false; } }
- public virtual bool BreathEffectFixedDir { get { return false; } }
- public virtual int BreathEffectHue { get { return 0; } }
- public virtual int BreathEffectRenderMode { get { return 0; } }
- public virtual int BreathEffectSound { get { return 0x227; } }
- // Anger sound/animations
- public virtual int BreathAngerSound { get { return GetAngerSound(); } }
- public virtual int BreathAngerAnimation { get { return 12; } }
- public virtual void BreathStart(Mobile target)
- {
- BreathStallMovement();
- BreathPlayAngerSound();
- BreathPlayAngerAnimation();
- this.Direction = this.GetDirectionTo(target);
- Timer.DelayCall(TimeSpan.FromSeconds(BreathEffectDelay), new TimerStateCallback(BreathEffect_Callback), target);
- }
- public virtual void BreathStallMovement()
- {
- if (m_AI != null)
- m_AI.NextMove = DateTime.Now + TimeSpan.FromSeconds(BreathStallTime);
- }
- public virtual void BreathPlayAngerSound()
- {
- PlaySound(BreathAngerSound);
- }
- public virtual void BreathPlayAngerAnimation()
- {
- Animate(BreathAngerAnimation, 5, 1, true, false, 0);
- }
- public virtual void BreathEffect_Callback(object state)
- {
- Mobile target = (Mobile)state;
- if (!target.Alive || !CanBeHarmful(target))
- return;
- BreathPlayEffectSound();
- BreathPlayEffect(target);
- Timer.DelayCall(TimeSpan.FromSeconds(BreathDamageDelay), new TimerStateCallback(BreathDamage_Callback), target);
- }
- public virtual void BreathPlayEffectSound()
- {
- PlaySound(BreathEffectSound);
- }
- public virtual void BreathPlayEffect(Mobile target)
- {
- Effects.SendMovingEffect(this, target, BreathEffectItemID,
- BreathEffectSpeed, BreathEffectDuration, BreathEffectFixedDir,
- BreathEffectExplodes, BreathEffectHue, BreathEffectRenderMode);
- }
- public virtual void BreathDamage_Callback(object state)
- {
- Mobile target = (Mobile)state;
- if (CanBeHarmful(target))
- {
- DoHarmful(target);
- BreathDealDamage(target);
- }
- }
- public virtual void BreathDealDamage(Mobile target)
- {
- int physDamage = BreathPhysicalDamage;
- int fireDamage = BreathFireDamage;
- int coldDamage = BreathColdDamage;
- int poisDamage = BreathPoisonDamage;
- int nrgyDamage = BreathEnergyDamage;
- if (physDamage == 0 && fireDamage == 0 && coldDamage == 0 && poisDamage == 0 && nrgyDamage == 0)
- { // Unresistable damage even in AOS
- target.Damage(BreathComputeDamage(), this);
- }
- else
- {
- AOS.Damage(target, this, BreathComputeDamage(), physDamage, fireDamage, coldDamage, poisDamage, nrgyDamage);
- }
- }
- public virtual int BreathComputeDamage()
- {
- return (int)(Hits * BreathDamageScalar);
- }
- #endregion
- private DateTime m_EndFlee;
- public DateTime EndFleeTime
- {
- get { return m_EndFlee; }
- set { m_EndFlee = value; }
- }
- public virtual void StopFlee()
- {
- m_EndFlee = DateTime.MinValue;
- }
- public virtual bool CheckFlee()
- {
- if (m_EndFlee == DateTime.MinValue)
- return false;
- if (DateTime.Now >= m_EndFlee)
- {
- StopFlee();
- return false;
- }
- return true;
- }
- public virtual void BeginFlee(TimeSpan maxDuration)
- {
- m_EndFlee = DateTime.Now + maxDuration;
- }
- public BaseAI AIObject { get { return m_AI; } }
- public const int MaxOwners = 5;
- public virtual OppositionGroup OppositionGroup
- {
- get { return null; }
- }
- public virtual bool IsFriend(Mobile m)
- {
- OppositionGroup g = this.OppositionGroup;
- if (g != null && g.IsEnemy(this, m))
- return false;
- if (!(m is BaseCreature))
- return false;
- BaseCreature c = (BaseCreature)m;
- return (m_iTeam == c.m_iTeam && ((m_bSummoned || m_bControled) == (c.m_bSummoned || c.m_bControled)));
- }
- public virtual bool IsEnemy(Mobile m)
- {
- OppositionGroup g = this.OppositionGroup;
- if (g != null && g.IsEnemy(this, m))
- return true;
- if (m is BaseGuard)
- return false;
- if (!(m is BaseCreature))
- return true;
- BaseCreature c = (BaseCreature)m;
- return (m_iTeam != c.m_iTeam || ((m_bSummoned || m_bControled) != (c.m_bSummoned || c.m_bControled)));
- }
- public virtual bool CheckControlChance(Mobile m)
- {
- return CheckControlChance(m, 0.0);
- }
- public virtual bool CheckControlChance(Mobile m, double offset)
- {
- double v = GetControlChance(m) + offset;
- if (v > Utility.RandomDouble())
- return true;
- PlaySound(GetAngerSound());
- if (Body.IsAnimal)
- Animate(10, 5, 1, true, false, 0);
- else if (Body.IsMonster)
- Animate(18, 5, 1, true, false, 0);
- return false;
- }
- public virtual bool CanBeControlledBy(Mobile m)
- {
- return (GetControlChance(m) > 0.0);
- }
- public virtual double GetControlChance(Mobile m)
- {
- return 100;
- }
- private static Type[] m_AnimateDeadTypes = new Type[]
- {
- typeof( MoundOfMaggots ), typeof( HellSteed ), typeof( SkeletalMount ),
- typeof( WailingBanshee ), typeof( Wraith ), typeof( SkeletalDragon ),
- typeof( LichLord ), typeof( FleshGolem ), typeof( Lich ),
- typeof( SkeletalKnight ), typeof( BoneKnight ), typeof( Mummy2 ),
- typeof( SkeletalMage ), typeof( BoneMagi ), typeof( PatchworkSkeleton )
- };
- public virtual bool IsAnimatedDead
- {
- get
- {
- if (!Summoned)
- return false;
- Type type = this.GetType();
- bool contains = false;
- for (int i = 0; !contains && i < m_AnimateDeadTypes.Length; ++i)
- contains = (type == m_AnimateDeadTypes[i]);
- return contains;
- }
- }
- public override void Damage(int amount, Mobile from)
- {
- int oldHits = this.Hits;
- if (Spells.Necromancy.EvilOmenSpell.CheckEffect(this))
- amount = (int)(amount * 1.25);
- Mobile oath = Spells.Necromancy.BloodOathSpell.GetBloodOath(from);
- if (oath == this)
- {
- amount = (int)(amount * 1.1);
- from.Damage(amount, from);
- }
- base.Damage(amount, from);
- if (SubdueBeforeTame && !Controled)
- {
- if ((oldHits > (this.HitsMax / 10)) && (this.Hits <= (this.HitsMax / 10)))
- PublicOverheadMessage(MessageType.Regular, 0x3B2, false, "* The creature has been beaten into subjugation! *");
- }
- }
- public virtual bool DeleteCorpseOnDeath
- {
- get
- {
- return !Core.AOS && m_bSummoned;
- }
- }
- public override void SetLocation(Point3D newLocation, bool isTeleport)
- {
- base.SetLocation(newLocation, isTeleport);
- if (isTeleport && m_AI != null)
- m_AI.OnTeleported();
- }
- public override ApplyPoisonResult ApplyPoison(Mobile from, Poison poison)
- {
- if (!Alive || IsDeadPet)
- return ApplyPoisonResult.Immune;
- if (Spells.Necromancy.EvilOmenSpell.CheckEffect(this))
- return base.ApplyPoison(from, PoisonImpl.IncreaseLevel(poison));
- return base.ApplyPoison(from, poison);
- }
- public override bool CheckPoisonImmunity(Mobile from, Poison poison)
- {
- if (base.CheckPoisonImmunity(from, poison))
- return true;
- Poison p = this.PoisonImmune;
- return (p != null && p.Level >= poison.Level);
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public PetLoyalty Loyalty
- {
- get
- {
- return m_Loyalty;
- }
- set
- {
- m_Loyalty = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public WayPoint CurrentWayPoint
- {
- get
- {
- return m_CurrentWayPoint;
- }
- set
- {
- m_CurrentWayPoint = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public Point2D TargetLocation
- {
- get
- {
- return m_TargetLocation;
- }
- set
- {
- m_TargetLocation = value;
- }
- }
- public virtual Mobile ConstantFocus { get { return null; } }
- public virtual bool DisallowAllMoves
- {
- get
- {
- return false;
- }
- }
- public virtual bool InitialInnocent
- {
- get
- {
- return false;
- }
- }
- public virtual bool AlwaysMurderer
- {
- get
- {
- return false;
- }
- }
- public virtual bool AlwaysAttackable
- {
- get
- {
- return false;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public virtual int DamageMin { get { return m_DamageMin; } set { m_DamageMin = value; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public virtual int DamageMax { get { return m_DamageMax; } set { m_DamageMax = value; } }
- [CommandProperty(AccessLevel.GameMaster)]
- public override int HitsMax
- {
- get
- {
- if (m_HitsMax >= 0)
- return m_HitsMax;
- return Str;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public int HitsMaxSeed
- {
- get { return m_HitsMax; }
- set { m_HitsMax = value; }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public override int StamMax
- {
- get
- {
- if (m_StamMax >= 0)
- return m_StamMax;
- return Dex;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public int StamMaxSeed
- {
- get { return m_StamMax; }
- set { m_StamMax = value; }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public override int ManaMax
- {
- get
- {
- if (m_ManaMax >= 0)
- return m_ManaMax;
- return Int;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public int ManaMaxSeed
- {
- get { return m_ManaMax; }
- set { m_ManaMax = value; }
- }
- public Hashtable FearLove
- {
- get { return m_FearLove; }
- }
- public Hashtable Hate
- {
- get { return m_Hate; }
- }
- public virtual bool CanOpenDoors
- {
- get
- {
- return !this.Body.IsAnimal && !this.Body.IsSea;
- }
- }
- public virtual bool CanMoveOverObstacles
- {
- get
- {
- return this.Body.IsMonster;
- }
- }
- public virtual bool CanDestroyObstacles
- {
- get
- {
- // to enable breaking of furniture, 'return CanMoveOverObstacles;'
- return false;
- }
- }
- public override void OnDamage(int amount, Mobile from, bool willKill)
- {
- WeightOverloading.FatigueOnDamage(this, amount);
- InhumanSpeech speechType = this.SpeechType;
- if (speechType != null && !willKill)
- speechType.OnDamage(this, amount);
- base.OnDamage(amount, from, willKill);
- }
- public virtual void OnDamagedBySpell(Mobile from)
- {
- }
- public virtual void AlterDamageScalarFrom(Mobile caster, ref double scalar)
- {
- }
- public virtual void AlterDamageScalarTo(Mobile target, ref double scalar)
- {
- }
- public virtual void AlterMeleeDamageFrom(Mobile from, ref int damage)
- {
- }
- public virtual void AlterMeleeDamageTo(Mobile to, ref int damage)
- {
- }
- public virtual void CheckReflect(Mobile caster, ref bool reflect)
- {
- }
- public virtual void OnCarve(Mobile from, Corpse corpse)
- {
- int feathers = Feathers;
- int wool = Wool;
- int meat = Meat;
- int hides = Hides;
- int scales = Scales;
- if ((feathers == 0 && wool == 0 && meat == 0 && hides == 0 && scales == 0) || Summoned || IsBonded)
- {
- from.SendLocalizedMessage(500485); // You see nothing useful to carve from the corpse.
- }
- else
- {
- if (corpse.Map == Map.Felucca)
- {
- feathers *= 2;
- wool *= 2;
- hides *= 2;
- }
- new Blood(0x122D).MoveToWorld(corpse.Location, corpse.Map);
- if (feathers != 0)
- {
- corpse.DropItem(new Feather(feathers));
- from.SendLocalizedMessage(500479); // You pluck the bird. The feathers are now on the corpse.
- }
- if (wool != 0)
- {
- corpse.DropItem(new Wool(wool));
- from.SendLocalizedMessage(500483); // You shear it, and the wool is now on the corpse.
- }
- if (meat != 0)
- {
- if (MeatType == MeatType.Ribs)
- corpse.DropItem(new RawRibs(meat));
- else if (MeatType == MeatType.Bird)
- corpse.DropItem(new RawBird(meat));
- else if (MeatType == MeatType.LambLeg)
- corpse.DropItem(new RawLambLeg(meat));
- else if (MeatType == MeatType.Chicken)
- corpse.DropItem(new RawChickenLeg(meat));
- from.SendLocalizedMessage(500467); // You carve some meat, which remains on the corpse.
- }
- if (hides != 0)
- {
- if (HideType == HideType.Regular)
- corpse.DropItem(new Hides(hides));
- else if (HideType == HideType.Spined)
- corpse.DropItem(new SpinedHides(hides));
- else if (HideType == HideType.Horned)
- corpse.DropItem(new HornedHides(hides));
- else if (HideType == HideType.Barbed)
- corpse.DropItem(new BarbedHides(hides));
- from.SendLocalizedMessage(500471); // You skin it, and the hides are now in the corpse.
- }
- if (scales != 0)
- {
- ScaleType sc = this.ScaleType;
- switch (sc)
- {
- case ScaleType.Red: corpse.DropItem(new RedScales(scales)); break;
- case ScaleType.Yellow: corpse.DropItem(new YellowScales(scales)); break;
- case ScaleType.Black: corpse.DropItem(new BlackScales(scales)); break;
- case ScaleType.Green: corpse.DropItem(new GreenScales(scales)); break;
- case ScaleType.White: corpse.DropItem(new WhiteScales(scales)); break;
- case ScaleType.Blue: corpse.DropItem(new BlueScales(scales)); break;
- case ScaleType.All:
- {
- corpse.DropItem(new RedScales(scales));
- corpse.DropItem(new YellowScales(scales));
- corpse.DropItem(new BlackScales(scales));
- corpse.DropItem(new GreenScales(scales));
- corpse.DropItem(new WhiteScales(scales));
- corpse.DropItem(new BlueScales(scales));
- break;
- }
- }
- from.SendMessage("You cut away some scales, but they remain on the corpse.");
- }
- corpse.Carved = true;
- if (corpse.IsCriminalAction(from))
- from.CriminalAction(true);
- }
- }
- public const int DefaultRangePerception = 16;
- public const int OldRangePerception = 10;
- public BaseCreature(AIType ai,
- FightMode mode,
- int iRangePerception,
- int iRangeFight,
- double dActiveSpeed,
- double dPassiveSpeed)
- {
- if (iRangePerception == OldRangePerception)
- iRangePerception = DefaultRangePerception;
- m_Loyalty = PetLoyalty.WonderfullyHappy;
- m_CurrentAI = ai;
- m_DefaultAI = ai;
- m_iRangePerception = iRangePerception;
- m_iRangeFight = iRangeFight;
- m_FightMode = mode;
- m_iTeam = 0;
- SpeedInfo.GetSpeeds(this, ref dActiveSpeed, ref dPassiveSpeed);
- m_dActiveSpeed = dActiveSpeed;
- m_dPassiveSpeed = dPassiveSpeed;
- m_dCurrentSpeed = dPassiveSpeed;
- m_bDebugAI = false;
- m_arSpellAttack = new ArrayList();
- m_arSpellDefense = new ArrayList();
- m_bControled = false;
- m_ControlMaster = null;
- m_ControlTarget = null;
- m_ControlOrder = OrderType.None;
- m_bTamable = false;
- m_Owners = new ArrayList();
- m_NextReaquireTime = DateTime.Now + ReaquireDelay;
- ChangeAIType(AI);
- InhumanSpeech speechType = this.SpeechType;
- if (speechType != null)
- speechType.OnConstruct(this);
- GenerateLoot(true);
- }
- public BaseCreature(Serial serial)
- : base(serial)
- {
- m_arSpellAttack = new ArrayList();
- m_arSpellDefense = new ArrayList();
- m_bDebugAI = false;
- }
- public override void Serialize(GenericWriter writer)
- {
- base.Serialize(writer);
- writer.Write((int)17); // version
- writer.Write((int)m_LootLevel);
- writer.Write(Frozen);
- writer.Write(m_IsSystemInitialized);
- writer.Write(m_ShowNameTag);
- writer.Write(m_SayingsEnabled);
- writer.Write(m_SayingsSecondsDelay);
- writer.Write(m_Saying1);
- writer.Write(m_Saying2);
- writer.Write(m_Saying3);
- writer.Write(m_Saying4);
- writer.Write(m_Saying5);
- writer.Write((int)m_CurrentAI);
- writer.Write((int)m_DefaultAI);
- writer.Write((int)m_iRangePerception);
- writer.Write((int)m_iRangeFight);
- writer.Write((int)m_iTeam);
- writer.Write((double)m_dActiveSpeed);
- writer.Write((double)m_dPassiveSpeed);
- writer.Write((double)m_dCurrentSpeed);
- writer.Write((int)m_pHome.X);
- writer.Write((int)m_pHome.Y);
- writer.Write((int)m_pHome.Z);
- // Version 1
- writer.Write((int)m_iRangeHome);
- int i = 0;
- writer.Write((int)m_arSpellAttack.Count);
- for (i = 0; i < m_arSpellAttack.Count; i++)
- {
- writer.Write(m_arSpellAttack[i].ToString());
- }
- writer.Write((int)m_arSpellDefense.Count);
- for (i = 0; i < m_arSpellDefense.Count; i++)
- {
- writer.Write(m_arSpellDefense[i].ToString());
- }
- // Version 2
- writer.Write((int)m_FightMode);
- writer.Write((bool)m_bControled);
- writer.Write((Mobile)m_ControlMaster);
- writer.Write((Mobile)m_ControlTarget);
- writer.Write((Point3D)m_ControlDest);
- writer.Write((int)m_ControlOrder);
- writer.Write((double)m_dMinTameSkill);
- // Removed in version 9
- //writer.Write( (double) m_dMaxTameSkill );
- writer.Write((bool)m_bTamable);
- writer.Write((bool)m_bSummoned);
- if (m_bSummoned)
- writer.WriteDeltaTime(m_SummonEnd);
- writer.Write((int)m_iControlSlots);
- // Version 3
- writer.Write((int)m_Loyalty);
- // Version 4
- writer.Write(m_CurrentWayPoint);
- // Verison 5
- writer.Write(m_SummonMaster);
- // Version 6
- writer.Write((int)m_HitsMax);
- writer.Write((int)m_StamMax);
- writer.Write((int)m_ManaMax);
- writer.Write((int)m_DamageMin);
- writer.Write((int)m_DamageMax);
- // Version 7
- writer.Write((int)m_PhysicalResistance);
- writer.Write((int)m_PhysicalDamage);
- writer.Write((int)m_FireResistance);
- writer.Write((int)m_FireDamage);
- writer.Write((int)m_ColdResistance);
- writer.Write((int)m_ColdDamage);
- writer.Write((int)m_PoisonResistance);
- writer.Write((int)m_PoisonDamage);
- writer.Write((int)m_EnergyResistance);
- writer.Write((int)m_EnergyDamage);
- // Version 8
- writer.WriteMobileList(m_Owners, true);
- // Version 10
- writer.Write((bool)m_IsDeadPet);
- writer.Write((bool)m_IsBonded);
- writer.Write((DateTime)m_BondingBegin);
- writer.Write((DateTime)m_OwnerAbandonTime);
- // Version 11
- writer.Write((bool)m_HasGeneratedLoot);
- // Version 12
- writer.Write((int)Erudition);
- //// Version 13
- //writer.Write((int)m_FearLove.Count);
- //foreach (Mobile mobile in m_FearLove.Keys)
- //{
- // writer.Write((Mobile)mobile);
- // writer.Write((double)m_FearLove[mobile]);
- //}
- //writer.Write((int)m_Hate.Count);
- //foreach (Mobile mobile in m_Hate.Keys)
- //{
- // writer.Write((Mobile)mobile);
- // writer.Write((double)m_Hate[mobile]);
- //}
- }
- private static double[] m_StandardActiveSpeeds = new double[]
- {
- 0.175, 0.1, 0.15, 0.2, 0.25, 0.3, 0.4, 0.5, 0.6, 0.8
- };
- private static double[] m_StandardPassiveSpeeds = new double[]
- {
- 0.350, 0.2, 0.4, 0.5, 0.6, 0.8, 1.0, 1.2, 1.6, 2.0
- };
- public override void Deserialize(GenericReader reader)
- {
- base.Deserialize(reader);
- int version = reader.ReadInt();
- if (version >= 17)
- {
- m_LootLevel = (LootPackLevel)reader.ReadInt();
- }
- if (version >= 16)
- {
- Frozen = reader.ReadBool();
- }
- if (version >= 15)
- {
- m_IsSystemInitialized = reader.ReadBool();
- }
- if (version >= 14)
- {
- m_ShowNameTag = reader.ReadBool();
- }
- if (version >= 13)
- {
- m_SayingsEnabled = reader.ReadBool();
- m_SayingsSecondsDelay = reader.ReadInt();
- m_Saying1 = reader.ReadString();
- m_Saying2 = reader.ReadString();
- m_Saying3 = reader.ReadString();
- m_Saying4 = reader.ReadString();
- m_Saying5 = reader.ReadString();
- m_SayingsDelay = TimeSpan.FromSeconds(m_SayingsSecondsDelay);
- }
- m_CurrentAI = (AIType)reader.ReadInt();
- m_DefaultAI = (AIType)reader.ReadInt();
- m_iRangePerception = reader.ReadInt();
- m_iRangeFight = reader.ReadInt();
- m_iTeam = reader.ReadInt();
- m_dActiveSpeed = reader.ReadDouble();
- m_dPassiveSpeed = reader.ReadDouble();
- m_dCurrentSpeed = reader.ReadDouble();
- double activeSpeed = m_dActiveSpeed;
- double passiveSpeed = m_dPassiveSpeed;
- SpeedInfo.GetSpeeds(this, ref activeSpeed, ref passiveSpeed);
- bool isStandardActive = false;
- for (int i = 0; !isStandardActive && i < m_StandardActiveSpeeds.Length; ++i)
- isStandardActive = (m_dActiveSpeed == m_StandardActiveSpeeds[i]);
- bool isStandardPassive = false;
- for (int i = 0; !isStandardPassive && i < m_StandardPassiveSpeeds.Length; ++i)
- isStandardPassive = (m_dPassiveSpeed == m_StandardPassiveSpeeds[i]);
- if (isStandardActive && m_dCurrentSpeed == m_dActiveSpeed)
- m_dCurrentSpeed = activeSpeed;
- else if (isStandardPassive && m_dCurrentSpeed == m_dPassiveSpeed)
- m_dCurrentSpeed = passiveSpeed;
- if (isStandardActive)
- m_dActiveSpeed = activeSpeed;
- if (isStandardPassive)
- m_dPassiveSpeed = passiveSpeed;
- if (m_iRangePerception == OldRangePerception)
- m_iRangePerception = DefaultRangePerception;
- m_pHome.X = reader.ReadInt();
- m_pHome.Y = reader.ReadInt();
- m_pHome.Z = reader.ReadInt();
- if (version >= 1)
- {
- m_iRangeHome = reader.ReadInt();
- int i, iCount;
- iCount = reader.ReadInt();
- for (i = 0; i < iCount; i++)
- {
- string str = reader.ReadString();
- Type type = Type.GetType(str);
- if (type != null)
- {
- m_arSpellAttack.Add(type);
- }
- }
- iCount = reader.ReadInt();
- for (i = 0; i < iCount; i++)
- {
- string str = reader.ReadString();
- Type type = Type.GetType(str);
- if (type != null)
- {
- m_arSpellDefense.Add(type);
- }
- }
- }
- else
- {
- m_iRangeHome = 0;
- }
- if (version >= 2)
- {
- m_FightMode = (FightMode)reader.ReadInt();
- m_bControled = reader.ReadBool();
- m_ControlMaster = reader.ReadMobile();
- m_ControlTarget = reader.ReadMobile();
- m_ControlDest = reader.ReadPoint3D();
- m_ControlOrder = (OrderType)reader.ReadInt();
- m_dMinTameSkill = reader.ReadDouble();
- if (version < 9)
- reader.ReadDouble();
- m_bTamable = reader.ReadBool();
- m_bSummoned = reader.ReadBool();
- if (m_bSummoned)
- {
- m_SummonEnd = reader.ReadDeltaTime();
- new UnsummonTimer(m_ControlMaster, this, m_SummonEnd - DateTime.Now).Start();
- }
- m_iControlSlots = reader.ReadInt();
- }
- else
- {
- m_FightMode = FightMode.Closest;
- m_bControled = false;
- m_ControlMaster = null;
- m_ControlTarget = null;
- m_ControlOrder = OrderType.None;
- }
- if (version >= 3)
- m_Loyalty = (PetLoyalty)reader.ReadInt();
- else
- m_Loyalty = PetLoyalty.WonderfullyHappy;
- if (version >= 4)
- m_CurrentWayPoint = reader.ReadItem() as WayPoint;
- if (version >= 5)
- m_SummonMaster = reader.ReadMobile();
- if (version >= 6)
- {
- m_HitsMax = reader.ReadInt();
- m_StamMax = reader.ReadInt();
- m_ManaMax = reader.ReadInt();
- m_DamageMin = reader.ReadInt();
- m_DamageMax = reader.ReadInt();
- }
- if (version >= 7)
- {
- m_PhysicalResistance = reader.ReadInt();
- m_PhysicalDamage = reader.ReadInt();
- m_FireResistance = reader.ReadInt();
- m_FireDamage = reader.ReadInt();
- m_ColdResistance = reader.ReadInt();
- m_ColdDamage = reader.ReadInt();
- m_PoisonResistance = reader.ReadInt();
- m_PoisonDamage = reader.ReadInt();
- m_EnergyResistance = reader.ReadInt();
- m_EnergyDamage = reader.ReadInt();
- }
- if (version >= 8)
- m_Owners = reader.ReadMobileList();
- else
- m_Owners = new ArrayList();
- if (version >= 10)
- {
- m_IsDeadPet = reader.ReadBool();
- m_IsBonded = reader.ReadBool();
- m_BondingBegin = reader.ReadDateTime();
- m_OwnerAbandonTime = reader.ReadDateTime();
- }
- if (version >= 11)
- m_HasGeneratedLoot = reader.ReadBool();
- else
- m_HasGeneratedLoot = true;
- if (version >= 12)
- Erudition = reader.ReadInt();
- else
- Erudition = 0;
- CheckStatTimers();
- ChangeAIType(m_CurrentAI);
- AddFollowers();
- if (IsAnimatedDead)
- Spells.Necromancy.AnimateDeadSpell.Register(m_SummonMaster, this);
- }
- #region Fonction ObjectPropertyList
- public override void AddNameProperties(ObjectPropertyList list)
- {
- base.AddNameProperties(list);
- if (Controled && Commandable)
- {
- if (Summoned)
- list.Add(1049646); // (summoned)
- else if (IsBonded)
- list.Add(1049608); // (bonded)
- else
- list.Add(502006); // (tame)
- }
- }
- public override void GetProperties(ObjectPropertyList list)
- {
- base.GetProperties(list);
- }
- protected int m_Erudition = 0;
- [CommandProperty(AccessLevel.GameMaster)]
- public int Erudition
- {
- get { return m_Erudition; }
- set { m_Erudition = value; }
- }
- public override void SendPropertiesTo(Mobile from)
- {
- ObjectPropertyList opl = new ObjectPropertyList(this);
- string name = Name;
- if (from is RacePlayerMobile && (!(this is BaseVendor)))
- {
- RacePlayerMobile pmf = (RacePlayerMobile)from;
- if (pmf.AccessLevel > AccessLevel.Player)
- {
- // SI GM
- if (pmf.Capacities[CapacityName.Lore].Value < Erudition)
- {//pas �rudit
- opl.Add(1050045, "{0} \t{1}\t {2}", "", "Cr�ature", ""); // ~1_PREFIX~~2_NAME~~3_SUFFIX~
- }
- else
- {//Assez �rudit
- opl.Add(1050045, "{0} \t{1}\t {2}", "", name, ""); // ~1_PREFIX~~2_NAME~~3_SUFFIX~
- }
- }
- else
- {
- // SI PJ
- if (pmf.Capacities[CapacityName.Lore].Value < Erudition)
- {//pas �rudit
- opl.Add(1050045, "{0} \t{1}\t {2}", "", "Cr�ature", ""); // ~1_PREFIX~~2_NAME~~3_SUFFIX~
- }
- else
- {//Assez �rudit
- opl.Add(1050045, "{0} \t{1}\t {2}", "", name, ""); // ~1_PREFIX~~2_NAME~~3_SUFFIX~
- }
- }
- }
- //from.Send(opl);
- base.SendPropertiesTo(from);
- }
- private static ArrayList m_Hears;
- private static ArrayList m_OnSpeech;
- private static bool m_NoSpeechLOS1;
- [CommandProperty(AccessLevel.GameMaster)]
- public static bool NoSpeechLOS1 { get { return m_NoSpeechLOS1; } set { m_NoSpeechLOS1 = value; } }
- public override bool CanSee(Mobile m)
- {
- //SendPropertiesTo(this);
- //SendPropertiesTo(m);
- return base.CanSee(m);
- }
- public override void DoSpeech(string text, int[] keywords, MessageType type, int hue)
- {
- // base.DoSpeech(text, keywords, type, hue);
- if (Commands.Handle(this, text))
- return;
- int range = 12;
- switch (type)
- {
- case MessageType.Regular: this.SpeechHue = hue; break;
- case MessageType.Emote: this.EmoteHue = hue; break;
- case MessageType.Whisper: this.WhisperHue = hue; range = 2; break;
- case MessageType.Yell:
- this.YellHue = hue; range = 18;
- range = 18;
- break;
- default: type = MessageType.Regular; break;
- }
- SpeechEventArgs regArgs = new SpeechEventArgs(this, text, type, hue, keywords);
- EventSink.InvokeSpeech(regArgs);
- this.Region.OnSpeech(regArgs);
- OnSaid(regArgs);
- if (regArgs.Blocked)
- return;
- text = regArgs.Speech;
- if (text == null || text.Length == 0)
- return;
- if (m_Hears == null)
- m_Hears = new ArrayList();
- else if (m_Hears.Count > 0)
- m_Hears.Clear();
- if (m_OnSpeech == null)
- m_OnSpeech = new ArrayList();
- else if (m_OnSpeech.Count > 0)
- m_OnSpeech.Clear();
- ArrayList hears = m_Hears;
- ArrayList onSpeech = m_OnSpeech;
- if (this.Map != null)
- {
- IPooledEnumerable eable = this.Map.GetObjectsInRange(this.Location, range);
- foreach (object o in eable)
- {
- if (o is Mobile)
- {
- Mobile heard = (Mobile)o;
- if (heard.CanSee(this) && (m_NoSpeechLOS1 || !heard.Player || heard.InLOS(this)))
- {
- if (heard.NetState != null)
- hears.Add(heard);
- if (heard.HandlesOnSpeech(this))
- onSpeech.Add(heard);
- for (int i = 0; i < heard.Items.Count; ++i)
- {
- Item item = (Item)heard.Items[i];
- if (item.HandlesOnSpeech)
- onSpeech.Add(item);
- //if (item is Container)
- // AddSpeechItemsFrom(onSpeech, (Container)item);
- }
- }
- }
- else if (o is Item)
- {
- if (((Item)o).HandlesOnSpeech)
- onSpeech.Add(o);
- //if (o is Container)
- // AddSpeechItemsFrom(onSpeech, (Container)o);
- }
- }
- //eable.Free();
- object mutateContext = null;
- string mutatedText = text;
- SpeechEventArgs mutatedArgs = null;
- if (MutateSpeech(hears, ref mutatedText, ref mutateContext))
- mutatedArgs = new SpeechEventArgs(this, mutatedText, type, hue, new int[0]);
- CheckSpeechManifest();
- ProcessDelta();
- Packet regp = null;
- Packet mutp = null;
- for (int i = 0; i < hears.Count; ++i)
- {
- Mobile heard = (Mobile)hears[i];
- //SendPropertiesTo(heard);
- if (mutatedArgs == null || !CheckHearsMutatedSpeech(heard, mutateContext))
- {
- heard.OnSpeech(regArgs);
- NetState ns = heard.NetState;
- if (ns != null)
- {
- string name = Name;
- RacePlayerMobile pmf = (RacePlayerMobile)(ns.Mobile);
- if (pmf.Capacities[CapacityName.Lore].Value < Erudition)
- {//pas �rudit
- name = "Cr�ature";
- }
- if (type == MessageType.Yell)
- {
- regp = new UnicodeMessage(this.Serial, Body, type, this.EmoteHue, 3, this.Language, name, "*crie*");
- regp = new UnicodeMessage(this.Serial, Body, type, hue, 3, this.Language, name, text);
- }
- else if (type == MessageType.Whisper)
- {
- regp = new UnicodeMessage(this.Serial, Body, type, this.EmoteHue, 3, this.Language, name, "*murmure*");
- regp = new UnicodeMessage(this.Serial, Body, type, hue, 3, this.Language, name, text);
- }
- else
- regp = new UnicodeMessage(this.Serial, Body, type, hue, 3, this.Language, name, text);
- if (regp == null)
- {
- // string name = Name;
- // name = this.TrouverNom(heard.Serial.Value);
- // if (name == "-1")
- //{
- // if (this.Female)
- // name = "Inconnue";
- // else
- // name = "Inconnu";
- // }
- //regp = new UnicodeMessage(this.Serial, Body, type, hue, 3, this.Language, Convert.ToString(this.Serial.Value) + " � " + Convert.ToString(heard.Serial.Value), text);
- }
- ns.Send(regp);
- }
- }
- else
- {
- heard.OnSpeech(mutatedArgs);
- NetState ns = heard.NetState;
- if (ns != null)
- {
- //if (mutp == null)
- // {
- string name = Name;
- RacePlayerMobile pmf = (RacePlayerMobile)(ns.Mobile);
- if (pmf.Capacities[CapacityName.Lore].Value < Erudition)
- {//pas �rudit
- name = "Cr�ature";
- }
- mutp = new UnicodeMessage(this.Serial, Body, type, hue, 3, this.Language, name, mutatedText);
- // }
- ns.Send(mutp);
- }
- }
- }
- //if (onSpeech.Count > 1)
- // onSpeech.Sort(LocationComparer.GetInstance(this));
- for (int i = 0; i < onSpeech.Count; ++i)
- {
- object obj = onSpeech[i];
- if (obj is Mobile)
- {
- Mobile heard = (Mobile)obj;
- if (mutatedArgs == null || !CheckHearsMutatedSpeech(heard, mutateContext))
- heard.OnSpeech(regArgs);
- else
- heard.OnSpeech(mutatedArgs);
- }
- else
- {
- Item item = (Item)obj;
- item.OnSpeech(regArgs);
- }
- }
- }
- }
- #endregion
- public virtual bool IsHumanInTown()
- {
- return (Body.IsHuman && Region is Regions.GuardedRegion);
- }
- public virtual bool CheckGold(Mobile from, Item dropped)
- {
- if (dropped is Gold)
- return OnGoldGiven(from, (Gold)dropped);
- return false;
- }
- public virtual bool OnGoldGiven(Mobile from, Gold dropped)
- {
- if (CheckTeachingMatch(from))
- {
- if (Teach(m_Teaching, from, dropped.Amount, true))
- {
- dropped.Delete();
- return true;
- }
- }
- else if (IsHumanInTown())
- {
- Direction = GetDirectionTo(from);
- int oldSpeechHue = this.SpeechHue;
- this.SpeechHue = 0x23F;
- SayTo(from, "Vous me donnez �a?");
- if (dropped.Amount >= 400)
- SayTo(from, "Hoo, c't'un bon cadeau.");
- else
- SayTo(from, "L'�cus sont toujours bienvenus.");
- this.SpeechHue = 0x3B2;
- SayTo(from, 501548); // I thank thee.
- this.SpeechHue = oldSpeechHue;
- dropped.Delete();
- return true;
- }
- return false;
- }
- public override bool ShouldCheckStatTimers { get { return false; } }
- private static Type[] m_Eggs = new Type[]
- {
- typeof( FriedEggs ), typeof( Eggs )
- };
- private static Type[] m_Fish = new Type[]
- {
- typeof( FishSteak ), typeof( RawFishSteak )
- };
- private static Type[] m_GrainsAndHay = new Type[]
- {
- typeof( BreadLoaf ), typeof( FrenchBread )
- };
- private static Type[] m_Meat = new Type[]
- {
- /* Cooked */
- typeof( Bacon ), typeof( CookedBird ), typeof( Sausage ),
- typeof( Ham ), typeof( Ribs ), typeof( LambLeg ),
- typeof( ChickenLeg ),
- /* Uncooked */
- typeof( RawBird ), typeof( RawRibs ), typeof( RawLambLeg ),
- typeof( RawChickenLeg ),
- /* Body Parts */
- typeof( Head ), typeof( LeftArm ), typeof( LeftLeg ),
- typeof( Torso ), typeof( RightArm ), typeof( RightLeg )
- };
- private static Type[] m_FruitsAndVegies = new Type[]
- {
- typeof( HoneydewMelon ), typeof( YellowGourd ), typeof( GreenGourd ),
- typeof( Banana ), typeof( Bananas ), typeof( Lemon ), typeof( Lime ),
- typeof( Dates ), typeof( Grapes ), typeof( Peach ), typeof( Pear ),
- typeof( Apple ), typeof( Watermelon ), typeof( Squash ),
- typeof( Cantaloupe ), typeof( Carrot ), typeof( Cabbage ),
- typeof( Onion ), typeof( Lettuce ), typeof( Pumpkin )
- };
- private static Type[] m_Gold = new Type[]
- {
- // white wyrms eat gold..
- typeof( Gold )
- };
- public virtual bool CheckFoodPreference(Item f)
- {
- if (CheckFoodPreference(f, FoodType.Eggs, m_Eggs))
- return true;
- if (CheckFoodPreference(f, FoodType.Fish, m_Fish))
- return true;
- if (CheckFoodPreference(f, FoodType.GrainsAndHay, m_GrainsAndHay))
- return true;
- if (CheckFoodPreference(f, FoodType.Meat, m_Meat))
- return true;
- if (CheckFoodPreference(f, FoodType.FruitsAndVegies, m_FruitsAndVegies))
- return true;
- if (CheckFoodPreference(f, FoodType.Gold, m_Gold))
- return true;
- return false;
- }
- public virtual bool CheckFoodPreference(Item fed, FoodType type, Type[] types)
- {
- if ((FavoriteFood & type) == 0)
- return false;
- Type fedType = fed.GetType();
- bool contains = false;
- for (int i = 0; !contains && i < types.Length; ++i)
- contains = (fedType == types[i]);
- return contains;
- }
- public virtual bool CheckFeed(Mobile from, Item dropped)
- {
- if (!IsDeadPet && Controled && ControlMaster == from && (dropped is Food || dropped is Gold || dropped is CookableFood || dropped is Head || dropped is LeftArm || dropped is LeftLeg || dropped is Torso || dropped is RightArm || dropped is RightLeg))
- {
- Item f = dropped;
- if (CheckFoodPreference(f))
- {
- int amount = f.Amount;
- if (amount > 0)
- {
- bool happier = false;
- int stamGain;
- if (f is Gold)
- stamGain = amount - 50;
- else
- stamGain = (amount * 15) - 50;
- if (stamGain > 0)
- Stam += stamGain;
- for (int i = 0; i < amount; ++i)
- {
- if (m_Loyalty < PetLoyalty.WonderfullyHappy && 0.5 >= Utility.RandomDouble())
- {
- ++m_Loyalty;
- happier = true;
- }
- }
- if (happier)
- SayTo(from, 502060); // Your pet looks happier.
- if (Body.IsAnimal)
- Animate(3, 5, 1, true, false, 0);
- else if (Body.IsMonster)
- Animate(17, 5, 1, true, false, 0);
- if (IsBondable && !IsBonded)
- {
- Mobile master = m_ControlMaster;
- if (master != null)
- {
- if (m_dMinTameSkill <= 29.1 || master.Skills[SkillName.AnimalTaming].Value >= m_dMinTameSkill || this is SwampDragon || this is Ridgeback || this is SavageRidgeback)
- {
- if (BondingBegin == DateTime.MinValue)
- {
- BondingBegin = DateTime.Now;
- }
- else if ((BondingBegin + BondingDelay) <= DateTime.Now)
- {
- IsBonded = true;
- BondingBegin = DateTime.MinValue;
- from.SendLocalizedMessage(1049666); // Your pet has bonded with you!
- }
- }
- }
- }
- dropped.Delete();
- return true;
- }
- }
- }
- return false;
- }
- public virtual void OnActionWander()
- {
- }
- public virtual void OnActionCombat()
- {
- }
- public virtual void OnActionGuard()
- {
- }
- public virtual void OnActionFlee()
- {
- }
- public virtual void OnActionInteract()
- {
- }
- public virtual void OnActionBackoff()
- {
- }
- public override bool OnDragDrop(Mobile from, Item dropped)
- {
- if (CheckFeed(from, dropped))
- return true;
- else if (CheckGold(from, dropped))
- return true;
- return base.OnDragDrop(from, dropped);
- }
- public virtual void ChangeAIType(AIType NewAI)
- {
- if (m_AI != null)
- m_AI.m_Timer.Stop();
- m_AI = null;
- switch (NewAI)
- {
- case AIType.AI_Melee:
- m_AI = new MeleeAI(this);
- break;
- case AIType.AI_CriminalsGuard:
- m_AI = new CriminalsGuardAI(this);
- break;
- case AIType.AI_Animal:
- m_AI = new AnimalAI(this);
- break;
- case AIType.AI_Berserk:
- m_AI = new BerserkAI(this);
- break;
- case AIType.AI_Archer:
- m_AI = new ArcherAI(this);
- break;
- case AIType.AI_Healer:
- m_AI = new HealerAI(this);
- break;
- case AIType.AI_Vendor:
- m_AI = new VendorAI(this);
- break;
- case AIType.AI_Mage:
- m_AI = new MageAI(this);
- break;
- case AIType.AI_Predator:
- //m_AI = new PredatorAI(this);
- m_AI = new MeleeAI(this);
- break;
- case AIType.AI_Thief:
- m_AI = new ThiefAI(this);
- break;
- }
- }
- public virtual void ChangeAIToDefault()
- {
- ChangeAIType(m_DefaultAI);
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public AIType AI
- {
- get
- {
- return m_CurrentAI;
- }
- set
- {
- m_CurrentAI = value;
- if (m_CurrentAI == AIType.AI_Use_Default)
- {
- m_CurrentAI = m_DefaultAI;
- }
- ChangeAIType(m_CurrentAI);
- }
- }
- [CommandProperty(AccessLevel.Administrator)]
- public bool Debug
- {
- get
- {
- return m_bDebugAI;
- }
- set
- {
- m_bDebugAI = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public int Team
- {
- get
- {
- return m_iTeam;
- }
- set
- {
- m_iTeam = value;
- OnTeamChange();
- }
- }
- public virtual void OnTeamChange()
- {
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public Mobile FocusMob
- {
- get
- {
- return m_FocusMob;
- }
- set
- {
- m_FocusMob = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public FightMode FightMode
- {
- get
- {
- return m_FightMode;
- }
- set
- {
- m_FightMode = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public int RangePerception
- {
- get
- {
- return m_iRangePerception;
- }
- set
- {
- m_iRangePerception = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public int RangeFight
- {
- get
- {
- return m_iRangeFight;
- }
- set
- {
- m_iRangeFight = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public int RangeHome
- {
- get
- {
- return m_iRangeHome;
- }
- set
- {
- m_iRangeHome = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public double ActiveSpeed
- {
- get
- {
- return m_dActiveSpeed;
- }
- set
- {
- m_dActiveSpeed = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public double PassiveSpeed
- {
- get
- {
- return m_dPassiveSpeed;
- }
- set
- {
- m_dPassiveSpeed = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public double CurrentSpeed
- {
- get
- {
- return m_dCurrentSpeed;
- }
- set
- {
- if (m_dCurrentSpeed != value)
- {
- m_dCurrentSpeed = value;
- if (m_AI != null)
- m_AI.OnCurrentSpeedChanged();
- }
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public Point3D Home
- {
- get
- {
- return m_pHome;
- }
- set
- {
- m_pHome = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public bool Controled
- {
- get
- {
- return m_bControled;
- }
- set
- {
- if (m_bControled == value)
- return;
- m_bControled = value;
- Delta(MobileDelta.Noto);
- InvalidateProperties();
- }
- }
- public override void RevealingAction()
- {
- Spells.Sixth.InvisibilitySpell.RemoveTimer(this);
- base.RevealingAction();
- }
- public void RemoveFollowers()
- {
- if (m_ControlMaster != null)
- m_ControlMaster.Followers -= ControlSlots;
- else if (m_SummonMaster != null)
- m_SummonMaster.Followers -= ControlSlots;
- if (m_ControlMaster != null && m_ControlMaster.Followers < 0)
- m_ControlMaster.Followers = 0;
- if (m_SummonMaster != null && m_SummonMaster.Followers < 0)
- m_SummonMaster.Followers = 0;
- }
- public void AddFollowers()
- {
- if (m_ControlMaster != null)
- m_ControlMaster.Followers += ControlSlots;
- else if (m_SummonMaster != null)
- m_SummonMaster.Followers += ControlSlots;
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public Mobile ControlMaster
- {
- get
- {
- return m_ControlMaster;
- }
- set
- {
- if (m_ControlMaster == value)
- return;
- RemoveFollowers();
- m_ControlMaster = value;
- AddFollowers();
- Delta(MobileDelta.Noto);
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public Mobile SummonMaster
- {
- get
- {
- return m_SummonMaster;
- }
- set
- {
- if (m_SummonMaster == value)
- return;
- RemoveFollowers();
- m_SummonMaster = value;
- AddFollowers();
- Delta(MobileDelta.Noto);
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public Mobile ControlTarget
- {
- get
- {
- return m_ControlTarget;
- }
- set
- {
- m_ControlTarget = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public Point3D ControlDest
- {
- get
- {
- return m_ControlDest;
- }
- set
- {
- m_ControlDest = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public OrderType ControlOrder
- {
- get
- {
- return m_ControlOrder;
- }
- set
- {
- m_ControlOrder = value;
- if (m_AI != null)
- m_AI.OnCurrentOrderChanged();
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public bool BardProvoked
- {
- get
- {
- return m_bBardProvoked;
- }
- set
- {
- m_bBardProvoked = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public bool BardPacified
- {
- get
- {
- return m_bBardPacified;
- }
- set
- {
- m_bBardPacified = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public Mobile BardMaster
- {
- get
- {
- return m_bBardMaster;
- }
- set
- {
- m_bBardMaster = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public Mobile BardTarget
- {
- get
- {
- return m_bBardTarget;
- }
- set
- {
- m_bBardTarget = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public DateTime BardEndTime
- {
- get
- {
- return m_timeBardEnd;
- }
- set
- {
- m_timeBardEnd = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public double MinTameSkill
- {
- get
- {
- return m_dMinTameSkill;
- }
- set
- {
- m_dMinTameSkill = value;
- }
- }
- [CommandProperty(AccessLevel.GameMaster)]
- public bool Tamable
- {
- get
- {
- return m_bTamable;
- }
- set
- {
- m_bTamable = value;
- }
- }
- [CommandProperty(AccessLevel.Administrator)]
- public bool Summoned
- {
- get
- {
- return m_bSummoned;
- }
- set
- {
- if (m_bSummoned == value)
- return;
- m_NextReaquireTime = DateTime.Now;
- m_bSummoned = value;
- Delta(MobileDelta.Noto);
- InvalidateProperties();
- }
- }
- [CommandProperty(AccessLevel.Administrator)]
- public int ControlSlots
- {
- get
- {
- return m_iControlSlots;
- }
- set
- {
- m_iControlSlots = value;
- }
- }
- public virtual bool NoHouseRestrictions { get { return false; } }
- public virtual bool IsHouseSummonable { get { return false; } }
- public virtual int Feathers { get { return 0; } }
- public virtual int Wool { get { return 0; } }
- public virtual MeatType MeatType { get { return MeatType.Ribs; } }
- public virtual int Meat { get { return 0; } }
- public virtual int Hides { get { return 0; } }
- public virtual HideType HideType { get { return HideType.Regular; } }
- public virtual int Scales { get { return 0; } }
- public virtual ScaleType ScaleType { get { return ScaleType.Red; } }
- public virtual bool AutoDispel { get { return false; } }
- public virtual bool IsScaryToPets { get { return false; } }
- public virtual bool IsScaredOfScaryThings { get { return true; } }
- public virtual bool CanRummageCorpses { get { return false; } }
- public virtual void OnGotMeleeAttack(Mobile attacker)
- {
- if (AutoDispel && attacker is BaseCreature && ((BaseCreature)attacker).Summoned && !((BaseCreature)attacker).IsAnimatedDead)
- Dispel(attacker);
- }
- public virtual void Dispel(Mobile m)
- {
- Effects.SendLocationParticles(EffectItem.Create(m.Location, m.Map, EffectItem.DefaultDuration), 0x3728, 8, 20, 5042);
- Effects.PlaySound(m, m.Map, 0x201);
- m.Delete();
- }
- public virtual bool DeleteOnRelease { get { return m_bSummoned; } }
- public virtual void OnGaveMeleeAttack(Mobile defender)
- {
- Poison p = HitPoison;
- if (p != null && HitPoisonChance >= Utility.RandomDouble())
- defender.ApplyPoison(this, p);
- if (AutoDispel && defender is BaseCreature && ((BaseCreature)defender).Summoned && !((BaseCreature)defender).IsAnimatedDead)
- Dispel(defender);
- }
- public override void OnAfterDelete()
- {
- if (m_AI != null)
- {
- if (m_AI.m_Timer != null)
- m_AI.m_Timer.Stop();
- m_AI = null;
- }
- FocusMob = null;
- if (IsAnimatedDead)
- Spells.Necromancy.AnimateDeadSpell.Unregister(m_SummonMaster, this);
- base.OnAfterDelete();
- }
- public void DebugSay(string text)
- {
- if (m_bDebugAI)
- this.PublicOverheadMessage(MessageType.Regular, 41, false, text);
- }
- public void DebugSay(string format, params object[] args)
- {
- if (m_bDebugAI)
- this.PublicOverheadMessage(MessageType.Regular, 41, false, String.Format(format, args));
- }
- /*
- * Will need to be givent a better name
- *
- * This function can be overriden.. so a "Strongest" mobile, can have a different definition depending
- * on who check for value
- * -Could add a FightMode.Prefered
- *
- */
- public virtual double GetValueFrom(Mobile m, FightMode acqType, bool bPlayerOnly)
- {
- if ((bPlayerOnly && m.Player) || !bPlayerOnly)
- {
- switch (acqType)
- {
- case FightMode.Strongest:
- return (m.Skills[SkillName.Tactics].Value + m.Str); //returns strongest mobile
- case FightMode.Weakest:
- return -m.Hits; // returns weakest mobile
- default:
- return -GetDistanceToSqrt(m); // returns closest mobile
- }
- }
- else
- {
- return double.MinValue;
- }
- }
- // Turn, - for let, + for right
- // Basic for now, need works
- public virtual void Turn(int iTurnSteps)
- {
- int v = (int)Direction;
- Direction = (Direction)((((v & 0x7) + iTurnSteps) & 0x7) | (v & 0x80));
- }
- public virtual void TurnInternal(int iTurnSteps)
- {
- int v = (int)Direction;
- SetDirection((Direction)((((v & 0x7) + iTurnSteps) & 0x7) | (v & 0x80)));
- }
- public bool IsHurt()
- {
- return (Hits != HitsMax);
- }
- public double GetHomeDistance()
- {
- return GetDistanceToSqrt(m_pHome);
- }
- public virtual int GetTeamSize(int iRange)
- {
- int iCount = 0;
- foreach (Mobile m in this.GetMobilesInRange(iRange))
- {
- if (m is BaseCreature)
- {
- if (((BaseCreature)m).Team == Team)
- {
- if (!m.Deleted)
- {
- if (m != this)
- {
- if (CanSee(m))
- {
- iCount++;
- }
- }
- }
- }
- }
- }
- return iCount;
- }
- // Do my combatant is attaking me??
- public bool IsCombatantAnAgressor()
- {
- if (Combatant != null)
- {
- if (Combatant.Combatant == this)
- {
- return true;
- }
- }
- return false;
- }
- private class TameEntry : ContextMenuEntry
- {
- private BaseCreature m_Mobile;
- public TameEntry(Mobile from, BaseCreature creature)
- : base(6130, 6)
- {
- m_Mobile = creature;
- Enabled = Enabled && (from.Female ? creature.AllowFemaleTamer : creature.AllowMaleTamer);
- }
- public override void OnClick()
- {
- if (!Owner.From.CheckAlive())
- return;
- Owner.From.TargetLocked = true;
- SkillHandlers.AnimalTaming.DisableMessage = true;
- if (Owner.From.UseSkill(SkillName.AnimalTaming))
- Owner.From.Target.Invoke(Owner.From, m_Mobile);
- SkillHandlers.AnimalTaming.DisableMessage = false;
- Owner.From.TargetLocked = false;
- }
- }
- public virtual bool CanTeach { get { return false; } }
- public virtual bool CheckTeach(SkillName skill, Mobile from)
- {
- if (!CanTeach)
- return false;
- if (skill == SkillName.Stealth && from.Skills[SkillName.Hiding].Base < 80.0)
- return false;
- if (skill == SkillName.RemoveTrap && (from.Skills[SkillName.Lockpicking].Base < 50.0 || from.Skills[SkillName.DetectHidden].Base < 50.0))
- return false;
- if (!Core.AOS && (skill == SkillName.Focus || skill == SkillName.Chivalry || skill == SkillName.Necromancy))
- return false;
- return true;
- }
- public enum TeachResult
- {
- Success,
- Failure,
- KnowsMoreThanMe,
- KnowsWhatIKnow,
- SkillNotRaisable,
- NotEnoughFreePoints
- }
- public virtual TeachResult CheckTeachSkills(SkillName skill, Mobile m, int maxPointsToLearn, ref int pointsToLearn, bool doTeach)
- {
- if (!CheckTeach(skill, m) || !m.CheckAlive())
- return TeachResult.Failure;
- Skill ourSkill = Skills[skill];
- Skill theirSkill = m.Skills[skill];
- if (ourSkill == null || theirSkill == null)
- return TeachResult.Failure;
- int baseToSet = ourSkill.BaseFixedPoint / 3;
- if (baseToSet > 420)
- baseToSet = 420;
- else if (baseToSet < 200)
- return TeachResult.Failure;
- if (baseToSet > theirSkill.CapFixedPoint)
- baseToSet = theirSkill.CapFixedPoint;
- pointsToLearn = baseToSet - theirSkill.BaseFixedPoint;
- if (maxPointsToLearn > 0 && pointsToLearn > maxPointsToLearn)
- {
- pointsToLearn = maxPointsToLearn;
- baseToSet = theirSkill.BaseFixedPoint + pointsToLearn;
- }
- if (pointsToLearn < 0)
- return TeachResult.KnowsMoreThanMe;
- if (pointsToLearn == 0)
- return TeachResult.KnowsWhatIKnow;
- if (theirSkill.Lock != SkillLock.Up)
- return TeachResult.SkillNotRaisable;
- int freePoints = m.Skills.Cap - m.Skills.Total;
- int freeablePoints = 0;
- if (freePoints < 0)
- freePoints = 0;
- for (int i = 0; (freePoints + freeablePoints) < pointsToLearn && i < m.Skills.Length; ++i)
- {
- Skill sk = m.Skills[i];
- if (sk == theirSkill || sk.Lock != SkillLock.Down)
- continue;
- freeablePoints += sk.BaseFixedPoint;
- }
- if ((freePoints + freeablePoints) == 0)
- return TeachResult.NotEnoughFreePoints;
- if ((freePoints + freeablePoints) < pointsToLearn)
- {
- pointsToLearn = freePoints + freeablePoints;
- baseToSet = theirSkill.BaseFixedPoint + pointsToLearn;
- }
- if (doTeach)
- {
- int need = pointsToLearn - freePoints;
- for (int i = 0; need > 0 && i < m.Skills.Length; ++i)
- {
- Skill sk = m.Skills[i];
- if (sk == theirSkill || sk.Lock != SkillLock.Down)
- continue;
- if (sk.BaseFixedPoint < need)
- {
- need -= sk.BaseFixedPoint;
- sk.BaseFixedPoint = 0;
- }
- else
- {
- sk.BaseFixedPoint -= need;
- need = 0;
- }
- }
- /* Sanity check */
- if (baseToSet > theirSkill.CapFixedPoint || (m.Skills.Total - theirSkill.BaseFixedPoint + baseToSet) > m.Skills.Cap)
- return TeachResult.NotEnoughFreePoints;
- theirSkill.BaseFixedPoint = baseToSet;
- }
- return TeachResult.Success;
- }
- public virtual bool CheckTeachingMatch(Mobile m)
- {
- if (m_Teaching == (SkillName)(-1))
- return false;
- if (m is PlayerMobile)
- return (((PlayerMobile)m).Learning == m_Teaching);
- return true;
- }
- private SkillName m_Teaching = (SkillName)(-1);
- public virtual bool Teach(SkillName skill, Mobile m, int maxPointsToLearn, bool doTeach)
- {
- int pointsToLearn = 0;
- TeachResult res = CheckTeachSkills(skill, m, maxPointsToLearn, ref pointsToLearn, doTeach);
- switch (res)
- {
- case TeachResult.KnowsMoreThanMe:
- {
- Say(501508); // I cannot teach thee, for thou knowest more than I!
- break;
- }
- case TeachResult.KnowsWhatIKnow:
- {
- Say(501509); // I cannot teach thee, for thou knowest all I can teach!
- break;
- }
- case TeachResult.NotEnoughFreePoints:
- case TeachResult.SkillNotRaisable:
- {
- // Make sure this skill is marked to raise. If you are near the skill cap (700 points) you may need to lose some points in another skill first.
- m.SendLocalizedMessage(501510, "", 0x22);
- break;
- }
- case TeachResult.Success:
- {
- if (doTeach)
- {
- Say(501539); // Let me show thee something of how this is done.
- m.SendLocalizedMessage(501540); // Your skill level increases.
- m_Teaching = (SkillName)(-1);
- if (m is PlayerMobile)
- ((PlayerMobile)m).Learning = (SkillName)(-1);
- }
- else
- {
- // I will teach thee all I know, if paid the amount in full. The price is:
- Say(1019077, AffixType.Append, String.Format(" {0}", pointsToLearn), "");
- Say(1043108); // For less I shall teach thee less.
- m_Teaching = skill;
- if (m is PlayerMobile)
- ((PlayerMobile)m).Learning = skill;
- }
- return true;
- }
- }
- return false;
- }
- public override void AggressiveAction(Mobile aggressor, bool criminal)
- {
- base.AggressiveAction(aggressor, criminal);
- StopFlee();
- ForceReaquire();
- OrderType ct = m_ControlOrder;
- if (aggressor.ChangingCombatant && (m_bControled || m_bSummoned) && (ct == OrderType.Come || ct == OrderType.Stay || ct == OrderType.Stop || ct == OrderType.None || ct == OrderType.Follow))
- {
- ControlTarget = aggressor;
- ControlOrder = OrderType.Attack;
- }
- }
- public virtual void AddCustomContextEntries(Mobile from, List<ContextMenuEntry> list)
- {
- }
- public override void GetContextMenuEntries(Mobile from, List<ContextMenuEntry> list)
- {
- base.GetContextMenuEntries(from, list);
- if (m_AI != null && Commandable)
- m_AI.GetContextMenuEntries(from, list);
- if (m_bTamable && !m_bControled && from.Alive)
- list.Add(new TameEntry(from, this));
- AddCustomContextEntries(from, list);
- if (CanTeach && from.Alive)
- {
- Skills ourSkills = this.Skills;
- Skills theirSkills = from.Skills;
- for (int i = 0; i < ourSkills.Length && i < theirSkills.Length; ++i)
- {
- Skill skill = ourSkills[i];
- Skill theirSkill = theirSkills[i];
- if (skill != null && theirSkill != null && skill.Base >= 60.0 && CheckTeach(skill.SkillName, from))
- {
- double toTeach = skill.Base / 3.0;
- if (toTeach > 42.0)
- toTeach = 42.0;
- list.Add(new TeachEntry((SkillName)i, this, from, (toTeach > theirSkill.Base)));
- }
- }
- }
- }
- /// <summary>
- /// Ensures that a template is assigned for the creature
- /// </summary>
- public void EnsureTemplateAssigned()
- {
- if (!m_IsSystemInitialized)
- {
- m_IsSystemInitialized = true;
- ManagerConfig.InitializeCreature(this);
- }
- }
- public override bool HandlesOnSpeech(Mobile from)
- {
- InhumanSpeech speechType = this.SpeechType;
- if (speechType != null && (speechType.Flags & IHSFlags.OnSpeech) != 0 && from.InRange(this, 3))
- return true;
- return (m_AI != null && m_AI.HandlesOnSpeech(from) && from.InRange(this, m_iRangePerception));
- }
- public override void OnSpeech(SpeechEventArgs e)
- {
- InhumanSpeech speechType = this.SpeechType;
- if (speechType != null && speechType.OnSpeech(this, e.Mobile, e.Speech))
- e.Handled = true;
- else if (!e.Handled && m_AI != null && e.Mobile.InRange(this, m_iRangePerception))
- m_AI.OnSpeech(e);
- }
- public override bool IsHarmfulCriminal(Mobile target)
- {
- if ((Controled && target == m_ControlMaster) || (Summoned && target == m_SummonMaster))
- return false;
- if (target is BaseCreature && ((BaseCreature)target).InitialInnocent)
- return false;
- if (target is PlayerMobile && ((PlayerMobile)target).PermaFlags.Count > 0)
- return false;
- return base.IsHarmfulCriminal(target);
- }
- public override void CriminalAction(bool message)
- {
- base.CriminalAction(message);
- if ((Controled || Summoned))
- {
- if (m_ControlMaster != null && m_ControlMaster.Player)
- m_ControlMaster.CriminalAction(false);
- else if (m_SummonMaster != null && m_SummonMaster.Player)
- m_SummonMaster.CriminalAction(false);
- }
- }
- public override void DoHarmful(Mobile target, bool indirect)
- {
- base.DoHarmful(target, indirect);
- if (target == this || target == m_ControlMaster || target == m_SummonMaster || (!Controled && !Summoned))
- return;
- ArrayList list = this.Aggressors;
- for (int i = 0; i < list.Count; ++i)
- {
- AggressorInfo ai = (AggressorInfo)list[i];
- if (ai.Attacker == target)
- return;
- }
- list = this.Aggressed;
- for (int i = 0; i < list.Count; ++i)
- {
- AggressorInfo ai = (AggressorInfo)list[i];
- if (ai.Defender == target)
- {
- if (m_ControlMaster != null && m_ControlMaster.Player && m_ControlMaster.CanBeHarmful(target, false))
- m_ControlMaster.DoHarmful(target, true);
- else if (m_SummonMaster != null && m_SummonMaster.Player && m_SummonMaster.CanBeHarmful(target, false))
- m_SummonMaster.DoHarmful(target, true);
- return;
- }
- }
- }
- private static Mobile m_NoDupeGuards;
- public void ReleaseGuardDupeLock()
- {
- m_NoDupeGuards = null;
- }
- public void ReleaseGuardLock()
- {
- EndAction(typeof(GuardedRegion));
- }
- private DateTime m_IdleReleaseTime;
- public virtual bool CheckIdle()
- {
- // Initialize on idling
- EnsureTemplateAssigned();
- if (Combatant != null)
- return false; // in combat.. not idling
- if (m_IdleReleaseTime > DateTime.MinValue)
- {
- // idling...
- if (DateTime.Now >= m_IdleReleaseTime)
- {
- m_IdleReleaseTime = DateTime.MinValue;
- return false; // idle is over
- }
- return true; // still idling
- }
- if (95 > Utility.Random(100))
- return false; // not idling, but don't want to enter idle state
- m_IdleReleaseTime = DateTime.Now + TimeSpan.FromSeconds(Utility.RandomMinMax(15, 25));
- if (Body.IsHuman)
- {
- switch (Utility.Random(2))
- {
- case 0: Animate(5, 5, 1, true, true, 1); break;
- case 1: Animate(6, 5, 1, true, false, 1); break;
- }
- }
- else if (Body.IsAnimal)
- {
- switch (Utility.Random(3))
- {
- case 0: Animate(3, 3, 1, true, false, 1); break;
- case 1: Animate(9, 5, 1, true, false, 1); break;
- case 2: Animate(10, 5, 1, true, false, 1); break;
- }
- }
- else if (Body.IsMonster)
- {
- switch (Utility.Random(2))
- {
- case 0: Animate(17, 5, 1, true, false, 1); break;
- case 1: Animate(18, 5, 1, true, false, 1); break;
- }
- }
- PlaySound(GetIdleSound());
- return true; // entered idle state
- }
- public override void OnMovement(Mobile m, Point3D oldLocation)
- {
- base.OnMovement(m, oldLocation);
- // Initialize on movement
- EnsureTemplateAssigned();
- if (m is RacePlayerMobile && m_SayingsEnabled && DateTime.Now >= m_NextSaying && !m.Hidden) // check if its time to talk
- {
- var rpm = m as RacePlayerMobile;
- if (rpm.AccessLevel == AccessLevel.Player && InRange(m, 2) && !InRange(oldLocation, 2) && InLOS(m)) // check if player in range.
- {
- m_NextSaying = DateTime.Now + m_SayingsDelay; // set next talk time
- if (Utility.Random(3) > 0)
- {
- switch (Utility.Random(5)) // 5 speech options
- {
- case 0: Say(m_Saying1); break;
- case 1: Say(m_Saying2); break;
- case 2: Say(m_Saying3); break;
- case 3: Say(m_Saying4); break;
- case 4: Say(m_Saying5); break;
- };
- }
- }
- }
- if (ReaquireOnMovement)
- ForceReaquire();
- InhumanSpeech speechType = this.SpeechType;
- if (speechType != null)
- speechType.OnMovement(this, m, oldLocation);
- /* Begin notice sound */
- if (m.Player && m_FightMode != FightMode.Agressor && m_FightMode != FightMode.None && Combatant == null && !Controled && !Summoned)
- {
- // If this creature defends itself but doesn't actively attack (animal) or
- // doesn't fight at all (vendor) then no notice sounds are played..
- // So, players are only notified of agressive monsters
- // Monsters that are currently fighting are ignored
- // Controled or summoned creatures are ignored
- if (InRange(m.Location, 18) && !InRange(oldLocation, 18))
- {
- if (Body.IsMonster)
- Animate(11, 5, 1, true, false, 1);
- PlaySound(GetAngerSound());
- }
- }
- /* End notice sound */
- if (m_NoDupeGuards == m)
- return;
- if (!Body.IsHuman || Kills >= 5 || AlwaysMurderer || AlwaysAttackable || m.Kills < 5 || !m.InRange(Location, 12) || !m.Alive)
- return;
- Region reg = this.Region;
- if (reg is GuardedRegion)
- {
- GuardedRegion guardedRegion = (GuardedRegion)reg;
- if (!guardedRegion.IsDisabled() && guardedRegion.IsGuardCandidate(m) && BeginAction(typeof(GuardedRegion)))
- {
- Say(1013037 + Utility.Random(16));
- guardedRegion.CallGuards(this.Location);
- Timer.DelayCall(TimeSpan.FromSeconds(5.0), new TimerCallback(ReleaseGuardLock));
- m_NoDupeGuards = m;
- Timer.DelayCall(TimeSpan.Zero, new TimerCallback(ReleaseGuardDupeLock));
- }
- }
- }
- public void AddSpellAttack(Type type)
- {
- m_arSpellAttack.Add(type);
- }
- public void AddSpellDefense(Type type)
- {
- m_arSpellDefense.Add(type);
- }
- public Spell GetAttackSpellRandom()
- {
- if (m_arSpellAttack.Count > 0)
- {
- Type type = (Type)m_arSpellAttack[Utility.Random(m_arSpellAttack.Count)];
- object[] args = { this, null };
- return Activator.CreateInstance(type, args) as Spell;
- }
- else
- {
- return null;
- }
- }
- public Spell GetDefenseSpellRandom()
- {
- if (m_arSpellDefense.Count > 0)
- {
- Type type = (Type)m_arSpellDefense[Utility.Random(m_arSpellDefense.Count)];
- object[] args = { this, null };
- return Activator.CreateInstance(type, args) as Spell;
- }
- else
- {
- return null;
- }
- }
- public Spell GetSpellSpecific(Type type)
- {
- int i;
- for (i = 0; i < m_arSpellAttack.Count; i++)
- {
- if (m_arSpellAttack[i] == type)
- {
- object[] args = { this, null };
- return Activator.CreateInstance(type, args) as Spell;
- }
- }
- for (i = 0; i < m_arSpellDefense.Count; i++)
- {
- if (m_arSpellDefense[i] == type)
- {
- object[] args = { this, null };
- return Activator.CreateInstance(type, args) as Spell;
- }
- }
- return null;
- }
- public void SetDamage(int val)
- {
- m_DamageMin = val;
- m_DamageMax = val;
- }
- public void SetDamage(int min, int max)
- {
- m_DamageMin = min;
- m_DamageMax = max;
- }
- public void SetHits(int val)
- {
- if (val < 1000 && !Core.AOS)
- val = (val * 100) / 60;
- m_HitsMax = val;
- Hits = HitsMax;
- }
- public void SetHits(int min, int max)
- {
- if (min < 1000 && !Core.AOS)
- {
- min = (min * 100) / 60;
- max = (max * 100) / 60;
- }
- m_HitsMax = Utility.RandomMinMax(min, max);
- Hits = HitsMax;
- }
- public void SetStam(int val)
- {
- m_StamMax = val;
- Stam = StamMax;
- }
- public void SetStam(int min, int max)
- {
- m_StamMax = Utility.RandomMinMax(min, max);
- Stam = StamMax;
- }
- public void SetMana(int val)
- {
- m_ManaMax = val;
- Mana = ManaMax;
- }
- public void SetMana(int min, int max)
- {
- m_ManaMax = Utility.RandomMinMax(min, max);
- Mana = ManaMax;
- }
- public void SetStr(int val)
- {
- RawStr = val;
- Hits = HitsMax;
- }
- public void SetStr(int min, int max)
- {
- RawStr = Utility.RandomMinMax(min, max);
- Hits = HitsMax;
- }
- public void SetDex(int val)
- {
- RawDex = val;
- Stam = StamMax;
- }
- public void SetDex(int min, int max)
- {
- RawDex = Utility.RandomMinMax(min, max);
- Stam = StamMax;
- }
- public void SetInt(int val)
- {
- RawInt = val;
- Mana = ManaMax;
- }
- public void SetInt(int min, int max)
- {
- RawInt = Utility.RandomMinMax(min, max);
- Mana = ManaMax;
- }
- public void SetDamageType(ResistanceType type, int min, int max)
- {
- SetDamageType(type, Utility.RandomMinMax(min, max));
- }
- public void SetDamageType(ResistanceType type, int val)
- {
- switch (type)
- {
- case ResistanceType.Physical: m_PhysicalDamage = val; break;
- case ResistanceType.Fire: m_FireDamage = val; break;
- case ResistanceType.Cold: m_ColdDamage = val; break;
- case ResistanceType.Poison: m_PoisonDamage = val; break;
- case ResistanceType.Energy: m_EnergyDamage = val; break;
- }
- }
- public void SetResistance(ResistanceType type, int min, int max)
- {
- SetResistance(type, Utility.RandomMinMax(min, max));
- }
- public void SetResistance(ResistanceType type, int val)
- {
- switch (type)
- {
- case ResistanceType.Physical: m_PhysicalResistance = val; break;
- case ResistanceType.Fire: m_FireResistance = val; break;
- case ResistanceType.Cold: m_ColdResistance = val; break;
- case ResistanceType.Poison: m_PoisonResistance = val; break;
- case ResistanceType.Energy: m_EnergyResistance = val; break;
- }
- UpdateResistances();
- }
- public void SetSkill(SkillName name, double val)
- {
- Skills[name].BaseFixedPoint = (int)(val * 10);
- }
- public void SetSkill(SkillName name, double min, double max)
- {
- int minFixed = (int)(min * 10);
- int maxFixed = (int)(max * 10);
- Skills[name].BaseFixedPoint = Utility.RandomMinMax(minFixed, maxFixed);
- }
- public void SetFameLevel(int level)
- {
- switch (level)
- {
- case 1: Fame = Utility.RandomMinMax(0, 1249); break;
- case 2: Fame = Utility.RandomMinMax(1250, 2499); break;
- case 3: Fame = Utility.RandomMinMax(2500, 4999); break;
- case 4: Fame = Utility.RandomMinMax(5000, 9999); break;
- case 5: Fame = Utility.RandomMinMax(10000, 10000); break;
- }
- }
- public void SetKarmaLevel(int level)
- {
- switch (level)
- {
- case 0: Karma = -Utility.RandomMinMax(0, 624); break;
- case 1: Karma = -Utility.RandomMinMax(625, 1249); break;
- case 2: Karma = -Utility.RandomMinMax(1250, 2499); break;
- case 3: Karma = -Utility.RandomMinMax(2500, 4999); break;
- case 4: Karma = -Utility.RandomMinMax(5000, 9999); break;
- case 5: Karma = -Utility.RandomMinMax(10000, 10000); break;
- }
- }
- public static void Cap(ref int val, int min, int max)
- {
- if (val < min)
- val = min;
- else if (val > max)
- val = max;
- }
- public void PackPotion()
- {
- PackMagicJewel();
- PackItem(Loot.RandomPotion());
- }
- public void PackScroll(int minCircle, int maxCircle)
- {
- PackScroll(Utility.RandomMinMax(minCircle, maxCircle));
- }
- public void PackScroll(int circle)
- {
- PackMagicJewel();
- int min = (circle - 1) * 8;
- PackItem(Loot.RandomScroll());
- }
- public void PackMagicItems(int minLevel, int maxLevel)
- {
- PackMagicItems(minLevel, maxLevel, 0.30, 0.15);
- }
- public void PackMagicItems(int minLevel, int maxLevel, double armorChance, double weaponChance)
- {
- if (!PackArmor(minLevel, maxLevel, armorChance))
- PackWeapon(minLevel, maxLevel, weaponChance);
- }
- protected bool m_Spawning;
- protected int m_KillersLuck;
- public void GenerateLoot(bool spawning)
- {
- m_Spawning = spawning;
- if (!spawning)
- m_KillersLuck = 0;
- GenerateLoot();
- var type = CreatureType.FindType(this);
- if (!spawning && type != null)
- {
- Container backpack = Backpack;
- if (backpack == null)
- {
- backpack = new Backpack();
- backpack.Movable = false;
- AddItem(backpack);
- }
- type.Loot.Generate(this, backpack, LootLevel);
- }
- m_Spawning = false;
- m_KillersLuck = 0;
- }
- public virtual void GenerateLoot()
- {
- }
- public bool PackArmor(int minLevel, int maxLevel)
- {
- return PackArmor(minLevel, maxLevel, 1.0);
- }
- public bool PackArmor(int minLevel, int maxLevel, double chance)
- {
- if (chance <= Utility.RandomDouble())
- return false;
- Cap(ref minLevel, 0, 5);
- Cap(ref maxLevel, 0, 5);
- if (Core.AOS)
- {
- Item item = Loot.RandomArmorOrShieldOrJewelry();
- if (item == null)
- return false;
- int attributeCount, min, max;
- GetRandomAOSStats(minLevel, maxLevel, out attributeCount, out min, out max);
- if (item is BaseArmor)
- BaseRunicTool.ApplyAttributesTo((BaseArmor)item, attributeCount, min, max);
- else if (item is BaseJewel)
- BaseRunicTool.ApplyAttributesTo((BaseJewel)item, attributeCount, min, max);
- PackItem(item);
- }
- else
- {
- BaseArmor armor = Loot.RandomArmorOrShield();
- if (armor == null)
- return false;
- armor.ProtectionLevel = (ArmorProtectionLevel)RandomMinMaxScaled(minLevel, maxLevel);
- armor.Durability = (ArmorDurabilityLevel)RandomMinMaxScaled(minLevel, maxLevel);
- PackItem(armor);
- }
- return true;
- }
- public static void GetRandomAOSStats(int minLevel, int maxLevel, out int attributeCount, out int min, out int max)
- {
- int v = RandomMinMaxScaled(minLevel, maxLevel);
- if (v >= 5)
- {
- attributeCount = Utility.RandomMinMax(2, 6);
- min = 20; max = 70;
- }
- else if (v == 4)
- {
- attributeCount = Utility.RandomMinMax(2, 4);
- min = 20; max = 50;
- }
- else if (v == 3)
- {
- attributeCount = Utility.RandomMinMax(2, 3);
- min = 20; max = 40;
- }
- else if (v == 2)
- {
- attributeCount = Utility.RandomMinMax(1, 2);
- min = 10; max = 30;
- }
- else
- {
- attributeCount = 1;
- min = 10; max = 20;
- }
- }
- public static int RandomMinMaxScaled(int min, int max)
- {
- if (min == max)
- return min;
- if (min > max)
- {
- int hold = min;
- min = max;
- max = hold;
- }
- /* Example:
- * min: 1
- * max: 5
- * count: 5
- *
- * total = (5*5) + (4*4) + (3*3) + (2*2) + (1*1) = 25 + 16 + 9 + 4 + 1 = 55
- *
- * chance for min+0 : 25/55 : 45.45%
- * chance for min+1 : 16/55 : 29.09%
- * chance for min+2 : 9/55 : 16.36%
- * chance for min+3 : 4/55 : 7.27%
- * chance for min+4 : 1/55 : 1.81%
- */
- int count = max - min + 1;
- int total = 0, toAdd = count;
- for (int i = 0; i < count; ++i, --toAdd)
- total += toAdd * toAdd;
- int rand = Utility.Random(total);
- toAdd = count;
- int val = min;
- for (int i = 0; i < count; ++i, --toAdd, ++val)
- {
- rand -= toAdd * toAdd;
- if (rand < 0)
- break;
- }
- return val;
- }
- public bool PackSlayer()
- {
- return PackSlayer(0.05);
- }
- public bool PackSlayer(double chance)
- {
- if (chance <= Utility.RandomDouble())
- return false;
- if (Utility.RandomBool())
- {
- BaseInstrument instrument = Loot.RandomInstrument();
- if (instrument != null)
- {
- instrument.Slayer = SlayerGroup.GetLootSlayerType(GetType());
- PackItem(instrument);
- }
- }
- return true;
- }
- public bool PackWeapon(int minLevel, int maxLevel)
- {
- return PackWeapon(minLevel, maxLevel, 1.0);
- }
- public bool PackWeapon(int minLevel, int maxLevel, double chance)
- {
- if (chance <= Utility.RandomDouble())
- return false;
- Cap(ref minLevel, 0, 5);
- Cap(ref maxLevel, 0, 5);
- Item item = Loot.RandomWeaponOrJewelry();
- if (item == null)
- return false;
- int attributeCount, min, max;
- GetRandomAOSStats(minLevel, maxLevel, out attributeCount, out min, out max);
- if (item is BaseWeapon)
- BaseRunicTool.ApplyAttributesTo((BaseWeapon)item, attributeCount, min, max);
- else if (item is BaseJewel)
- BaseRunicTool.ApplyAttributesTo((BaseJewel)item, attributeCount, min, max);
- PackItem(item);
- return true;
- }
- public void PackGold(int amount)
- {
- PackMagicJewel();
- //if ( amount > 0 )
- // PackItem( new Gold( amount ) );
- return;
- }
- public void PackGold(int min, int max)
- {
- PackMagicJewel();
- //PackGold( Utility.RandomMinMax( min, max ) );
- return;
- }
- public void PackStatue(int min, int max)
- {
- PackStatue(Utility.RandomMinMax(min, max));
- }
- public void PackStatue(int amount)
- {
- for (int i = 0; i < amount; ++i)
- PackStatue();
- }
- public void PackStatue()
- {
- PackItem(Loot.RandomStatue());
- }
- public void PackGem()
- {
- PackGem(1);
- PackMagicJewel();
- }
- public void PackLesserDaemonBone()
- {
- if (Utility.Random(0, 100) <= 15)
- {
- PackItem(new DaemonBone(Utility.Random(1, 5)));
- }
- }
- public void PackDaemonBone()
- {
- if (Utility.Random(0, 100) <= 25)
- {
- PackItem(new DaemonBone(Utility.Random(1, 10)));
- }
- }
- public void PackMagicJewel()
- {
- if (Utility.Random(0, 1000) <= 10)
- {
- PackItem(new MagicJewel());
- }
- }
- public void PackGem(int min, int max)
- {
- PackGem(Utility.RandomMinMax(min, max));
- }
- public void PackGem(int amount)
- {
- if (amount <= 0)
- return;
- Item gem = Loot.RandomGem();
- gem.Amount = amount;
- PackItem(gem);
- }
- public void PackItem(Item item)
- {
- if (Summoned || item == null)
- {
- if (item != null)
- item.Delete();
- return;
- }
- Container pack = Backpack;
- if (pack == null)
- {
- pack = new Backpack();
- pack.Movable = false;
- AddItem(pack);
- }
- if (!item.Stackable || !pack.TryDropItem(this, item, false)) // try stack
- pack.DropItem(item); // failed, drop it anyway
- }
- public override void OnDoubleClick(Mobile from)
- {
- if (from.AccessLevel >= AccessLevel.GameMaster && !Body.IsHuman)
- {
- Container pack = this.Backpack;
- if (pack != null)
- pack.DisplayTo(from);
- }
- base.OnDoubleClick(from);
- }
- #region Disable Local Names
- public sealed override void OnAosSingleClick(Mobile from)
- {
- if (!m_ShowNameTag || this is BaseGuildMobile)
- return;
- if (from is RacePlayerMobile)
- {
- var rpm = (RacePlayerMobile)from;
- if (this is BaseVendor)
- {
- if (!rpm.GuildInfo.IsYoung)
- return;
- }
- else
- {
- if (!rpm.GuildInfo.ShowMonsters)
- return;
- }
- }
- ObjectPropertyList opl = this.PropertyList;
- if (opl.Header > 0)
- {
- int hue;
- string name = Name;
- if (this.NameHue != -1)
- hue = this.NameHue;
- else if (this.AccessLevel > AccessLevel.Player)
- hue = 11;
- else
- hue = Notoriety.GetHue(Notoriety.Compute(from, this));
- if (from is RacePlayerMobile)
- {
- RacePlayerMobile rpm = (RacePlayerMobile)from;
- if (rpm.Capacities[CapacityName.Lore].Value < Erudition)
- name = "Cr�ature";
- }
- from.Send(new MessageLocalized(this.Serial, Body, MessageType.Label, hue, 3, opl.Header, name, opl.HeaderArgs));
- }
- //SendPropertiesTo(from);
- }
- public sealed override void OnSingleClick(Mobile from)
- {
- if (!m_ShowNameTag || this is BaseGuildMobile)
- return;
- if (from is RacePlayerMobile)
- {
- var rpm = (RacePlayerMobile)from;
- if (this is BaseVendor)
- {
- if (!rpm.GuildInfo.IsYoung)
- return;
- }
- else
- {
- if (!rpm.GuildInfo.ShowMonsters)
- return;
- }
- }
- if (Controled && Commandable)
- {
- int number;
- if (Summoned)
- number = 1049646; // (summoned)
- else if (IsBonded)
- number = 1049608; // (bonded)
- else
- number = 502006; // (tame)
- PrivateOverheadMessage(MessageType.Regular, 0x3B2, number, from.NetState);
- }
- if (this.Deleted)
- return;
- else if (AccessLevel == AccessLevel.Player && DisableHiddenSelfClick && Hidden && from == this)
- return;
- int hue;
- if (this.NameHue != -1)
- hue = this.NameHue;
- else if (AccessLevel > AccessLevel.Player)
- hue = 11;
- else
- hue = Notoriety.GetHue(Notoriety.Compute(from, this));
- string name = Name;
- if (name == null)
- name = String.Empty;
- string prefix = "";
- if (ShowFameTitle && (this.Player || this.Body.IsHuman) && this.Fame >= 10000)
- prefix = (this.Female ? "Lady" : "Lord");
- string suffix = "";
- if (ClickTitle && Title != null && Title.Length > 0)
- suffix = Title;
- //suffix = ApplyNameSuffix(suffix);
- string val;
- if (prefix.Length > 0 && suffix.Length > 0)
- val = String.Concat(prefix, " ", name, " ", suffix);
- else if (prefix.Length > 0)
- val = String.Concat(prefix, " ", name);
- else if (suffix.Length > 0)
- val = String.Concat(name, " ", suffix);
- else
- val = name;
- if (from.NetState.Mobile is RacePlayerMobile)
- {
- RacePlayerMobile rpm = (RacePlayerMobile)(from.NetState.Mobile);
- if (rpm.Capacities[CapacityName.Lore].Value < Erudition)
- val = "Cr�ature";
- }
- PrivateOverheadMessage(MessageType.Label, hue, true, val, from.NetState);
- //base.OnSingleClick( from );
- //SendPropertiesTo(from);
- }
- #endregion
- public virtual int TreasureMapLevel { get { return 0; } }
- public override bool OnBeforeDeath()
- {
- int treasureLevel = TreasureMapLevel;
- if (!Summoned && !NoKillAwards && !IsBonded && treasureLevel > 0 && (Map == Map.Felucca || Map == Map.Trammel) && TreasureMap.LootChance >= Utility.RandomDouble())
- PackItem(new TreasureMap(treasureLevel, Map));
- if (!Summoned && !NoKillAwards && !m_HasGeneratedLoot)
- {
- m_HasGeneratedLoot = true;
- GenerateLoot(false);
- }
- if (IsAnimatedDead)
- Effects.SendLocationEffect(Location, Map, 0x3728, 13, 1, 0x461, 4);
- InhumanSpeech speechType = this.SpeechType;
- if (speechType != null)
- speechType.OnDeath(this);
- return base.OnBeforeDeath();
- }
- private bool m_NoKillAwards;
- public bool NoKillAwards
- {
- get { return m_NoKillAwards; }
- set { m_NoKillAwards = value; }
- }
- public int ComputeBonusDamage(ArrayList list, Mobile m)
- {
- int bonus = 0;
- for (int i = list.Count - 1; i >= 0; --i)
- {
- DamageEntry de = (DamageEntry)list[i];
- if (de.Damager == m || !(de.Damager is BaseCreature))
- continue;
- BaseCreature bc = (BaseCreature)de.Damager;
- Mobile master = null;
- if (bc.Controled && bc.ControlMaster != null)
- master = bc.ControlMaster;
- else if (bc.Summoned && bc.SummonMaster != null)
- master = bc.SummonMaster;
- if (master == m)
- bonus += de.DamageGiven;
- }
- return bonus;
- }
- private class FKEntry
- {
- public Mobile m_Mobile;
- public int m_Damage;
- public FKEntry(Mobile m, int damage)
- {
- m_Mobile = m;
- m_Damage = damage;
- }
- }
- public static ArrayList GetLootingRights(ArrayList damageEntries)
- {
- ArrayList rights = new ArrayList();
- for (int i = damageEntries.Count - 1; i >= 0; --i)
- {
- if (i >= damageEntries.Count)
- continue;
- DamageEntry de = (DamageEntry)damageEntries[i];
- if (de.HasExpired)
- {
- damageEntries.RemoveAt(i);
- continue;
- }
- int damage = de.DamageGiven;
- ArrayList respList = de.Responsible;
- if (respList != null)
- {
- for (int j = 0; j < respList.Count; ++j)
- {
- DamageEntry subEntry = (DamageEntry)respList[j];
- Mobile master = subEntry.Damager;
- if (master == null || master.Deleted || !master.Player)
- continue;
- bool needNewSubEntry = true;
- for (int k = 0; needNewSubEntry && k < rights.Count; ++k)
- {
- DamageStore ds = (DamageStore)rights[k];
- if (ds.m_Mobile == master)
- {
- ds.m_Damage += subEntry.DamageGiven;
- needNewSubEntry = false;
- }
- }
- if (needNewSubEntry)
- rights.Add(new DamageStore(master, subEntry.DamageGiven));
- damage -= subEntry.DamageGiven;
- }
- }
- Mobile m = de.Damager;
- if (m is BaseCreature)
- {
- BaseCreature bc = (BaseCreature)m;
- if (bc.Controled && bc.ControlMaster != null)
- m = bc.ControlMaster;
- else if (bc.Summoned && bc.SummonMaster != null)
- m = bc.SummonMaster;
- }
- if (m == null || m.Deleted || !m.Player)
- continue;
- if (damage <= 0)
- continue;
- bool needNewEntry = true;
- for (int j = 0; needNewEntry && j < rights.Count; ++j)
- {
- DamageStore ds = (DamageStore)rights[j];
- if (ds.m_Mobile == m)
- {
- ds.m_Damage += damage;
- needNewEntry = false;
- }
- }
- if (needNewEntry)
- rights.Add(new DamageStore(m, damage));
- }
- if (rights.Count > 0)
- {
- if (rights.Count > 1)
- rights.Sort();
- int topDamage = ((DamageStore)rights[0]).m_Damage;
- int minDamage = (topDamage * 70) / 100;
- for (int i = 0; i < rights.Count; ++i)
- {
- DamageStore ds = (DamageStore)rights[i];
- ds.m_HasRight = (ds.m_Damage >= minDamage);
- }
- }
- return rights;
- }
- public override void OnDeath(Container c)
- {
- if (IsBonded)
- {
- int sound = this.GetDeathSound();
- if (sound >= 0)
- Effects.PlaySound(this, this.Map, sound);
- Warmode = false;
- Poison = null;
- Combatant = null;
- Hits = 0;
- Stam = 0;
- Mana = 0;
- IsDeadPet = true;
- ControlTarget = ControlMaster;
- ControlOrder = OrderType.Follow;
- ProcessDeltaQueue();
- SendIncomingPacket();
- SendIncomingPacket();
- ArrayList aggressors = this.Aggressors;
- for (int i = 0; i < aggressors.Count; ++i)
- {
- AggressorInfo info = (AggressorInfo)aggressors[i];
- if (info.Attacker.Combatant == this)
- info.Attacker.Combatant = null;
- }
- ArrayList aggressed = this.Aggressed;
- for (int i = 0; i < aggressed.Count; ++i)
- {
- AggressorInfo info = (AggressorInfo)aggressed[i];
- if (info.Defender.Combatant == this)
- info.Defender.Combatant = null;
- }
- Mobile owner = this.ControlMaster;
- if (owner == null || owner.Deleted || owner.Map != this.Map || !owner.InRange(this, 12) || !this.CanSee(owner) || !this.InLOS(owner))
- {
- if (this.OwnerAbandonTime == DateTime.MinValue)
- this.OwnerAbandonTime = DateTime.Now;
- }
- else
- {
- this.OwnerAbandonTime = DateTime.MinValue;
- }
- }
- else
- {
- if (!Summoned && !m_NoKillAwards)
- {
- int totalFame = Fame / 100;
- int totalKarma = -Karma / 100;
- ArrayList list = GetLootingRights(this.DamageEntries);
- bool givenQuestKill = false;
- for (int i = 0; i < list.Count; ++i)
- {
- DamageStore ds = (DamageStore)list[i];
- if (!ds.m_HasRight)
- continue;
- Titles.AwardFame(ds.m_Mobile, totalFame, true);
- Titles.AwardKarma(ds.m_Mobile, totalKarma, true);
- // ----------------------------------------------------------------------------
- /*
- if (ds.m_Mobile is RacePlayerMobile && m_CurrentAI != AIType.AI_Animal)
- {
- RacePlayerMobile player = (RacePlayerMobile)ds.m_Mobile;
- var Evo = player.EvolutionInfo;
- int PreviousLevel = Evo.Level;
-
- if (PreviousLevel < 25 && Utility.RandomMinMax(0,99) < 1)
- {
- Evo.Experience += 1;
- player.SendMessage("Vous vous sentez plus exp�riment� apr�s ce combat.");
-
- if (PreviousLevel < Evo.Level)
- {
- player.SendMessage("F�licitations! Vous avez atteint le niveau " + Evo.Level);
- player.SkillsCap += 1400;
- }
- }
- }
- */
- // ----------------------------------------------------------------------------
- if (givenQuestKill)
- continue;
- }
- }
- base.OnDeath(c);
- if (DeleteCorpseOnDeath)
- c.Delete();
- }
- }
- /* To save on cpu usage, RunUO creatures only reaquire creatures under the following circumstances:
- * - 10 seconds have elapsed since the last time it tried
- * - The creature was attacked
- * - Some creatures, like dragons, will reaquire when they see someone move
- *
- * This functionality appears to be implemented on OSI as well
- */
- private DateTime m_NextReaquireTime;
- public DateTime NextReaquireTime { get { return m_NextReaquireTime; } set { m_NextReaquireTime = value; } }
- public virtual TimeSpan ReaquireDelay { get { return TimeSpan.FromSeconds(10.0); } }
- public virtual bool ReaquireOnMovement { get { return false; } }
- public void ForceReaquire()
- {
- m_NextReaquireTime = DateTime.MinValue;
- }
- public override void OnDelete()
- {
- SetControlMaster(null);
- SummonMaster = null;
- base.OnDelete();
- }
- public override bool CanBeHarmful(Mobile target, bool message, bool ignoreOurBlessedness)
- {
- 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);
- }
- public override bool CanBeRenamedBy(Mobile from)
- {
- bool ret = base.CanBeRenamedBy(from);
- if (Controled && from == ControlMaster)
- ret = true;
- return ret;
- }
- public bool SetControlMaster(Mobile m)
- {
- if (m == null)
- {
- ControlMaster = null;
- Controled = false;
- ControlTarget = null;
- ControlOrder = OrderType.None;
- Guild = null;
- Delta(MobileDelta.Noto);
- }
- else
- {
- if (m.Followers + ControlSlots > m.FollowersMax)
- {
- m.SendLocalizedMessage(1049607); // You have too many followers to control that creature.
- return false;
- }
- CurrentWayPoint = null;//so tamed animals don't try to go back
- ControlMaster = m;
- Controled = true;
- ControlTarget = null;
- ControlOrder = OrderType.Come;
- Guild = null;
- Delta(MobileDelta.Noto);
- }
- return true;
- }
- private static bool m_Summoning;
- public static bool Summoning
- {
- get { return m_Summoning; }
- set { m_Summoning = value; }
- }
- public static bool Summon(BaseCreature creature, Mobile caster, Point3D p, int sound, TimeSpan duration)
- {
- return Summon(creature, true, caster, p, sound, duration);
- }
- public static bool Summon(BaseCreature creature, bool controled, Mobile caster, Point3D p, int sound, TimeSpan duration)
- {
- if (caster.Followers + creature.ControlSlots > caster.FollowersMax)
- {
- caster.SendLocalizedMessage(1049645); // You have too many followers to summon that creature.
- creature.Delete();
- return false;
- }
- creature.EnsureTemplateAssigned();
- m_Summoning = true;
- if (controled)
- creature.SetControlMaster(caster);
- creature.RangeHome = 10;
- creature.Summoned = true;
- creature.SummonMaster = caster;
- Container pack = creature.Backpack;
- if (pack != null)
- {
- for (int i = pack.Items.Count - 1; i >= 0; --i)
- {
- if (i >= pack.Items.Count)
- continue;
- ((Item)pack.Items[i]).Delete();
- }
- }
- new UnsummonTimer(caster, creature, duration).Start();
- creature.m_SummonEnd = DateTime.Now + duration;
- creature.MoveToWorld(p, caster.Map);
- Effects.PlaySound(p, creature.Map, sound);
- m_Summoning = false;
- return true;
- }
- private static bool EnableRummaging = true;
- private const double ChanceToRummage = 0.5; // 50%
- private const double MinutesToNextRummageMin = 1.0;
- private const double MinutesToNextRummageMax = 4.0;
- private const double MinutesToNextChanceMin = 0.25;
- private const double MinutesToNextChanceMax = 0.75;
- private DateTime m_NextRummageTime;
- public virtual void OnThink()
- {
- if (EnableRummaging && CanRummageCorpses && !Summoned && !Controled && DateTime.Now >= m_NextRummageTime)
- {
- double min, max;
- if (ChanceToRummage > Utility.RandomDouble() && Rummage())
- {
- min = MinutesToNextRummageMin;
- max = MinutesToNextRummageMax;
- }
- else
- {
- min = MinutesToNextChanceMin;
- max = MinutesToNextChanceMax;
- }
- double delay = min + (Utility.RandomDouble() * (max - min));
- m_NextRummageTime = DateTime.Now + TimeSpan.FromMinutes(delay);
- }
- if (HasBreath && !Summoned && DateTime.Now >= m_NextBreathTime) // tested: controled dragons do breath fire, what about summoned skeletal dragons?
- {
- Mobile target = this.Combatant;
- if (target != null && target.Alive && !target.IsDeadBondedPet && CanBeHarmful(target) && target.Map == this.Map && !IsDeadBondedPet && target.InRange(this, BreathRange) && InLOS(target) && !BardPacified)
- BreathStart(target);
- m_NextBreathTime = DateTime.Now + TimeSpan.FromSeconds(BreathMinDelay + (Utility.RandomDouble() * BreathMaxDelay));
- }
- }
- public virtual bool Rummage()
- {
- Corpse toRummage = null;
- foreach (Item item in this.GetItemsInRange(2))
- {
- if (item is Corpse && item.Items.Count > 0)
- {
- toRummage = (Corpse)item;
- break;
- }
- }
- if (toRummage == null)
- return false;
- Container pack = this.Backpack;
- if (pack == null)
- return false;
- var items = toRummage.Items;
- bool rejected;
- LRReason reason;
- for (int i = 0; i < items.Count; ++i)
- {
- Item item = (Item)items[Utility.Random(items.Count)];
- Lift(item, item.Amount, out rejected, out reason);
- if (!rejected && Drop(this, new Point3D(-1, -1, 0)))
- {
- // *rummages through a corpse and takes an item*
- PublicOverheadMessage(MessageType.Emote, 0x3B2, 1008086);
- return true;
- }
- }
- return false;
- }
- public void Pacify(Mobile master, DateTime endtime)
- {
- BardPacified = true;
- BardEndTime = endtime;
- }
- public override Mobile GetDamageMaster(Mobile damagee)
- {
- if (m_bBardProvoked && damagee == m_bBardTarget)
- return m_bBardMaster;
- return base.GetDamageMaster(damagee);
- }
- public void Provoke(Mobile master, Mobile target, bool bSuccess)
- {
- BardProvoked = true;
- this.PublicOverheadMessage(MessageType.Emote, EmoteHue, false, "*looks furious*");
- if (bSuccess)
- {
- PlaySound(GetIdleSound());
- BardMaster = master;
- BardTarget = target;
- Combatant = target;
- BardEndTime = DateTime.Now + TimeSpan.FromSeconds(30.0);
- if (target is BaseCreature)
- {
- BaseCreature t = (BaseCreature)target;
- t.BardProvoked = true;
- t.BardMaster = master;
- t.BardTarget = this;
- t.Combatant = this;
- t.BardEndTime = DateTime.Now + TimeSpan.FromSeconds(30.0);
- }
- }
- else
- {
- PlaySound(GetAngerSound());
- BardMaster = master;
- BardTarget = target;
- }
- }
- public bool FindMyName(string str, bool bWithAll)
- {
- int i, j;
- string name = this.Name;
- if (name == null || str.Length < name.Length)
- return false;
- string[] wordsString = str.Split(' ');
- string[] wordsName = name.Split(' ');
- for (j = 0; j < wordsName.Length; j++)
- {
- string wordName = wordsName[j];
- bool bFound = false;
- for (i = 0; i < wordsString.Length; i++)
- {
- string word = wordsString[i];
- if (Insensitive.Equals(word, wordName))
- bFound = true;
- if (bWithAll && Insensitive.Equals(word, "all"))
- return true;
- }
- if (!bFound)
- return false;
- }
- return true;
- }
- public static void TeleportPets(Mobile master, Point3D loc, Map map)
- {
- TeleportPets(master, loc, map, false);
- }
- public static void TeleportPets(Mobile master, Point3D loc, Map map, bool onlyBonded)
- {
- ArrayList move = new ArrayList();
- foreach (Mobile m in master.GetMobilesInRange(3))
- {
- if (m is BaseCreature)
- {
- BaseCreature pet = (BaseCreature)m;
- if (pet.Controled && pet.ControlMaster == master)
- {
- if (!onlyBonded || pet.IsBonded)
- {
- if (pet.ControlOrder == OrderType.Guard || pet.ControlOrder == OrderType.Follow || pet.ControlOrder == OrderType.Come)
- move.Add(pet);
- }
- }
- }
- }
- foreach (Mobile m in move)
- m.MoveToWorld(loc, map);
- }
- public virtual void ResurrectPet()
- {
- if (!IsDeadPet)
- return;
- OnBeforeResurrect();
- Poison = null;
- Warmode = false;
- Hits = 10;
- Stam = StamMax;
- Mana = 0;
- ProcessDeltaQueue();
- IsDeadPet = false;
- Effects.SendPacket(Location, Map, new BondedStatus(0, this.Serial, 0));
- this.SendIncomingPacket();
- this.SendIncomingPacket();
- OnAfterResurrect();
- //Bonded Status only last once and has to be reaquired.
- IsBonded = false;
- BondingBegin = DateTime.MinValue;
- Mobile owner = this.ControlMaster;
- if (owner == null || owner.Deleted || owner.Map != this.Map || !owner.InRange(this, 12) || !this.CanSee(owner) || !this.InLOS(owner))
- {
- if (this.OwnerAbandonTime == DateTime.MinValue)
- this.OwnerAbandonTime = DateTime.Now;
- }
- else
- {
- this.OwnerAbandonTime = DateTime.MinValue;
- }
- }
- public override bool CanBeDamaged()
- {
- if (IsDeadPet)
- return false;
- return base.CanBeDamaged();
- }
- public virtual bool PlayerRangeSensitive { get { return true; } }
- public override void OnSectorDeactivate()
- {
- if (PlayerRangeSensitive && m_AI != null)
- m_AI.Deactivate();
- base.OnSectorDeactivate();
- }
- public override void OnSectorActivate()
- {
- if (PlayerRangeSensitive && m_AI != null)
- m_AI.Activate();
- base.OnSectorActivate();
- }
- // used for deleting creatures in houses
- private int m_RemoveStep;
- [CommandProperty(AccessLevel.GameMaster)]
- public int RemoveStep { get { return m_RemoveStep; } set { m_RemoveStep = value; } }
- }
- public class LoyaltyTimer : Timer
- {
- private static TimeSpan InternalDelay = TimeSpan.FromMinutes(5.0);
- public static void Initialize()
- {
- new LoyaltyTimer().Start();
- }
- public LoyaltyTimer()
- : base(InternalDelay, InternalDelay)
- {
- m_NextHourlyCheck = DateTime.Now + TimeSpan.FromHours(5.0);
- Priority = TimerPriority.FiveSeconds;
- }
- private DateTime m_NextHourlyCheck;
- protected override void OnTick()
- {
- bool hasHourElapsed = (DateTime.Now >= m_NextHourlyCheck);
- if (hasHourElapsed)
- m_NextHourlyCheck = DateTime.Now + TimeSpan.FromHours(5.0);
- ArrayList toRelease = new ArrayList();
- // added array for wild creatures in house regions to be removed
- ArrayList toRemove = new ArrayList();
- foreach (Mobile m in World.Mobiles.Values)
- {
- if (m is BaseMount && ((BaseMount)m).Rider != null)
- continue;
- if (m is BaseCreature)
- {
- BaseCreature c = (BaseCreature)m;
- if (c.IsDeadPet)
- {
- Mobile owner = c.ControlMaster;
- if (owner == null || owner.Deleted || owner.Map != c.Map || !owner.InRange(c, 12) || !c.CanSee(owner) || !c.InLOS(owner))
- {
- if (c.OwnerAbandonTime == DateTime.MinValue)
- c.OwnerAbandonTime = DateTime.Now;
- else if ((c.OwnerAbandonTime + c.BondingAbandonDelay) <= DateTime.Now)
- toRemove.Add(c);
- }
- else
- {
- c.OwnerAbandonTime = DateTime.MinValue;
- }
- }
- else if (c.Controled && c.Commandable && c.Loyalty > PetLoyalty.None && c.Map != Map.Internal)
- {
- Mobile owner = c.ControlMaster;
- // changed loyalty decrement
- if (hasHourElapsed)
- {
- --c.Loyalty;
- if (c.Loyalty == PetLoyalty.Confused)
- {
- c.Say(1043270, "Cr�ature"); // * ~1_NAME~ looks around desperately *
- c.PlaySound(c.GetIdleSound());
- }
- }
- c.OwnerAbandonTime = DateTime.MinValue;
- if (c.Loyalty == PetLoyalty.None)
- toRelease.Add(c);
- }
- // added lines to check if a wild creature in a house region has to be removed or not
- if (!c.Controled && c.Region is HouseRegion && c.CanBeDamaged())
- {
- c.RemoveStep++;
- if (c.RemoveStep >= 20)
- toRemove.Add(c);
- }
- else
- {
- c.RemoveStep = 0;
- }
- }
- }
- foreach (BaseCreature c in toRelease)
- {
- c.Say(1043255, "Cr�ature"); // ~1_NAME~ appears to have decided that is better off without a master!
- c.Loyalty = PetLoyalty.WonderfullyHappy;
- c.IsBonded = false;
- c.BondingBegin = DateTime.MinValue;
- c.OwnerAbandonTime = DateTime.MinValue;
- c.ControlTarget = null;
- //c.ControlOrder = OrderType.Release;
- c.AIObject.DoOrderRelease(); // this will prevent no release of creatures left alone with AI disabled (and consequent bug of Followers)
- }
- // added code to handle removing of wild creatures in house regions
- foreach (BaseCreature c in toRemove)
- {
- c.Delete();
- }
- }
- }
- }