using System; using System.Collections; using System.Collections.Generic; using Server.Misc; using Server.Items; using Server.Gumps; using Server.Multis; using Server.Engines.Help; using Server.ContextMenus; using Server.Network; using Server.Spells; using Server.Spells.Fifth; using Server.Spells.Seventh; using Server.Targeting; using Server.Regions; using Server.Accounting; using Server.Engines.Craft; using Server.Engines.PartySystem; namespace Server.Mobiles { #region Enums [Flags] public enum PlayerFlag // First 16 bits are reserved for default-distro use, start custom flags at 0x00010000 { None = 0x00000001, KarmaLocked = 0x00000002, UseOwnFilter = 0x00000004, PagingSquelched = 0x00000008, AcceptGuildInvites = 0x00000010 } public enum NpcGuild { None, AssassinsGuild, BardsGuild, MagesGuild, RangersGuild, ThievesGuild, WarriorsGuild, AlchemistsGuild, BlacksmithsGuild, CarpentryGuild, HealersGuild, LibrariansGuild, MarinersGuild, TailorsGuild, TinkersGuild } #endregion public class PlayerMobile : Mobile { private class CountAndTimeStamp { private int m_Count; private DateTime m_Stamp; public CountAndTimeStamp() { } public DateTime TimeStamp { get{ return m_Stamp; } } public int Count { get { return m_Count; } set { m_Count = value; m_Stamp = DateTime.Now; } } } private DesignContext m_DesignContext; private NpcGuild m_NpcGuild; private DateTime m_NpcGuildJoinTime; private TimeSpan m_NpcGuildGameTime; private DateTime m_Camp; private DateTime m_Bedroll; private PlayerFlag m_Flags; private int m_StepsTaken; private int m_Profession; private bool m_IsStealthing; // IsStealthing should be moved to Server.Mobiles private bool m_IgnoreMobiles; // IgnoreMobiles should be moved to Server.Mobiles /* * a value of zero means, that the mobile is not executing the spell. Otherwise, * the value should match the BaseMana required */ private DateTime m_LastOnline; private Server.Guilds.RankDefinition m_GuildRank; private int m_GuildMessageHue, m_AllianceMessageHue; private List m_AllFollowers; private List m_RecentlyReported; private int m_QuestLevel; private string m_MapMarkers; #region Getters & Setters public List RecentlyReported { get { return m_RecentlyReported; } set { m_RecentlyReported = value; } } public List AllFollowers { get { if( m_AllFollowers == null ) m_AllFollowers = new List(); return m_AllFollowers; } } public Server.Guilds.RankDefinition GuildRank { get { if( this.AccessLevel >= AccessLevel.GameMaster ) return Server.Guilds.RankDefinition.Leader; else return m_GuildRank; } set{ m_GuildRank = value; } } [CommandProperty( AccessLevel.GameMaster )] public int QuestLevel { get{ return m_QuestLevel; } set{ m_QuestLevel = value; } } [CommandProperty( AccessLevel.GameMaster )] public string MapMarkers { get{ return m_MapMarkers; } set{ m_MapMarkers = value; } } [CommandProperty( AccessLevel.GameMaster )] public int GuildMessageHue { get{ return m_GuildMessageHue; } set{ m_GuildMessageHue = value; } } [CommandProperty( AccessLevel.GameMaster )] public int AllianceMessageHue { get { return m_AllianceMessageHue; } set { m_AllianceMessageHue = value; } } [CommandProperty( AccessLevel.GameMaster )] public int Profession { get{ return m_Profession; } set{ m_Profession = value; } } public int StepsTaken { get{ return m_StepsTaken; } set{ m_StepsTaken = value; } } [CommandProperty( AccessLevel.GameMaster )] public bool IsStealthing // IsStealthing should be moved to Server.Mobiles { get { return m_IsStealthing; } set { m_IsStealthing = value; } } [CommandProperty( AccessLevel.GameMaster )] public bool IgnoreMobiles // IgnoreMobiles should be moved to Server.Mobiles { get { return m_IgnoreMobiles; } set { if( m_IgnoreMobiles != value ) { m_IgnoreMobiles = value; Delta( MobileDelta.Flags ); } } } [CommandProperty( AccessLevel.GameMaster )] public NpcGuild NpcGuild { get{ return m_NpcGuild; } set{ m_NpcGuild = value; } } [CommandProperty( AccessLevel.GameMaster )] public DateTime NpcGuildJoinTime { get{ return m_NpcGuildJoinTime; } set{ m_NpcGuildJoinTime = value; } } [CommandProperty( AccessLevel.GameMaster )] public DateTime LastOnline { get{ return m_LastOnline; } set{ m_LastOnline = value; } } [CommandProperty( AccessLevel.GameMaster )] public TimeSpan NpcGuildGameTime { get{ return m_NpcGuildGameTime; } set{ m_NpcGuildGameTime = value; } } [CommandProperty( AccessLevel.GameMaster )] public DateTime Camp { get{ return m_Camp; } set{ m_Camp = value; } } [CommandProperty( AccessLevel.GameMaster )] public DateTime Bedroll { get{ return m_Bedroll; } set{ m_Bedroll = value; } } #endregion #region PlayerFlags public PlayerFlag Flags { get{ return m_Flags; } set{ m_Flags = value; } } [CommandProperty( AccessLevel.GameMaster )] public bool PagingSquelched { get{ return GetFlag( PlayerFlag.PagingSquelched ); } set{ SetFlag( PlayerFlag.PagingSquelched, value ); } } [CommandProperty( AccessLevel.GameMaster )] public bool KarmaLocked { get{ return GetFlag( PlayerFlag.KarmaLocked ); } set{ SetFlag( PlayerFlag.KarmaLocked, value ); } } [CommandProperty( AccessLevel.GameMaster )] public bool UseOwnFilter { get{ return GetFlag( PlayerFlag.UseOwnFilter ); } set{ SetFlag( PlayerFlag.UseOwnFilter, value ); } } [CommandProperty( AccessLevel.GameMaster )] public bool AcceptGuildInvites { get{ return GetFlag( PlayerFlag.AcceptGuildInvites ); } set{ SetFlag( PlayerFlag.AcceptGuildInvites, value ); } } #endregion #region Auto Arrow Recovery private Dictionary m_RecoverableAmmo = new Dictionary(); public Dictionary RecoverableAmmo { get { return m_RecoverableAmmo; } } public void RecoverAmmo() { } #endregion private DateTime m_AnkhNextUse; [CommandProperty( AccessLevel.GameMaster )] public DateTime AnkhNextUse { get{ return m_AnkhNextUse; } set{ m_AnkhNextUse = value; } } [CommandProperty( AccessLevel.GameMaster )] public TimeSpan DisguiseTimeLeft { get{ return DisguiseTimers.TimeRemaining( this ); } } private DateTime m_PeacedUntil; [CommandProperty( AccessLevel.GameMaster )] public DateTime PeacedUntil { get { return m_PeacedUntil; } set { m_PeacedUntil = value; } } public static Direction GetDirection4( Point3D from, Point3D to ) { int dx = from.X - to.X; int dy = from.Y - to.Y; int rx = dx - dy; int ry = dx + dy; Direction ret; if ( rx >= 0 && ry >= 0 ) ret = Direction.West; else if ( rx >= 0 && ry < 0 ) ret = Direction.South; else if ( rx < 0 && ry < 0 ) ret = Direction.East; else ret = Direction.North; return ret; } public override bool OnDroppedItemToWorld( Item item, Point3D location ) { if ( !base.OnDroppedItemToWorld( item, location ) ) return false; IPooledEnumerable mobiles = Map.GetMobilesInRange( location, 0 ); foreach ( Mobile m in mobiles ) { if ( m.Z >= location.Z && m.Z < location.Z + 16 ) { mobiles.Free(); return false; } } mobiles.Free(); BounceInfo bi = item.GetBounce(); if ( bi != null ) { Type type = item.GetType(); if ( type.IsDefined( typeof( FurnitureAttribute ), true ) || type.IsDefined( typeof( DynamicFlipingAttribute ), true ) ) { object[] objs = type.GetCustomAttributes( typeof( FlipableAttribute ), true ); if ( objs != null && objs.Length > 0 ) { FlipableAttribute fp = objs[0] as FlipableAttribute; if ( fp != null ) { int[] itemIDs = fp.ItemIDs; Point3D oldWorldLoc = bi.m_WorldLoc; Point3D newWorldLoc = location; if ( oldWorldLoc.X != newWorldLoc.X || oldWorldLoc.Y != newWorldLoc.Y ) { Direction dir = GetDirection4( oldWorldLoc, newWorldLoc ); if ( itemIDs.Length == 2 ) { switch ( dir ) { case Direction.North: case Direction.South: item.ItemID = itemIDs[0]; break; case Direction.East: case Direction.West: item.ItemID = itemIDs[1]; break; } } else if ( itemIDs.Length == 4 ) { switch ( dir ) { case Direction.South: item.ItemID = itemIDs[0]; break; case Direction.East: item.ItemID = itemIDs[1]; break; case Direction.North: item.ItemID = itemIDs[2]; break; case Direction.West: item.ItemID = itemIDs[3]; break; } } } } } } } return true; } public override int GetPacketFlags() { int flags = base.GetPacketFlags(); if ( m_IgnoreMobiles ) flags |= 0x10; return flags; } public override int GetOldPacketFlags() { int flags = base.GetOldPacketFlags(); if ( m_IgnoreMobiles ) flags |= 0x10; return flags; } public bool GetFlag( PlayerFlag flag ) { return ( (m_Flags & flag) != 0 ); } public void SetFlag( PlayerFlag flag, bool value ) { if ( value ) m_Flags |= flag; else m_Flags &= ~flag; } public DesignContext DesignContext { get{ return m_DesignContext; } set{ m_DesignContext = value; } } public static void Initialize() { if ( FastwalkPrevention ) PacketHandlers.RegisterThrottler( 0x02, new ThrottlePacketCallback( MovementThrottle_Callback ) ); EventSink.Login += new LoginEventHandler( OnLogin ); EventSink.Logout += new LogoutEventHandler( OnLogout ); EventSink.Connected += new ConnectedEventHandler( EventSink_Connected ); EventSink.Disconnected += new DisconnectedEventHandler( EventSink_Disconnected ); } protected override void OnRaceChange( Race oldRace ) { ValidateEquipment(); } public override int MaxWeight { get { return (40 + (int)(3.5 * this.Str)); } } private int m_LastGlobalLight = -1, m_LastPersonalLight = -1; public override void OnNetStateChanged() { m_LastGlobalLight = -1; m_LastPersonalLight = -1; } public override void ComputeBaseLightLevels( out int global, out int personal ) { global = LightCycle.ComputeLevelFor( this ); personal = this.LightLevel; } public override void CheckLightLevels( bool forceResend ) { NetState ns = this.NetState; if ( ns == null ) return; int global, personal; ComputeLightLevels( out global, out personal ); if ( !forceResend ) forceResend = ( global != m_LastGlobalLight || personal != m_LastPersonalLight ); if ( !forceResend ) return; m_LastGlobalLight = global; m_LastPersonalLight = personal; ns.Send( GlobalLightLevel.Instantiate( global ) ); ns.Send( new PersonalLightLevel( this, personal ) ); } private static void OnLogin( LoginEventArgs e ) { Mobile from = e.Mobile; if ( AccountHandler.LockdownLevel > AccessLevel.Player ) { string notice; Accounting.Account acct = from.Account as Accounting.Account; if ( acct == null || !acct.HasAccess( from.NetState ) ) { if ( from.AccessLevel == AccessLevel.Player ) notice = "The server is currently under lockdown. No players are allowed to log in at this time."; else notice = "The server is currently under lockdown. You do not have sufficient access level to connect."; Timer.DelayCall( TimeSpan.FromSeconds( 1.0 ), new TimerStateCallback( Disconnect ), from ); } else if ( from.AccessLevel >= AccessLevel.Administrator ) { notice = "The server is currently under lockdown. As you are an administrator, you may change this from the [Admin gump."; } else { notice = "The server is currently under lockdown. You have sufficient access level to connect."; } from.SendGump( new NoticeGump( 1060637, 30720, notice, 0xFFC000, 300, 140, null, null ) ); return; } } private bool m_NoDeltaRecursion; public void ValidateEquipment() { if ( m_NoDeltaRecursion || Map == null || Map == Map.Internal ) return; if ( this.Items == null ) return; m_NoDeltaRecursion = true; Timer.DelayCall( TimeSpan.Zero, new TimerCallback( ValidateEquipment_Sandbox ) ); } private void ValidateEquipment_Sandbox() { try { if ( Map == null || Map == Map.Internal ) return; List items = this.Items; if ( items == null ) return; bool moved = false; int str = this.Str; int dex = this.Dex; int intel = this.Int; Mobile from = this; for ( int i = items.Count - 1; i >= 0; --i ) { if ( i >= items.Count ) continue; Item item = items[i]; if ( item is BaseWeapon ) { BaseWeapon weapon = (BaseWeapon)item; bool drop = false; if( dex < weapon.DexRequirement ) drop = true; else if( str < Ultima.Scale( weapon.StrRequirement, 100 - weapon.GetLowerStatReq() ) ) drop = true; else if( intel < weapon.IntRequirement ) drop = true; if ( drop ) { string name = weapon.Name; if ( name == null ) name = String.Format( "#{0}", weapon.LabelNumber ); from.SendLocalizedMessage( 1062001, name ); // You can no longer wield your ~1_WEAPON~ from.AddToBackpack( weapon ); moved = true; } } else if ( item is BaseArmor ) { BaseArmor armor = (BaseArmor)item; bool drop = false; if ( !armor.AllowMaleWearer && !from.Female && from.AccessLevel < AccessLevel.GameMaster ) { drop = true; } else if ( !armor.AllowFemaleWearer && from.Female && from.AccessLevel < AccessLevel.GameMaster ) { drop = true; } else { int strBonus = armor.ComputeStatBonus( StatType.Str ), strReq = armor.ComputeStatReq( StatType.Str ); int dexBonus = armor.ComputeStatBonus( StatType.Dex ), dexReq = armor.ComputeStatReq( StatType.Dex ); int intBonus = armor.ComputeStatBonus( StatType.Int ), intReq = armor.ComputeStatReq( StatType.Int ); if( dex < dexReq || (dex + dexBonus) < 1 ) drop = true; else if( str < strReq || (str + strBonus) < 1 ) drop = true; else if( intel < intReq || (intel + intBonus) < 1 ) drop = true; } if ( drop ) { string name = armor.Name; if ( name == null ) name = String.Format( "#{0}", armor.LabelNumber ); if ( armor is BaseShield ) from.SendLocalizedMessage( 1062003, name ); // You can no longer equip your ~1_SHIELD~ else from.SendLocalizedMessage( 1062002, name ); // You can no longer wear your ~1_ARMOR~ from.AddToBackpack( armor ); moved = true; } } else if ( item is BaseClothing ) { BaseClothing clothing = (BaseClothing)item; bool drop = false; if ( !clothing.AllowMaleWearer && !from.Female && from.AccessLevel < AccessLevel.GameMaster ) { drop = true; } else if ( !clothing.AllowFemaleWearer && from.Female && from.AccessLevel < AccessLevel.GameMaster ) { drop = true; } if ( drop ) { string name = clothing.Name; if ( name == null ) name = String.Format( "#{0}", clothing.LabelNumber ); from.SendLocalizedMessage( 1062002, name ); // You can no longer wear your ~1_ARMOR~ from.AddToBackpack( clothing ); moved = true; } } } if ( moved ) from.SendLocalizedMessage( 500647 ); // Some equipment has been moved to your backpack. } catch ( Exception e ) { Console.WriteLine( e ); } finally { m_NoDeltaRecursion = false; } } public override void Delta( MobileDelta flag ) { base.Delta( flag ); if ( (flag & MobileDelta.Stat) != 0 ) ValidateEquipment(); } private static void Disconnect( object state ) { NetState ns = ((Mobile)state).NetState; if ( ns != null ) ns.Dispose(); } private static void OnLogout( LogoutEventArgs e ) { } private static void EventSink_Connected( ConnectedEventArgs e ) { PlayerMobile pm = e.Mobile as PlayerMobile; if ( pm != null ) { pm.m_SessionStart = DateTime.Now; pm.LastOnline = DateTime.Now; } DisguiseTimers.StartTimer( e.Mobile ); } private static void EventSink_Disconnected( DisconnectedEventArgs e ) { Mobile from = e.Mobile; DesignContext context = DesignContext.Find( from ); if ( context != null ) { /* Client disconnected * - Remove design context * - Eject all from house * - Restore relocated entities */ // Remove design context DesignContext.Remove( from ); // Eject all from house from.RevealingAction(); foreach ( Item item in context.Foundation.GetItems() ) item.Location = context.Foundation.BanLocation; foreach ( Mobile mobile in context.Foundation.GetMobiles() ) mobile.Location = context.Foundation.BanLocation; // Restore relocated entities context.Foundation.RestoreRelocatedEntities(); } PlayerMobile pm = e.Mobile as PlayerMobile; if ( pm != null ) { pm.m_GameTime += (DateTime.Now - pm.m_SessionStart); pm.m_SpeechLog = null; pm.LastOnline = DateTime.Now; } DisguiseTimers.StopTimer( from ); if ( Server.Misc.Settings.LogoutSave() ){ World.Save( true, false ); } } public override void RevealingAction() { if ( m_DesignContext != null ) return; Spells.Sixth.InvisibilitySpell.RemoveTimer( this ); base.RevealingAction(); m_IsStealthing = false; // IsStealthing should be moved to Server.Mobiles } [CommandProperty( AccessLevel.GameMaster )] public override bool Hidden { get { return base.Hidden; } set { base.Hidden = value; } } public override void OnSubItemAdded( Item item ) { if ( AccessLevel < AccessLevel.GameMaster && item.IsChildOf( this.Backpack ) ) { int maxWeight = WeightOverloading.GetMaxWeight( this ); int curWeight = Mobile.BodyWeight + this.TotalWeight; if ( curWeight > maxWeight ) this.SendLocalizedMessage( 1019035, true, String.Format( " : {0} / {1}", curWeight, maxWeight ) ); } } public override bool CanBeHarmful( Mobile target, bool message, bool ignoreOurBlessedness ) { if ( m_DesignContext != null || (target is PlayerMobile && ((PlayerMobile)target).m_DesignContext != null) ) return false; if ( target.Invulnerable || 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 CanBeBeneficial( Mobile target, bool message, bool allowDead ) { if ( m_DesignContext != null || (target is PlayerMobile && ((PlayerMobile)target).m_DesignContext != null) ) return false; return base.CanBeBeneficial( target, message, allowDead ); } public override bool CheckContextMenuDisplay( IEntity target ) { return ( m_DesignContext == null ); } public override void OnItemAdded( Item item ) { base.OnItemAdded( item ); if ( item is BaseArmor || item is BaseWeapon ) { Hits=Hits; Stam=Stam; Mana=Mana; } if ( this.NetState != null ) CheckLightLevels( false ); } public override void OnItemRemoved( Item item ) { base.OnItemRemoved( item ); if ( item is BaseArmor || item is BaseWeapon ) { Hits=Hits; Stam=Stam; Mana=Mana; } if ( this.NetState != null ) CheckLightLevels( false ); } public override double ArmorRating { get { //BaseArmor ar; double rating = 0.0; AddArmorRating( ref rating, NeckArmor ); AddArmorRating( ref rating, HandArmor ); AddArmorRating( ref rating, HeadArmor ); AddArmorRating( ref rating, ArmsArmor ); AddArmorRating( ref rating, LegsArmor ); AddArmorRating( ref rating, ChestArmor ); AddArmorRating( ref rating, ShieldArmor ); return VirtualArmor + VirtualArmorMod + rating; } } private void AddArmorRating( ref double rating, Item armor ) { if ( armor is BaseArmor ) { BaseArmor ar = armor as BaseArmor; rating += ar.ArmorRatingScaled; } } #region [Stats]Max [CommandProperty( AccessLevel.GameMaster )] public override int HitsMax { get { int hits = this.RawStr; int strOffs = GetStatOffset( StatType.Str ); hits = (hits / 2) + strOffs; hits = (int)(hits * Server.Misc.Settings.HitPoints()); hits = hits + 50; return hits; } } [CommandProperty( AccessLevel.GameMaster )] public override int StamMax { get{ return base.StamMax; } } [CommandProperty( AccessLevel.GameMaster )] public override int ManaMax { get{ return base.ManaMax; } } #endregion #region Stat Getters/Setters [CommandProperty( AccessLevel.GameMaster )] public override int Str { get { return base.Str; } set { base.Str = value; } } [CommandProperty( AccessLevel.GameMaster )] public override int Int { get { return base.Int; } set { base.Int = value; } } [CommandProperty( AccessLevel.GameMaster )] public override int Dex { get { return base.Dex; } set { base.Dex = value; } } #endregion public override bool Move( Direction d ) { NetState ns = this.NetState; if ( ns != null ) { if ( HasGump( typeof( ResurrectGump ) ) ) { if ( Alive ) { CloseGump( typeof( ResurrectGump ) ); } else { SendLocalizedMessage( 500111 ); // You are frozen and cannot move. return false; } } } TimeSpan speed = ComputeMovementSpeed( d ); bool res; if ( !Alive ) Server.Movement.MovementImpl.IgnoreMovableImpassables = true; res = base.Move( d ); Server.Movement.MovementImpl.IgnoreMovableImpassables = false; if ( !res ) return false; m_NextMovementTime += speed; return true; } public override bool CheckMovement( Direction d, out int newZ ) { DesignContext context = m_DesignContext; if ( context == null ) return base.CheckMovement( d, out newZ ); HouseFoundation foundation = context.Foundation; newZ = foundation.Z + HouseFoundation.GetLevelZ( context.Level, context.Foundation ); int newX = this.X, newY = this.Y; Movement.Movement.Offset( d, ref newX, ref newY ); int startX = foundation.X + foundation.Components.Min.X + 1; int startY = foundation.Y + foundation.Components.Min.Y + 1; int endX = startX + foundation.Components.Width - 1; int endY = startY + foundation.Components.Height - 2; return ( newX >= startX && newY >= startY && newX < endX && newY < endY && Map == foundation.Map ); } public override bool AllowItemUse( Item item ) { return DesignContext.Check( this ); } public override bool AllowSkillUse( SkillName skill ) { return DesignContext.Check( this ); } public override void SetLocation( Point3D loc, bool isTeleport ) { if ( !isTeleport && AccessLevel == AccessLevel.Player ) { // moving, not teleporting int zDrop = ( this.Location.Z - loc.Z ); if ( zDrop > 20 ) // we fell more than one story Hits -= ((zDrop / 20) * 10) - 5; // deal some damage; does not kill, disrupt, etc } base.SetLocation( loc, isTeleport ); } public override void GetContextMenuEntries( Mobile from, List list ) { base.GetContextMenuEntries( from, list ); if ( from == this ) { BaseHouse house = BaseHouse.FindHouseAt( this ); if ( house != null ) { if ( Alive && house.InternalizedVendors.Count > 0 && house.IsOwner( this ) ) list.Add( new CallbackEntry( 6204, new ContextCallback( GetVendor ) ) ); if ( house.IsAosRules ) list.Add( new CallbackEntry( 6207, new ContextCallback( LeaveHouse ) ) ); } } } private void GetVendor() { BaseHouse house = BaseHouse.FindHouseAt( this ); if ( CheckAlive() && house != null && house.IsOwner( this ) && house.InternalizedVendors.Count > 0 ) { CloseGump( typeof( ReclaimVendorGump ) ); SendGump( new ReclaimVendorGump( house ) ); } } private void LeaveHouse() { BaseHouse house = BaseHouse.FindHouseAt( this ); if ( house != null ) this.Location = house.BanLocation; } private delegate void ContextCallback(); private class CallbackEntry : ContextMenuEntry { private ContextCallback m_Callback; public CallbackEntry( int number, ContextCallback callback ) : this( number, -1, callback ) { } public CallbackEntry( int number, int range, ContextCallback callback ) : base( number, range ) { m_Callback = callback; } public override void OnClick() { if ( m_Callback != null ) m_Callback(); } } public override void DisruptiveAction() { base.DisruptiveAction(); } public override void OnDoubleClick( Mobile from ) { if ( this == from && !Warmode ) { IMount mount = Mount; if ( mount != null && !DesignContext.Check( this ) ) return; } base.OnDoubleClick( from ); } public override void DisplayPaperdollTo( Mobile to ) { if ( DesignContext.Check( this ) ) base.DisplayPaperdollTo( to ); } private static bool m_NoRecursion; public override bool CheckEquip( Item item ) { if ( !base.CheckEquip( item ) ) return false; if ( this.AccessLevel < AccessLevel.GameMaster && item.Layer != Layer.Mount && this.HasTrade ) { BounceInfo bounce = item.GetBounce(); if ( bounce != null ) { if ( bounce.m_Parent is Item ) { Item parent = (Item) bounce.m_Parent; if ( parent == this.Backpack || parent.IsChildOf( this.Backpack ) ) return true; } else if ( bounce.m_Parent == this ) { return true; } } SendLocalizedMessage( 1004042 ); // You can only equip what you are already carrying while you have a trade pending. return false; } return true; } public override bool CheckTrade( Mobile to, Item item, SecureTradeContainer cont, bool message, bool checkItems, int plusItems, int plusWeight ) { int msgNum = 0; if ( cont == null ) { if ( to.Holding != null ) msgNum = 1062727; // You cannot trade with someone who is dragging something. else if ( this.HasTrade ) msgNum = 1062781; // You are already trading with someone else! else if ( to.HasTrade ) msgNum = 1062779; // That person is already involved in a trade } if ( msgNum == 0 ) { if ( cont != null ) { plusItems += cont.TotalItems; plusWeight += cont.TotalWeight; } if ( this.Backpack == null || !this.Backpack.CheckHold( this, item, false, checkItems, plusItems, plusWeight ) ) msgNum = 1004040; // You would not be able to hold this if the trade failed. else if ( to.Backpack == null || !to.Backpack.CheckHold( to, item, false, checkItems, plusItems, plusWeight ) ) msgNum = 1004039; // The recipient of this trade would not be able to carry this. else msgNum = CheckContentForTrade( item ); } if ( msgNum != 0 ) { if ( message ) this.SendLocalizedMessage( msgNum ); return false; } return true; } private static int CheckContentForTrade( Item item ) { if ( item is TrapableContainer && ((TrapableContainer)item).TrapType != TrapType.None ) return 1004044; // You may not trade trapped items. if ( SkillHandlers.StolenItem.IsStolen( item ) ) return 1004043; // You may not trade recently stolen items. if ( item is Container ) { foreach ( Item subItem in item.Items ) { int msg = CheckContentForTrade( subItem ); if ( msg != 0 ) return msg; } } return 0; } public override bool CheckNonlocalDrop( Mobile from, Item item, Item target ) { if ( !base.CheckNonlocalDrop( from, item, target ) ) return false; if ( from.AccessLevel >= AccessLevel.GameMaster ) return true; Container pack = this.Backpack; if ( from == this && this.HasTrade && ( target == pack || target.IsChildOf( pack ) ) ) { BounceInfo bounce = item.GetBounce(); if ( bounce != null && bounce.m_Parent is Item ) { Item parent = (Item) bounce.m_Parent; if ( parent == pack || parent.IsChildOf( pack ) ) return true; } SendLocalizedMessage( 1004041 ); // You can't do that while you have a trade pending. return false; } return true; } protected override void OnLocationChange( Point3D oldLocation ) { Server.Misc.RegionMusic.MusicRegion( this, this.Map, this.Location, oldLocation ); CheckLightLevels( false ); DesignContext context = m_DesignContext; if ( context == null || m_NoRecursion ) return; m_NoRecursion = true; HouseFoundation foundation = context.Foundation; int newX = this.X, newY = this.Y; int newZ = foundation.Z + HouseFoundation.GetLevelZ( context.Level, context.Foundation ); int startX = foundation.X + foundation.Components.Min.X + 1; int startY = foundation.Y + foundation.Components.Min.Y + 1; int endX = startX + foundation.Components.Width - 1; int endY = startY + foundation.Components.Height - 2; if ( newX >= startX && newY >= startY && newX < endX && newY < endY && Map == foundation.Map ) { if ( Z != newZ ) Location = new Point3D( X, Y, newZ ); m_NoRecursion = false; return; } Location = new Point3D( foundation.X, foundation.Y, newZ ); Map = foundation.Map; m_NoRecursion = false; } public override void GetProperties( ObjectPropertyList list ) { base.GetProperties( list ); //string sTitle = GetNPCGuild( this ); //list.Add( Utility.FixHtml( sTitle ) ); } public static string GetNPCGuild( Mobile m ) { string GuildTitle = ""; if ( m is PlayerMobile ) { PlayerMobile pm = (PlayerMobile)m; if ( pm.NpcGuild == NpcGuild.MagesGuild ){ GuildTitle = "Mages Guild"; } else if ( pm.NpcGuild == NpcGuild.WarriorsGuild ){ GuildTitle = "Warriors Guild"; } else if ( pm.NpcGuild == NpcGuild.ThievesGuild ){ GuildTitle = "Thieves Guild"; } else if ( pm.NpcGuild == NpcGuild.RangersGuild ){ GuildTitle = "Rangers Guild"; } else if ( pm.NpcGuild == NpcGuild.HealersGuild ){ GuildTitle = "Healers Guild"; } else if ( pm.NpcGuild == NpcGuild.TinkersGuild ){ GuildTitle = "Tinkers Guild"; } else if ( pm.NpcGuild == NpcGuild.TailorsGuild ){ GuildTitle = "Tailors Guild"; } else if ( pm.NpcGuild == NpcGuild.MarinersGuild ){ GuildTitle = "Mariners Guild"; } else if ( pm.NpcGuild == NpcGuild.BardsGuild ){ GuildTitle = "Bards Guild"; } else if ( pm.NpcGuild == NpcGuild.BlacksmithsGuild ){ GuildTitle = "Blacksmiths Guild"; } else if ( pm.NpcGuild == NpcGuild.AlchemistsGuild ){ GuildTitle = "Alchemists Guild"; } else if ( pm.NpcGuild == NpcGuild.CarpentryGuild ){ GuildTitle = "Carpenters Guild"; } else if ( pm.NpcGuild == NpcGuild.LibrariansGuild ){ GuildTitle = "Librarians Guild"; } else if ( pm.NpcGuild == NpcGuild.AssassinsGuild ){ GuildTitle = "Assassins Guild"; } } return GuildTitle; } public override bool OnMoveOver( Mobile m ) { if ( m is BaseCreature && !((BaseCreature)m).Controlled ) return ( !Alive || !m.Alive || IsDeadBondedPet || m.IsDeadBondedPet ) || ( Hidden && m.AccessLevel > AccessLevel.Player ); return base.OnMoveOver( m ); } public override bool CheckShove( Mobile shoved ) { if( m_IgnoreMobiles ) return true; else return base.CheckShove( shoved ); } protected override void OnMapChange( Map oldMap ) { InvalidateProperties(); Server.Misc.RegionMusic.MusicRegion( this, this.Map, this.Location, this.Location ); DesignContext context = m_DesignContext; if ( context == null || m_NoRecursion ) return; m_NoRecursion = true; HouseFoundation foundation = context.Foundation; if ( Map != foundation.Map ) Map = foundation.Map; m_NoRecursion = false; } public override void OnDamage( int amount, Mobile from, bool willKill ) { int disruptThreshold = 0; if ( amount > disruptThreshold ) { BandageContext c = BandageContext.GetContext( this ); if ( c != null ) c.Slip(); } WeightOverloading.FatigueOnDamage( this, amount ); if ( willKill && from is PlayerMobile ) Timer.DelayCall( TimeSpan.FromSeconds( 10 ), new TimerCallback( ((PlayerMobile) from).RecoverAmmo ) ); base.OnDamage( amount, from, willKill ); } public override void Resurrect() { bool wasAlive = this.Alive; base.Resurrect(); if ( this.Alive && !wasAlive ) { Item deathRobe = new DeathRobe(); Hits = HitsMax; Stam = StamMax; Mana = ManaMax; Hunger = 20; Thirst = 20; if ( !EquipItem( deathRobe ) ) deathRobe.Delete(); } } public override double RacialSkillBonus { get { return 0; } } public override void OnWarmodeChanged() { if ( !Warmode ) Timer.DelayCall( TimeSpan.FromSeconds( 10 ), new TimerCallback( RecoverAmmo ) ); } private bool FindItems_Callback(Item item) { if (!item.Deleted && item.LootType == LootType.Blessed ) { if (this.Backpack != item.ParentEntity) { return true; } } return false; } public static void RemoveMyClothes( Mobile m ) { if ( m.FindItemOnLayer( Layer.OuterTorso ) != null && !(m.FindItemOnLayer( Layer.OuterTorso ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.OuterTorso ).Delete(); } if ( m.FindItemOnLayer( Layer.MiddleTorso ) != null && !(m.FindItemOnLayer( Layer.MiddleTorso ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.MiddleTorso ).Delete(); } if ( m.FindItemOnLayer( Layer.OneHanded ) != null && !(m.FindItemOnLayer( Layer.OneHanded ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.OneHanded ).Delete(); } if ( m.FindItemOnLayer( Layer.TwoHanded ) != null && !(m.FindItemOnLayer( Layer.TwoHanded ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.TwoHanded ).Delete(); } if ( m.FindItemOnLayer( Layer.Bracelet ) != null && !(m.FindItemOnLayer( Layer.Bracelet ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.Bracelet ).Delete(); } if ( m.FindItemOnLayer( Layer.Ring ) != null && !(m.FindItemOnLayer( Layer.Ring ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.Ring ).Delete(); } if ( m.FindItemOnLayer( Layer.Helm ) != null && !(m.FindItemOnLayer( Layer.Helm ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.Helm ).Delete(); } if ( m.FindItemOnLayer( Layer.Arms ) != null && !(m.FindItemOnLayer( Layer.Arms ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.Arms ).Delete(); } if ( m.FindItemOnLayer( Layer.OuterLegs ) != null && !(m.FindItemOnLayer( Layer.OuterLegs ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.OuterLegs ).Delete(); } if ( m.FindItemOnLayer( Layer.Neck ) != null && !(m.FindItemOnLayer( Layer.Neck ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.Neck ).Delete(); } if ( m.FindItemOnLayer( Layer.Gloves ) != null && !(m.FindItemOnLayer( Layer.Gloves ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.Gloves ).Delete(); } if ( m.FindItemOnLayer( Layer.Talisman ) != null && !(m.FindItemOnLayer( Layer.Talisman ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.Talisman ).Delete(); } if ( m.FindItemOnLayer( Layer.Shoes ) != null && !(m.FindItemOnLayer( Layer.Shoes ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.Shoes ).Delete(); } if ( m.FindItemOnLayer( Layer.FirstValid ) != null && !(m.FindItemOnLayer( Layer.FirstValid ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.FirstValid ).Delete(); } if ( m.FindItemOnLayer( Layer.Waist ) != null && !(m.FindItemOnLayer( Layer.Waist ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.Waist ).Delete(); } if ( m.FindItemOnLayer( Layer.InnerLegs ) != null && !(m.FindItemOnLayer( Layer.InnerLegs ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.InnerLegs ).Delete(); } if ( m.FindItemOnLayer( Layer.InnerTorso ) != null && !(m.FindItemOnLayer( Layer.InnerTorso ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.InnerTorso ).Delete(); } if ( m.FindItemOnLayer( Layer.Pants ) != null && !(m.FindItemOnLayer( Layer.Pants ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.Pants ).Delete(); } if ( m.FindItemOnLayer( Layer.Shirt ) != null && !(m.FindItemOnLayer( Layer.Shirt ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.Shirt ).Delete(); } if ( m.FindItemOnLayer( Layer.Cloak ) != null && !(m.FindItemOnLayer( Layer.Cloak ).LootType == LootType.Blessed) ) { m.FindItemOnLayer( Layer.Cloak ).Delete(); } } public override bool OnBeforeDeath() { if ( this.LastKiller is Guard ) { BaseCreature guard = (BaseCreature)(this.LastKiller); Point3D p = new Point3D( 2002, 1494, -20 ); if ( Utility.RandomBool() ) { switch ( Utility.Random( 12 ) ) { case 0: p = new Point3D(985, 982, 0); break; case 1: p = new Point3D(985, 976, 0); break; case 2: p = new Point3D(985, 970, 0); break; case 3: p = new Point3D(985, 964, 0); break; case 4: p = new Point3D(985, 958, 0); break; case 5: p = new Point3D(998, 951, 0); break; case 6: p = new Point3D(1007, 951, 0); break; case 7: p = new Point3D(1013, 951, 0); break; case 8: p = new Point3D(1019, 964, 0); break; case 9: p = new Point3D(1019, 970, 0); break; case 10: p = new Point3D(1019, 976, 0); break; case 11: p = new Point3D(1019, 982, 0); break; }; } else { switch ( Utility.Random( 5 ) ) { case 0: p = new Point3D(2002, 1494, -20); break; case 1: p = new Point3D(2002, 1488, -20); break; case 2: p = new Point3D(2002, 1483, -20); break; case 3: p = new Point3D(2014, 1483, -20); break; case 4: p = new Point3D(2014, 1489, -20); break; }; } Map map = Map.Britannia; this.Criminal = false; if ( this.Kills > 4 ){ this.Kills = 4; } Hits = HitsMax; Stam = StamMax; Mana = ManaMax; Hunger = 20; Thirst = 20; List stuff = new List(); foreach( Item c in this.Backpack.Items ) { if ( c.LootType != LootType.Blessed ) { stuff.Add(c); } } foreach ( Item item in stuff ) { item.Delete(); } RemoveMyClothes( this ); if ( this.Mounted ) { Mobile horse = (Mobile)(this.Mount); Server.Mobiles.BaseMount.Dismount( this ); horse.Delete(); } if ( this.FindItemOnLayer( Layer.Shoes ) == null ) { this.AddItem( new Shoes( Utility.RandomNeutralHue() ) ); } if ( this.FindItemOnLayer( Layer.Pants ) == null ) { this.AddItem( new ShortPants( Utility.RandomNeutralHue() ) ); } if ( this.FindItemOnLayer( Layer.Shirt ) == null ) { this.AddItem( new Shirt( Utility.RandomNeutralHue() ) ); } this.SendMessage("You have been sent to prison!"); Server.Mobiles.BaseCreature.DeletePets( this ); this.MoveToWorld( p, map ); this.InvalidateProperties(); guard.Combatant = null; guard.Warmode = false; guard.InvalidateProperties(); return false; } NetState state = NetState; if ( state != null ) state.CancelAllTrades(); DropHolding(); if (Backpack != null && !Backpack.Deleted) { List ilist = Backpack.FindItemsByType(FindItems_Callback); for (int i = 0; i < ilist.Count; i++) { Backpack.AddItem(ilist[i]); } } RecoverAmmo(); return base.OnBeforeDeath(); } public override DeathMoveResult GetParentMoveResultFor( Item item ) { DeathMoveResult res = base.GetParentMoveResultFor( item ); return res; } public override DeathMoveResult GetInventoryMoveResultFor( Item item ) { DeathMoveResult res = base.GetInventoryMoveResultFor( item ); return res; } public override void OnDeath( Container c ) { base.OnDeath(c); HueMod = -1; NameMod = null; SetHairMods( -1, -1 ); PolymorphSpell.StopTimer( this ); IncognitoSpell.StopTimer( this ); DisguiseTimers.RemoveTimer( this ); EndAction( typeof( PolymorphSpell ) ); EndAction( typeof( IncognitoSpell ) ); SkillHandlers.StolenItem.ReturnOnDeath( this, c ); if ( m_PermaFlags.Count > 0 ) { m_PermaFlags.Clear(); if ( c is Corpse ) ((Corpse)c).Criminal = true; if ( SkillHandlers.Stealing.ClassicMode ) Criminal = true; } Mobile killer = this.FindMostRecentDamager( true ); if ( killer is BaseCreature ) { BaseCreature bc = (BaseCreature)killer; Mobile master = bc.GetMaster(); if( master != null ) killer = master; } Server.Guilds.Guild.HandleDeath( this, killer ); } private List m_PermaFlags; private List m_VisList; private Hashtable m_AntiMacroTable; private TimeSpan m_GameTime; private TimeSpan m_ShortTermElapse; private TimeSpan m_LongTermElapse; private DateTime m_SessionStart; private SkillName m_Learning = (SkillName)(-1); public SkillName Learning { get{ return m_Learning; } set{ m_Learning = value; } } public PlayerMobile() { m_VisList = new List(); m_PermaFlags = new List(); m_AntiMacroTable = new Hashtable(); m_RecentlyReported = new List(); m_GameTime = TimeSpan.Zero; m_ShortTermElapse = TimeSpan.FromHours( 8.0 ); m_LongTermElapse = TimeSpan.FromHours( 40.0 ); m_GuildRank = Guilds.RankDefinition.Lowest; } public override bool MutateSpeech( List hears, ref string text, ref object context ) { if ( Alive ) return false; return base.MutateSpeech( hears, ref text, ref context ); } public override void DoSpeech( string text, int[] keywords, MessageType type, int hue ) { if( Guilds.Guild.NewGuildSystem && (type == MessageType.Guild || type == MessageType.Alliance) ) { Guilds.Guild g = this.Guild as Guilds.Guild; if( g == null ) { SendLocalizedMessage( 1063142 ); // You are not in a guild! } else if( type == MessageType.Alliance ) { if( g.Alliance != null && g.Alliance.IsMember( g ) ) { //g.Alliance.AllianceTextMessage( hue, "[Alliance][{0}]: {1}", this.Name, text ); g.Alliance.AllianceChat( this, text ); SendToStaffMessage( this, "[Alliance]: {0}", text ); m_AllianceMessageHue = hue; } else { SendLocalizedMessage( 1071020 ); // You are not in an alliance! } } else //Type == MessageType.Guild { m_GuildMessageHue = hue; g.GuildChat( this, text ); SendToStaffMessage( this, "[Guild]: {0}", text ); } } else { base.DoSpeech( text, keywords, type, hue ); } } private static void SendToStaffMessage( Mobile from, string text ) { Packet p = null; foreach( NetState ns in from.GetClientsInRange( 8 ) ) { Mobile mob = ns.Mobile; if( mob != null && mob.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > from.AccessLevel ) { if( p == null ) p = Packet.Acquire( new UnicodeMessage( from.Serial, from.Body, MessageType.Regular, from.SpeechHue, 3, from.Language, from.Name, text ) ); ns.Send( p ); } } Packet.Release( p ); } private static void SendToStaffMessage( Mobile from, string format, params object[] args ) { SendToStaffMessage( from, String.Format( format, args ) ); } public override void Damage( int amount, Mobile from ) { base.Damage( amount, from ); } #region Poison public override ApplyPoisonResult ApplyPoison( Mobile from, Poison poison ) { if ( !Alive ) return ApplyPoisonResult.Immune; ApplyPoisonResult result = base.ApplyPoison( from, poison ); if ( from != null && result == ApplyPoisonResult.Poisoned && PoisonTimer is PoisonImpl.PoisonTimer ) (PoisonTimer as PoisonImpl.PoisonTimer).From = from; return result; } #endregion public PlayerMobile( Serial s ) : base( s ) { m_VisList = new List(); m_AntiMacroTable = new Hashtable(); } public List VisibilityList { get{ return m_VisList; } } public List PermaFlags { get{ return m_PermaFlags; } } public override bool IsHarmfulCriminal( Mobile target ) { if ( SkillHandlers.Stealing.ClassicMode && target is PlayerMobile && ((PlayerMobile)target).m_PermaFlags.Count > 0 ) { int noto = Notoriety.Compute( this, target ); if ( noto == Notoriety.Innocent ) target.Delta( MobileDelta.Noto ); return false; } if ( target is BaseCreature && ((BaseCreature)target).InitialInnocent && !((BaseCreature)target).Controlled ) return false; return base.IsHarmfulCriminal( target ); } public bool AntiMacroCheck( Skill skill, object obj ) { if ( obj == null || m_AntiMacroTable == null || this.AccessLevel != AccessLevel.Player ) return true; Hashtable tbl = (Hashtable)m_AntiMacroTable[skill]; if ( tbl == null ) m_AntiMacroTable[skill] = tbl = new Hashtable(); CountAndTimeStamp count = (CountAndTimeStamp)tbl[obj]; if ( count != null ) { if ( count.TimeStamp + SkillCheck.AntiMacroExpire <= DateTime.Now ) { count.Count = 1; return true; } else { ++count.Count; if ( count.Count <= SkillCheck.Allowance ) return true; else return false; } } else { tbl[obj] = count = new CountAndTimeStamp(); count.Count = 1; return true; } } private void RevertHair() { SetHairMods( -1, -1 ); } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); m_PeacedUntil = reader.ReadDateTime(); m_AnkhNextUse = reader.ReadDateTime(); m_AllianceMessageHue = reader.ReadEncodedInt(); m_GuildMessageHue = reader.ReadEncodedInt(); m_QuestLevel = reader.ReadInt(); m_MapMarkers = reader.ReadString(); int rank = reader.ReadEncodedInt(); int maxRank = Guilds.RankDefinition.Ranks.Length -1; if( rank > maxRank ) rank = maxRank; m_GuildRank = Guilds.RankDefinition.Ranks[rank]; m_LastOnline = reader.ReadDateTime(); m_Profession = reader.ReadEncodedInt(); if ( reader.ReadBool() ) { m_HairModID = reader.ReadInt(); m_HairModHue = reader.ReadInt(); m_BeardModID = reader.ReadInt(); m_BeardModHue = reader.ReadInt(); } m_NpcGuild = (NpcGuild)reader.ReadInt(); m_NpcGuildJoinTime = reader.ReadDateTime(); m_NpcGuildGameTime = reader.ReadTimeSpan(); m_Camp = reader.ReadDateTime(); m_Bedroll = reader.ReadDateTime(); m_PermaFlags = reader.ReadStrongMobileList(); m_Flags = (PlayerFlag)reader.ReadInt(); m_LongTermElapse = reader.ReadTimeSpan(); m_ShortTermElapse = reader.ReadTimeSpan(); m_GameTime = reader.ReadTimeSpan(); StatCap = 200; Skills.Cap = 7000; if (m_RecentlyReported == null) m_RecentlyReported = new List(); if ( !CharacterCreation.VerifyProfession( m_Profession ) ) m_Profession = 0; if ( m_PermaFlags == null ) m_PermaFlags = new List(); if( m_GuildRank == null ) m_GuildRank = Guilds.RankDefinition.Member; //Default to member if going from older verstion to new version (only time it should be null) if( m_LastOnline == DateTime.MinValue && Account != null ) m_LastOnline = ((Account)Account).LastLogin; if ( AccessLevel > AccessLevel.Player ) m_IgnoreMobiles = true; List list = this.Stabled; for ( int i = 0; i < list.Count; ++i ) { BaseCreature bc = list[i] as BaseCreature; if ( bc != null ) bc.IsStabled = true; } } public override void Serialize( GenericWriter writer ) { //cleanup our anti-macro table foreach ( Hashtable t in m_AntiMacroTable.Values ) { ArrayList remove = new ArrayList(); foreach ( CountAndTimeStamp time in t.Values ) { if ( time.TimeStamp + SkillCheck.AntiMacroExpire <= DateTime.Now ) remove.Add( time ); } for (int i=0;i 0 ) --Kills; } } public void ResetKillTime() { m_ShortTermElapse = this.GameTime + TimeSpan.FromHours( 8 ); m_LongTermElapse = this.GameTime + TimeSpan.FromHours( 40 ); } [CommandProperty( AccessLevel.GameMaster )] public DateTime SessionStart { get{ return m_SessionStart; } } [CommandProperty( AccessLevel.GameMaster )] public TimeSpan GameTime { get { if ( NetState != null ) return m_GameTime + (DateTime.Now - m_SessionStart); else return m_GameTime; } } public override bool CanSee( Mobile m ) { if ( m is PlayerMobile && ((PlayerMobile)m).m_VisList.Contains( this ) ) return true; return base.CanSee( m ); } public override bool CanSee( Item item ) { if ( m_DesignContext != null && m_DesignContext.Foundation.IsHiddenToCustomizer( item ) ) return false; return base.CanSee( item ); } public override void OnAfterDelete() { base.OnAfterDelete(); BaseHouse.HandleDeletion( this ); DisguiseTimers.RemoveTimer( this ); } public override bool NewGuildDisplay { get { return Server.Guilds.Guild.NewGuildSystem; } } protected override bool OnMove( Direction d ) { return base.OnMove( d ); } [CommandProperty( AccessLevel.GameMaster )] public override bool Paralyzed { get { return base.Paralyzed; } set { base.Paralyzed = value; } } #region Fastwalk Prevention private static bool FastwalkPrevention = true; // Is fastwalk prevention enabled? private static TimeSpan FastwalkThreshold = TimeSpan.FromSeconds( 0.4 ); // Fastwalk prevention will become active after 0.4 seconds private DateTime m_NextMovementTime; public virtual bool UsesFastwalkPrevention{ get{ return ( AccessLevel < AccessLevel.Counselor ); } } public override TimeSpan ComputeMovementSpeed( Direction dir, bool checkTurning ) { if ( checkTurning && (dir & Direction.Mask) != (this.Direction & Direction.Mask) ) return Mobile.RunMount; // We are NOT actually moving (just a direction change) bool running = ( (dir & Direction.Running) != 0 ); bool onHorse = ( this.Mount != null ); if( onHorse ) return ( running ? Mobile.RunMount : Mobile.WalkMount ); return ( running ? Mobile.RunFoot : Mobile.WalkFoot ); } public static bool MovementThrottle_Callback( NetState ns ) { PlayerMobile pm = ns.Mobile as PlayerMobile; if ( pm == null || !pm.UsesFastwalkPrevention ) return true; if ( pm.m_NextMovementTime == DateTime.MinValue ) { // has not yet moved pm.m_NextMovementTime = DateTime.Now; return true; } TimeSpan ts = pm.m_NextMovementTime - DateTime.Now; if ( ts < TimeSpan.Zero ) { // been a while since we've last moved pm.m_NextMovementTime = DateTime.Now; return true; } return ( ts < FastwalkThreshold ); } #endregion #region Hair and beard mods private int m_HairModID = -1, m_HairModHue; private int m_BeardModID = -1, m_BeardModHue; public void SetHairMods( int hairID, int beardID ) { if ( hairID == -1 ) InternalRestoreHair( true, ref m_HairModID, ref m_HairModHue ); else if ( hairID != -2 ) InternalChangeHair( true, hairID, ref m_HairModID, ref m_HairModHue ); if ( beardID == -1 ) InternalRestoreHair( false, ref m_BeardModID, ref m_BeardModHue ); else if ( beardID != -2 ) InternalChangeHair( false, beardID, ref m_BeardModID, ref m_BeardModHue ); } private void CreateHair( bool hair, int id, int hue ) { if( hair ) { //TODO Verification? HairItemID = id; RecordHair = id; HairHue = hue; } else { FacialHairItemID = id; RecordBeard = id; FacialHairHue = hue; } } private void InternalRestoreHair( bool hair, ref int id, ref int hue ) { if ( id == -1 ) return; if ( hair ) { HairItemID = 0; RecordHair = 0; } else { FacialHairItemID = 0; RecordBeard = 0; } //if( id != 0 ) CreateHair( hair, id, hue ); id = -1; hue = 0; } private void InternalChangeHair( bool hair, int id, ref int storeID, ref int storeHue ) { if ( storeID == -1 ) { storeID = hair ? HairItemID : FacialHairItemID; storeHue = hair ? HairHue : FacialHairHue; } CreateHair( hair, id, 0 ); } #endregion #region Speech log private SpeechLog m_SpeechLog; public SpeechLog SpeechLog{ get{ return m_SpeechLog; } } public override void OnSpeech( SpeechEventArgs e ) { if ( SpeechLog.Enabled && this.NetState != null ) { if ( m_SpeechLog == null ) m_SpeechLog = new SpeechLog(); m_SpeechLog.Add( e.Mobile, e.Speech ); } } #endregion } }