using System; using System.Collections; using Server; using Server.Network; using Server.Mobiles; namespace Server.Items { [FlipableAttribute( 0x100A/*East*/, 0x100B/*South*/ )] public class ArcheryButte : AddonComponent { private double m_MinSkill; private double m_MaxSkill; private int m_Arrows, m_Bolts; private DateTime m_LastUse; [CommandProperty( AccessLevel.GameMaster )] public double MinSkill { get{ return m_MinSkill; } set{ m_MinSkill = value; } } [CommandProperty( AccessLevel.GameMaster )] public double MaxSkill { get{ return m_MaxSkill; } set{ m_MaxSkill = value; } } [CommandProperty( AccessLevel.GameMaster )] public DateTime LastUse { get{ return m_LastUse; } set{ m_LastUse = value; } } [CommandProperty( AccessLevel.GameMaster )] public bool FacingEast { get{ return ( ItemID == 0x100A ); } set{ ItemID = value ? 0x100A : 0x100B; } } [CommandProperty( AccessLevel.GameMaster )] public int Arrows { get{ return m_Arrows; } set{ m_Arrows = value; } } [CommandProperty( AccessLevel.GameMaster )] public int Bolts { get{ return m_Bolts; } set{ m_Bolts = value; } } [Constructable] public ArcheryButte() : this( 0x100A ) { } public ArcheryButte( int itemID ) : base( itemID ) { m_MinSkill = -25.0; m_MaxSkill = +25.0; } public ArcheryButte( Serial serial ) : base( serial ) { } public override void OnDoubleClick( Mobile from ) { if ( (m_Arrows > 0 || m_Bolts > 0) && from.InRange( GetWorldLocation(), 1 ) ) Gather( from ); else Fire( from ); } public void Gather( Mobile from ) { from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500592 ); // You gather the arrows and bolts. if ( m_Arrows > 0 ) from.AddToBackpack( new Arrow( m_Arrows ) ); if ( m_Bolts > 0 ) from.AddToBackpack( new Bolt( m_Bolts ) ); m_Arrows = 0; m_Bolts = 0; m_Entries = null; } private static TimeSpan UseDelay = TimeSpan.FromSeconds( 2.0 ); private class ScoreEntry { private int m_Total; private int m_Count; public int Total{ get{ return m_Total; } set{ m_Total = value; } } public int Count{ get{ return m_Count; } set{ m_Count = value; } } public void Record( int score ) { m_Total += score; m_Count += 1; } public ScoreEntry() { } } private Hashtable m_Entries; private ScoreEntry GetEntryFor( Mobile from ) { if ( m_Entries == null ) m_Entries = new Hashtable(); ScoreEntry e = (ScoreEntry)m_Entries[from]; if ( e == null ) m_Entries[from] = e = new ScoreEntry(); return e; } public void Fire( Mobile from ) { BaseRanged bow = from.Weapon as BaseRanged; if ( bow == null ) { SendLocalizedMessageTo( from, 500593 ); // You must practice with ranged weapons on this. return; } if ( DateTime.Now < (m_LastUse + UseDelay) ) return; Point3D worldLoc = GetWorldLocation(); if ( FacingEast ? from.X <= worldLoc.X : from.Y <= worldLoc.Y ) { from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500596 ); // You would do better to stand in front of the archery butte. return; } if ( FacingEast ? from.Y != worldLoc.Y : from.X != worldLoc.X ) { from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500597 ); // You aren't properly lined up with the archery butte to get an accurate shot. return; } if ( !from.InRange( worldLoc, 6 ) ) { from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500598 ); // You are too far away from the archery butte to get an accurate shot. return; } else if ( from.InRange( worldLoc, 4 ) ) { from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500599 ); // You are too close to the target. return; } Container pack = from.Backpack; Type ammoType = bow.AmmoType; bool isArrow = ( ammoType == typeof( Arrow ) ); bool isBolt = ( ammoType == typeof( Bolt ) ); bool isKnown = ( isArrow || isBolt ); if ( from is PlayerMobile && ( pack == null || !pack.ConsumeTotal( ammoType, 1 ) ) ) { if ( isArrow ) from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500594 ); // You do not have any arrows with which to practice. else if ( isBolt ) from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 500595 ); // You do not have any crossbow bolts with which to practice. else SendLocalizedMessageTo( from, 500593 ); // You must practice with ranged weapons on this. return; } m_LastUse = DateTime.Now; from.Direction = from.GetDirectionTo( GetWorldLocation() ); bow.PlaySwingAnimation( from ); from.MovingEffect( this, bow.EffectID, 18, 1, false, false ); ScoreEntry se = GetEntryFor( from ); if ( from is PlayerMobile && !from.CheckSkill( bow.Skill, m_MinSkill, m_MaxSkill ) ) { from.PlaySound( bow.MissSound ); PublicOverheadMessage( MessageType.Regular, 0x3B2, 500604, from.Name ); // You miss the target altogether. se.Record( 0 ); if ( se.Count == 1 ) PublicOverheadMessage( MessageType.Regular, 0x3B2, 1062719, se.Total.ToString() ); else PublicOverheadMessage( MessageType.Regular, 0x3B2, 1042683, String.Format( "{0}\t{1}", se.Total, se.Count ) ); return; } Effects.PlaySound( Location, Map, 0x2B1 ); if ( from is PlayerMobile ) { double rand = Utility.RandomDouble(); int area, score, splitScore; if ( 0.10 > rand ) { area = 0; // bullseye score = 50; splitScore = 100; } else if ( 0.25 > rand ) { area = 1; // inner ring score = 10; splitScore = 20; } else if ( 0.50 > rand ) { area = 2; // middle ring score = 5; splitScore = 15; } else { area = 3; // outer ring score = 2; splitScore = 5; } bool split = ( isKnown && ((m_Arrows + m_Bolts) * 0.02) > Utility.RandomDouble() ); if ( split ) { PublicOverheadMessage( MessageType.Regular, 0x3B2, 1010027 + (isArrow ? 0 : 4) + area, from.Name ); } else { PublicOverheadMessage( MessageType.Regular, 0x3B2, 1010035 + area, from.Name ); if ( isArrow ) ++m_Arrows; else if ( isBolt ) ++m_Bolts; } se.Record( split ? splitScore : score ); if ( se.Count == 1 ) PublicOverheadMessage( MessageType.Regular, 0x3B2, 1062719, se.Total.ToString() ); else PublicOverheadMessage( MessageType.Regular, 0x3B2, 1042683, String.Format( "{0}\t{1}", se.Total, se.Count ) ); } } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int) 0 ); writer.Write( m_MinSkill ); writer.Write( m_MaxSkill ); writer.Write( m_Arrows ); writer.Write( m_Bolts ); } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); switch ( version ) { case 0: { m_MinSkill = reader.ReadDouble(); m_MaxSkill = reader.ReadDouble(); m_Arrows = reader.ReadInt(); m_Bolts = reader.ReadInt(); if ( m_MinSkill == 0.0 && m_MaxSkill == 30.0 ) { m_MinSkill = -25.0; m_MaxSkill = +25.0; } break; } } } } public class ArcheryButteAddon : BaseAddon { public override BaseAddonDeed Deed{ get{ return new ArcheryButteDeed(); } } [Constructable] public ArcheryButteAddon() { AddComponent( new ArcheryButte( 0x100A ), 0, 0, 0 ); } public ArcheryButteAddon( Serial serial ) : base( serial ) { } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int) 0 ); // version } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); } } public class ArcheryButteDeed : BaseAddonDeed { public override BaseAddon Addon{ get{ return new ArcheryButteAddon(); } } public override int LabelNumber{ get{ return 1024106; } } // archery butte [Constructable] public ArcheryButteDeed() { } public ArcheryButteDeed( Serial serial ) : base( serial ) { } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int) 0 ); // version } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); } } }