using System; using System.Text; using System.Collections; using Server; using Server.Items; using Server.Gumps; using Server.Network; using Server.ContextMenus; using Server.Mobiles; using Server.Targeting; using System.Collections.Generic; using Server.Factions; using Server.Ethics; using Server.Ethics.Evil; using Server.Ethics.Hero; namespace Server.Engines.ConPVP { public enum TournamentStage { Inactive, Signup, Fighting } public enum GroupingType { HighVsLow, Nearest, Random } public enum TieType { Random, Highest, Lowest, FullElimination, FullAdvancement } public class TournamentRegistrar : Banker { private TournamentController m_Tournament; [CommandProperty( AccessLevel.GameMaster )] public TournamentController Tournament{ get{ return m_Tournament; } set{ m_Tournament = value; } } [Constructable] public TournamentRegistrar() { Timer.DelayCall( TimeSpan.FromSeconds( 30.0 ), TimeSpan.FromSeconds( 30.0 ), new TimerCallback( Announce_Callback ) ); } private void Announce_Callback() { Tournament tourny = null; if ( m_Tournament != null ) tourny = m_Tournament.Tournament; if ( tourny != null && tourny.Stage == TournamentStage.Signup ) PublicOverheadMessage( MessageType.Regular, 0x35, false, "Come one, come all! Do you aspire to be a fighter of great renown? Join this tournament and show the world your abilities." ); } public override void OnMovement( Mobile m, Point3D oldLocation ) { base.OnMovement( m, oldLocation ); Tournament tourny = null; if ( m_Tournament != null ) tourny = m_Tournament.Tournament; if ( InRange( m, 4 ) && !InRange( oldLocation, 4 ) && tourny != null && tourny.Stage == TournamentStage.Signup && m.CanBeginAction( this ) ) { Ladder ladder = Ladder.Instance; if ( ladder != null ) { LadderEntry entry = ladder.Find( m ); if ( entry != null && Ladder.GetLevel( entry.Experience ) < tourny.LevelRequirement ) return; } if ( tourny.IsFactionRestricted && Faction.Find( m ) == null ) { return; } if ( tourny.HasParticipant( m ) ) return; PrivateOverheadMessage( MessageType.Regular, 0x35, false, String.Format( "Hello m'{0}. Dost thou wish to enter this tournament? You need only to write your name in this book.", m.Female ? "Lady" : "Lord" ), m.NetState ); m.BeginAction( this ); Timer.DelayCall( TimeSpan.FromSeconds( 10.0 ), new TimerStateCallback( ReleaseLock_Callback ), m ); } } private void ReleaseLock_Callback( object obj ) { ((Mobile)obj).EndAction( this ); } public TournamentRegistrar( Serial serial ) : base( serial ) { } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int) 0 ); writer.Write( (Item) m_Tournament ); } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); switch ( version ) { case 0: { m_Tournament = reader.ReadItem() as TournamentController; break; } } Timer.DelayCall( TimeSpan.FromSeconds( 30.0 ), TimeSpan.FromSeconds( 30.0 ), new TimerCallback( Announce_Callback ) ); } } public class TournamentSignupItem : Item { private TournamentController m_Tournament; private Mobile m_Registrar; [CommandProperty( AccessLevel.GameMaster )] public TournamentController Tournament{ get{ return m_Tournament; } set{ m_Tournament = value; } } [CommandProperty( AccessLevel.GameMaster )] public Mobile Registrar{ get{ return m_Registrar; } set{ m_Registrar = value; } } public override string DefaultName { get { return "tournament signup book"; } } [Constructable] public TournamentSignupItem() : base( 4029 ) { Movable = false; } public override void OnDoubleClick( Mobile from ) { if ( !from.InRange( GetWorldLocation(), 2 ) ) { from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1019045 ); // I can't reach that } else if ( m_Tournament != null ) { Tournament tourny = m_Tournament.Tournament; if ( tourny != null ) { if ( m_Registrar != null ) m_Registrar.Direction = m_Registrar.GetDirectionTo( this ); switch ( tourny.Stage ) { case TournamentStage.Fighting: { if ( m_Registrar != null ) { if ( tourny.HasParticipant( from ) ) { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, "Excuse me? You are already signed up.", from.NetState ); } else { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "The tournament has already begun. You are too late to signup now.", from.NetState ); } } break; } case TournamentStage.Inactive: { if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, "The tournament is closed.", from.NetState ); break; } case TournamentStage.Signup: { Ladder ladder = Ladder.Instance; if ( ladder != null ) { LadderEntry entry = ladder.Find( from ); if ( entry != null && Ladder.GetLevel( entry.Experience ) < tourny.LevelRequirement ) { if ( m_Registrar != null ) { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, "You have not yet proven yourself a worthy dueler.", from.NetState ); } break; } } if ( tourny.IsFactionRestricted && Faction.Find( from ) == null ) { if ( m_Registrar != null ) { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, "Only those who have declared their faction allegiance may participate.", from.NetState ); } break; } if ( from.HasGump( typeof( AcceptTeamGump ) ) ) { if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "You must first respond to the offer I've given you.", from.NetState ); } else if ( from.HasGump( typeof( AcceptDuelGump ) ) ) { if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "You must first cancel your duel offer.", from.NetState ); } else if ( from is PlayerMobile && ((PlayerMobile)from).DuelContext != null ) { if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "You are already participating in a duel.", from.NetState ); } else if ( !tourny.HasParticipant( from ) ) { ArrayList players = new ArrayList(); players.Add(from); from.CloseGump( typeof( ConfirmSignupGump ) ); from.SendGump( new ConfirmSignupGump( from, m_Registrar, tourny, players ) ); } else if ( m_Registrar != null ) { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, "You have already entered this tournament.", from.NetState ); } break; } } } } } public TournamentSignupItem( Serial serial ) : base( serial ) { } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int) 0 ); writer.Write( (Item) m_Tournament ); writer.Write( (Mobile) m_Registrar ); } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); switch ( version ) { case 0: { m_Tournament = reader.ReadItem() as TournamentController; m_Registrar = reader.ReadMobile(); break; } } } } public class ConfirmSignupGump : Gump { private Mobile m_From; private Tournament m_Tournament; private ArrayList m_Players; private Mobile m_Registrar; private const int BlackColor32 = 0x000008; private const int LabelColor32 = 0xFFFFFF; public string Center( string text ) { return String.Format( "
{0}
", text ); } public string Color( string text, int color ) { return String.Format( "{1}", color, text ); } private void AddBorderedText( int x, int y, int width, int height, string text, int color, int borderColor ) { AddColoredText( x - 1, y - 1, width, height, text, borderColor ); AddColoredText( x - 1, y + 1, width, height, text, borderColor ); AddColoredText( x + 1, y - 1, width, height, text, borderColor ); AddColoredText( x + 1, y + 1, width, height, text, borderColor ); AddColoredText( x, y, width, height, text, color ); } private void AddColoredText( int x, int y, int width, int height, string text, int color ) { if ( color == 0 ) AddHtml( x, y, width, height, text, false, false ); else AddHtml( x, y, width, height, Color( text, color ), false, false ); } public void AddGoldenButton( int x, int y, int bid ) { AddButton( x , y , 0xD2, 0xD2, bid, GumpButtonType.Reply, 0 ); AddButton( x+3, y+3, 0xD8, 0xD8, bid, GumpButtonType.Reply, 0 ); } public ConfirmSignupGump( Mobile from, Mobile registrar, Tournament tourny, ArrayList players ) : base( 50, 50 ) { m_From = from; m_Registrar = registrar; m_Tournament = tourny; m_Players = players; m_From.CloseGump( typeof( AcceptTeamGump ) ); m_From.CloseGump( typeof( AcceptDuelGump ) ); m_From.CloseGump( typeof( DuelContextGump ) ); m_From.CloseGump( typeof( ConfirmSignupGump ) ); #region Rules Ruleset ruleset = tourny.Ruleset; Ruleset basedef = ruleset.Base; int height = 185 + 60 + 12; int changes = 0; BitArray defs; if ( ruleset.Flavors.Count > 0 ) { defs = new BitArray( basedef.Options ); for ( int i = 0; i < ruleset.Flavors.Count; ++i ) defs.Or( ((Ruleset)ruleset.Flavors[i]).Options ); height += ruleset.Flavors.Count * 18; } else { defs = basedef.Options; } BitArray opts = ruleset.Options; for ( int i = 0; i < opts.Length; ++i ) { if ( defs[i] != opts[i] ) ++changes; } height += (changes * 22); height += 10 + 22 + 25 + 25; if ( tourny.PlayersPerParticipant > 1 ) height += 36 + (tourny.PlayersPerParticipant * 20); #endregion Closable = false; AddPage( 0 ); //AddBackground( 0, 0, 400, 220, 9150 ); AddBackground( 1, 1, 398, height, 3600 ); //AddBackground( 16, 15, 369, 189, 9100 ); AddImageTiled( 16, 15, 369, height - 29, 3604 ); AddAlphaRegion( 16, 15, 369, height - 29 ); AddImage( 215, -43, 0xEE40 ); //AddImage( 330, 141, 0x8BA ); StringBuilder sb = new StringBuilder(); if ( tourny.TournyType == TournyType.FreeForAll ) { sb.Append( "FFA" ); } else if ( tourny.TournyType == TournyType.RandomTeam ) { sb.Append( tourny.ParticipantsPerMatch ); sb.Append( "-Team" ); } else if ( tourny.TournyType == TournyType.Faction ) { sb.Append( tourny.ParticipantsPerMatch ); sb.Append( "-Team Faction" ); } else if ( tourny.TournyType == TournyType.RedVsBlue ) { sb.Append( "Red v Blue" ); } else { for ( int i = 0; i < tourny.ParticipantsPerMatch; ++i ) { if ( sb.Length > 0 ) sb.Append( 'v' ); sb.Append( tourny.PlayersPerParticipant ); } } if ( tourny.EventController != null ) sb.Append( ' ' ).Append( tourny.EventController.Title ); sb.Append( " Tournament Signup" ); AddBorderedText( 22, 22, 294, 20, Center( sb.ToString() ), LabelColor32, BlackColor32 ); AddBorderedText( 22, 50, 294, 40, "You have requested to join the tournament. Do you accept the rules?", 0xB0C868, BlackColor32 ); AddImageTiled( 32, 88, 264, 1, 9107 ); AddImageTiled( 42, 90, 264, 1, 9157 ); #region Rules int y = 100; string groupText = null; switch ( tourny.GroupType ) { case GroupingType.HighVsLow: groupText = "High vs Low"; break; case GroupingType.Nearest: groupText = "Closest opponent"; break; case GroupingType.Random: groupText = "Random"; break; } AddBorderedText( 35, y, 190, 20, String.Format( "Grouping: {0}", groupText ), LabelColor32, BlackColor32 ); y += 20; string tieText = null; switch ( tourny.TieType ) { case TieType.Random: tieText = "Random"; break; case TieType.Highest: tieText = "Highest advances"; break; case TieType.Lowest: tieText = "Lowest advances"; break; case TieType.FullAdvancement: tieText = ( tourny.ParticipantsPerMatch == 2 ? "Both advance" : "Everyone advances" ); break; case TieType.FullElimination: tieText = ( tourny.ParticipantsPerMatch == 2 ? "Both eliminated" : "Everyone eliminated" ); break; } AddBorderedText( 35, y, 190, 20, String.Format( "Tiebreaker: {0}", tieText ), LabelColor32, BlackColor32 ); y += 20; string sdText = "Off"; if ( tourny.SuddenDeath > TimeSpan.Zero ) { sdText = String.Format( "{0}:{1:D2}", (int) tourny.SuddenDeath.TotalMinutes, tourny.SuddenDeath.Seconds ); if ( tourny.SuddenDeathRounds > 0 ) sdText = String.Format( "{0} (first {1} rounds)", sdText, tourny.SuddenDeathRounds ); else sdText = String.Format( "{0} (all rounds)", sdText ); } AddBorderedText( 35, y, 240, 20, String.Format( "Sudden Death: {0}", sdText ), LabelColor32, BlackColor32 ); y += 20; y += 6; AddImageTiled( 32, y-1, 264, 1, 9107 ); AddImageTiled( 42, y+1, 264, 1, 9157 ); y += 6; AddBorderedText( 35, y, 190, 20, String.Format( "Ruleset: {0}", basedef.Title ), LabelColor32, BlackColor32 ); y += 20; for ( int i = 0; i < ruleset.Flavors.Count; ++i, y += 18 ) AddBorderedText( 35, y, 190, 20, String.Format( " + {0}", ((Ruleset)ruleset.Flavors[i]).Title ), LabelColor32, BlackColor32 ); y += 4; if ( changes > 0 ) { AddBorderedText( 35, y, 190, 20, "Modifications:", LabelColor32, BlackColor32 ); y += 20; for ( int i = 0; i < opts.Length; ++i ) { if ( defs[i] != opts[i] ) { string name = ruleset.Layout.FindByIndex( i ); if ( name != null ) // sanity { AddImage( 35, y, opts[i] ? 0xD3 : 0xD2 ); AddBorderedText( 60, y, 165, 22, name, LabelColor32, BlackColor32 ); } y += 22; } } } else { AddBorderedText( 35, y, 190, 20, "Modifications: None", LabelColor32, BlackColor32 ); y += 20; } #endregion #region Team if ( tourny.PlayersPerParticipant > 1 ) { y += 8; AddImageTiled( 32, y-1, 264, 1, 9107 ); AddImageTiled( 42, y+1, 264, 1, 9157 ); y += 8; AddBorderedText( 35, y, 190, 20, "Your Team", LabelColor32, BlackColor32 ); y += 20; for ( int i = 0; i < players.Count; ++i, y += 20 ) { if ( i == 0 ) AddImage( 35, y, 0xD2 ); else AddGoldenButton( 35, y, 1 + i ); AddBorderedText( 60, y, 200, 20, ((Mobile)players[i]).Name, LabelColor32, BlackColor32 ); } for ( int i = players.Count; i < tourny.PlayersPerParticipant; ++i, y += 20 ) { if ( i == 0 ) AddImage( 35, y, 0xD2 ); else AddGoldenButton( 35, y, 1 + i ); AddBorderedText( 60, y, 200, 20, "(Empty)", LabelColor32, BlackColor32 ); } } #endregion y += 8; AddImageTiled( 32, y-1, 264, 1, 9107 ); AddImageTiled( 42, y+1, 264, 1, 9157 ); y += 8; AddRadio( 24, y, 9727, 9730, true, 1 ); AddBorderedText( 60, y+5, 250, 20, "Yes, I wish to join the tournament.", LabelColor32, BlackColor32 ); y += 35; AddRadio( 24, y, 9727, 9730, false, 2 ); AddBorderedText( 60, y+5, 250, 20, "No, I do not wish to join.", LabelColor32, BlackColor32 ); y += 35; y -= 3; AddButton( 314, y, 247, 248, 1, GumpButtonType.Reply, 0 ); } public override void OnResponse( NetState sender, RelayInfo info ) { if ( info.ButtonID == 1 && info.IsSwitched( 1 ) ) { Tournament tourny = m_Tournament; Mobile from = m_From; switch ( tourny.Stage ) { case TournamentStage.Fighting: { if ( m_Registrar != null ) { if ( m_Tournament.HasParticipant( from ) ) { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, "Excuse me? You are already signed up.", from.NetState ); } else { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "The tournament has already begun. You are too late to signup now.", from.NetState ); } } break; } case TournamentStage.Inactive: { if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, "The tournament is closed.", from.NetState ); break; } case TournamentStage.Signup: { if ( m_Players.Count != tourny.PlayersPerParticipant ) { if ( m_Registrar != null ) { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, "You have not yet chosen your team.", from.NetState ); } m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); break; } Ladder ladder = Ladder.Instance; for ( int i = 0; i < m_Players.Count; ++i ) { Mobile mob = (Mobile)m_Players[i]; LadderEntry entry = ( ladder == null ? null : ladder.Find( mob ) ); if ( entry != null && Ladder.GetLevel( entry.Experience ) < tourny.LevelRequirement ) { if ( m_Registrar != null ) { if ( mob == from ) { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, "You have not yet proven yourself a worthy dueler.", from.NetState ); } else { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, String.Format( "{0} has not yet proven themselves a worthy dueler.", mob.Name ), from.NetState ); } } m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); return; } else if ( tourny.IsFactionRestricted && Faction.Find( mob ) == null ) { if ( m_Registrar != null ) { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, "Only those who have declared their faction allegiance may participate.", from.NetState ); } m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); return; } else if ( tourny.HasParticipant( mob ) ) { if ( m_Registrar != null ) { if ( mob == from ) { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, "You have already entered this tournament.", from.NetState ); } else { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, String.Format( "{0} has already entered this tournament.", mob.Name ), from.NetState ); } } m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); return; } else if ( mob is PlayerMobile && ((PlayerMobile)mob).DuelContext != null ) { if ( m_Registrar != null ) { if ( mob == from ) { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, "You are already assigned to a duel. You must yield it before joining this tournament.", from.NetState ); } else { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, String.Format( "{0} is already assigned to a duel. They must yield it before joining this tournament.", mob.Name ), from.NetState ); } } m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); return; } } if ( m_Registrar != null ) { string fmt; if ( tourny.PlayersPerParticipant == 1 ) fmt = "As you say m'{0}. I've written your name to the bracket. The tournament will begin {1}."; else if ( tourny.PlayersPerParticipant == 2 ) fmt = "As you wish m'{0}. The tournament will begin {1}, but first you must name your partner."; else fmt = "As you wish m'{0}. The tournament will begin {1}, but first you must name your team."; string timeUntil; int minutesUntil = (int)Math.Round( ( (tourny.SignupStart + tourny.SignupPeriod) - DateTime.UtcNow ).TotalMinutes ); if ( minutesUntil == 0 ) timeUntil = "momentarily"; else timeUntil = String.Format( "in {0} minute{1}", minutesUntil, minutesUntil == 1 ? "" : "s" ); m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x35, false, String.Format( fmt, from.Female ? "Lady" : "Lord", timeUntil ), from.NetState ); } TournyParticipant part = new TournyParticipant( from ); part.Players.Clear(); part.Players.AddRange( m_Players ); tourny.Participants.Add( part ); break; } } } else if ( info.ButtonID > 1 ) { int index = info.ButtonID-1; if ( index > 0 && index < m_Players.Count ) { m_Players.RemoveAt( index ); m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); } else if ( m_Players.Count < m_Tournament.PlayersPerParticipant ) { m_From.BeginTarget( 12, false, TargetFlags.None, new TargetCallback( AddPlayer_OnTarget ) ); m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); } } } private void AddPlayer_OnTarget( Mobile from, object obj ) { Mobile mob = obj as Mobile; if ( mob == null || mob == from ) { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "Excuse me?", from.NetState ); } else if ( !mob.Player ) { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( mob.Body.IsHuman ) mob.SayTo( from, 1005443 ); // Nay, I would rather stay here and watch a nail rust. else mob.SayTo( from, 1005444 ); // The creature ignores your offer. } else if ( AcceptDuelGump.IsIgnored( mob, from ) || mob.Blessed ) { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "They ignore your invitation.", from.NetState ); } else { PlayerMobile pm = mob as PlayerMobile; if ( pm == null ) return; if ( pm.DuelContext != null ) { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "They are already assigned to another duel.", from.NetState ); } else if ( mob.HasGump( typeof( AcceptTeamGump ) ) ) { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "They have already been offered a partnership.", from.NetState ); } else if ( mob.HasGump( typeof( ConfirmSignupGump ) ) ) { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "They are already trying to join this tournament.", from.NetState ); } else if ( m_Players.Contains( mob ) ) { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "You have already named them as a team member.", from.NetState ); } else if ( m_Tournament.HasParticipant( mob ) ) { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "They have already entered this tournament.", from.NetState ); } else if ( m_Players.Count >= m_Tournament.PlayersPerParticipant ) { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "Your team is full.", from.NetState ); } else { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); mob.SendGump( new AcceptTeamGump( from, mob, m_Tournament, m_Registrar, m_Players ) ); if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x59, false, String.Format( "As you command m'{0}. I've given your offer to {1}.", from.Female ? "Lady" : "Lord", mob.Name ), from.NetState ); } } } } public class AcceptTeamGump : Gump { private bool m_Active; private Mobile m_From; private Mobile m_Requested; private Tournament m_Tournament; private Mobile m_Registrar; private ArrayList m_Players; private const int BlackColor32 = 0x000008; private const int LabelColor32 = 0xFFFFFF; public string Center( string text ) { return String.Format( "
{0}
", text ); } public string Color( string text, int color ) { return String.Format( "{1}", color, text ); } private void AddBorderedText( int x, int y, int width, int height, string text, int color, int borderColor ) { AddColoredText( x - 1, y - 1, width, height, text, borderColor ); AddColoredText( x - 1, y + 1, width, height, text, borderColor ); AddColoredText( x + 1, y - 1, width, height, text, borderColor ); AddColoredText( x + 1, y + 1, width, height, text, borderColor ); AddColoredText( x, y, width, height, text, color ); } private void AddColoredText( int x, int y, int width, int height, string text, int color ) { if ( color == 0 ) AddHtml( x, y, width, height, text, false, false ); else AddHtml( x, y, width, height, Color( text, color ), false, false ); } public AcceptTeamGump( Mobile from, Mobile requested, Tournament tourny, Mobile registrar, ArrayList players ) : base( 50, 50 ) { m_From = from; m_Requested = requested; m_Tournament = tourny; m_Registrar = registrar; m_Players = players; m_Active = true; #region Rules Ruleset ruleset = tourny.Ruleset; Ruleset basedef = ruleset.Base; int height = 185 + 35 + 60 + 12; int changes = 0; BitArray defs; if ( ruleset.Flavors.Count > 0 ) { defs = new BitArray( basedef.Options ); for ( int i = 0; i < ruleset.Flavors.Count; ++i ) defs.Or( ((Ruleset)ruleset.Flavors[i]).Options ); height += ruleset.Flavors.Count * 18; } else { defs = basedef.Options; } BitArray opts = ruleset.Options; for ( int i = 0; i < opts.Length; ++i ) { if ( defs[i] != opts[i] ) ++changes; } height += (changes * 22); height += 10 + 22 + 25 + 25; #endregion Closable = false; AddPage( 0 ); AddBackground( 1, 1, 398, height, 3600 ); AddImageTiled( 16, 15, 369, height - 29, 3604 ); AddAlphaRegion( 16, 15, 369, height - 29 ); AddImage( 215, -43, 0xEE40 ); StringBuilder sb = new StringBuilder(); if ( tourny.TournyType == TournyType.FreeForAll ) { sb.Append( "FFA" ); } else if ( tourny.TournyType == TournyType.RandomTeam ) { sb.Append( tourny.ParticipantsPerMatch ); sb.Append( "-Team" ); } else if ( tourny.TournyType == TournyType.Faction ) { sb.Append( tourny.ParticipantsPerMatch ); sb.Append( "-Team Faction" ); } else if ( tourny.TournyType == TournyType.RedVsBlue ) { sb.Append( "Red v Blue" ); } else { for ( int i = 0; i < tourny.ParticipantsPerMatch; ++i ) { if ( sb.Length > 0 ) sb.Append( 'v' ); sb.Append( tourny.PlayersPerParticipant ); } } if ( tourny.EventController != null ) sb.Append( ' ' ).Append( tourny.EventController.Title ); sb.Append( " Tournament Invitation" ); AddBorderedText( 22, 22, 294, 20, Center( sb.ToString() ), LabelColor32, BlackColor32 ); AddBorderedText( 22, 50, 294, 40, String.Format( "You have been asked to partner with {0} in a tournament. Do you accept?", from.Name ), 0xB0C868, BlackColor32 ); AddImageTiled( 32, 88, 264, 1, 9107 ); AddImageTiled( 42, 90, 264, 1, 9157 ); #region Rules int y = 100; string groupText = null; switch ( tourny.GroupType ) { case GroupingType.HighVsLow: groupText = "High vs Low"; break; case GroupingType.Nearest: groupText = "Closest opponent"; break; case GroupingType.Random: groupText = "Random"; break; } AddBorderedText( 35, y, 190, 20, String.Format( "Grouping: {0}", groupText ), LabelColor32, BlackColor32 ); y += 20; string tieText = null; switch ( tourny.TieType ) { case TieType.Random: tieText = "Random"; break; case TieType.Highest: tieText = "Highest advances"; break; case TieType.Lowest: tieText = "Lowest advances"; break; case TieType.FullAdvancement: tieText = ( tourny.ParticipantsPerMatch == 2 ? "Both advance" : "Everyone advances" ); break; case TieType.FullElimination: tieText = ( tourny.ParticipantsPerMatch == 2 ? "Both eliminated" : "Everyone eliminated" ); break; } AddBorderedText( 35, y, 190, 20, String.Format( "Tiebreaker: {0}", tieText ), LabelColor32, BlackColor32 ); y += 20; string sdText = "Off"; if ( tourny.SuddenDeath > TimeSpan.Zero ) { sdText = String.Format( "{0}:{1:D2}", (int) tourny.SuddenDeath.TotalMinutes, tourny.SuddenDeath.Seconds ); if ( tourny.SuddenDeathRounds > 0 ) sdText = String.Format( "{0} (first {1} rounds)", sdText, tourny.SuddenDeathRounds ); else sdText = String.Format( "{0} (all rounds)", sdText ); } AddBorderedText( 35, y, 240, 20, String.Format( "Sudden Death: {0}", sdText ), LabelColor32, BlackColor32 ); y += 20; y += 6; AddImageTiled( 32, y-1, 264, 1, 9107 ); AddImageTiled( 42, y+1, 264, 1, 9157 ); y += 6; AddBorderedText( 35, y, 190, 20, String.Format( "Ruleset: {0}", basedef.Title ), LabelColor32, BlackColor32 ); y += 20; for ( int i = 0; i < ruleset.Flavors.Count; ++i, y += 18 ) AddBorderedText( 35, y, 190, 20, String.Format( " + {0}", ((Ruleset)ruleset.Flavors[i]).Title ), LabelColor32, BlackColor32 ); y += 4; if ( changes > 0 ) { AddBorderedText( 35, y, 190, 20, "Modifications:", LabelColor32, BlackColor32 ); y += 20; for ( int i = 0; i < opts.Length; ++i ) { if ( defs[i] != opts[i] ) { string name = ruleset.Layout.FindByIndex( i ); if ( name != null ) // sanity { AddImage( 35, y, opts[i] ? 0xD3 : 0xD2 ); AddBorderedText( 60, y, 165, 22, name, LabelColor32, BlackColor32 ); } y += 22; } } } else { AddBorderedText( 35, y, 190, 20, "Modifications: None", LabelColor32, BlackColor32 ); y += 20; } #endregion y += 8; AddImageTiled( 32, y-1, 264, 1, 9107 ); AddImageTiled( 42, y+1, 264, 1, 9157 ); y += 8; AddRadio( 24, y, 9727, 9730, true, 1 ); AddBorderedText( 60, y+5, 250, 20, "Yes, I will join them.", LabelColor32, BlackColor32 ); y += 35; AddRadio( 24, y, 9727, 9730, false, 2 ); AddBorderedText( 60, y+5, 250, 20, "No, I do not wish to fight.", LabelColor32, BlackColor32 ); y += 35; AddRadio( 24, y, 9727, 9730, false, 3 ); AddBorderedText( 60, y+5, 270, 20, "No, most certainly not. Do not ask again.", LabelColor32, BlackColor32 ); y += 35; y -= 3; AddButton( 314, y, 247, 248, 1, GumpButtonType.Reply, 0 ); Timer.DelayCall( TimeSpan.FromSeconds( 15.0 ), new TimerCallback( AutoReject ) ); } public void AutoReject() { if ( !m_Active ) return; m_Active = false; m_Requested.CloseGump( typeof( AcceptTeamGump ) ); m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, String.Format( "{0} seems unresponsive.", m_Requested.Name ), m_From.NetState ); m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, String.Format( "You have declined the partnership with {0}.", m_From.Name ), m_Requested.NetState ); } } public override void OnResponse( NetState sender, RelayInfo info ) { Mobile from = m_From; Mobile mob = m_Requested; if ( info.ButtonID != 1 || !m_Active ) return; m_Active = false; if ( info.IsSwitched( 1 ) ) { PlayerMobile pm = mob as PlayerMobile; if ( pm == null ) return; if ( AcceptDuelGump.IsIgnored( mob, from ) || mob.Blessed ) { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "They ignore your invitation.", from.NetState ); } else if ( pm.DuelContext != null ) { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "They are already assigned to another duel.", from.NetState ); } else if ( m_Players.Contains( mob ) ) { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "You have already named them as a team member.", from.NetState ); } else if ( m_Tournament.HasParticipant( mob ) ) { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "They have already entered this tournament.", from.NetState ); } else if ( m_Players.Count >= m_Tournament.PlayersPerParticipant ) { m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, "Your team is full.", from.NetState ); } else { m_Players.Add( mob ); m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x59, false, String.Format( "{0} has accepted your offer of partnership.", mob.Name ), from.NetState ); m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x59, false, String.Format( "You have accepted the partnership with {0}.", from.Name ), mob.NetState ); } } } else { if ( info.IsSwitched( 3 ) ) AcceptDuelGump.BeginIgnore( m_Requested, m_From ); m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) ); if ( m_Registrar != null ) { m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, String.Format( "{0} has declined your offer of partnership.", mob.Name ), from.NetState ); m_Registrar.PrivateOverheadMessage( MessageType.Regular, 0x22, false, String.Format( "You have declined the partnership with {0}.", from.Name ), mob.NetState ); } } } } public class TournamentController : Item { private Tournament m_Tournament; [CommandProperty( AccessLevel.GameMaster )] public Tournament Tournament{ get{ return m_Tournament; } set{} } private static ArrayList m_Instances = new ArrayList(); public static bool IsActive { get { for ( int i = 0; i < m_Instances.Count; ++i ) { TournamentController controller = (TournamentController)m_Instances[i]; if ( controller != null && !controller.Deleted && controller.Tournament != null && controller.Tournament.Stage!=TournamentStage.Inactive ) return true; } return false; } } public override string DefaultName { get { return "tournament controller"; } } [Constructable] public TournamentController() : base( 0x1B7A ) { Visible = false; Movable = false; m_Tournament = new Tournament(); m_Instances.Add( this ); } public override void GetContextMenuEntries( Mobile from, List list ) { base.GetContextMenuEntries( from, list ); if ( from.AccessLevel >= AccessLevel.GameMaster && m_Tournament != null ) { list.Add( new EditEntry( m_Tournament ) ); if ( m_Tournament.CurrentStage == TournamentStage.Inactive ) list.Add( new StartEntry( m_Tournament ) ); } } private class EditEntry : ContextMenuEntry { private Tournament m_Tournament; public EditEntry( Tournament tourny ) : base( 5101 ) { m_Tournament = tourny; } public override void OnClick() { Owner.From.SendGump( new PropertiesGump( Owner.From, m_Tournament ) ); } } private class StartEntry : ContextMenuEntry { private Tournament m_Tournament; public StartEntry( Tournament tourny ) : base( 5113 ) { m_Tournament = tourny; } public override void OnClick() { if ( m_Tournament.Stage == TournamentStage.Inactive ) { m_Tournament.SignupStart = DateTime.UtcNow; m_Tournament.Stage = TournamentStage.Signup; m_Tournament.Participants.Clear(); m_Tournament.Pyramid.Levels.Clear(); m_Tournament.Alert( "Hear ye! Hear ye!", "Tournament signup has opened. You can enter by signing up with the registrar." ); } } } public override void OnDoubleClick( Mobile from ) { if ( from.AccessLevel >= AccessLevel.GameMaster && m_Tournament != null ) { from.CloseGump( typeof( PickRulesetGump ) ); from.CloseGump( typeof( RulesetGump ) ); from.SendGump( new PickRulesetGump( from, null, m_Tournament.Ruleset ) ); } } public TournamentController( Serial serial ) : base( serial ) { } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int) 0 ); m_Tournament.Serialize( writer ); } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); switch ( version ) { case 0: { m_Tournament = new Tournament( reader ); break; } } m_Instances.Add( this ); } public override void OnDelete() { base.OnDelete(); m_Instances.Remove( this ); } } public enum TournyType { Standard, FreeForAll, RandomTeam, RedVsBlue, Faction } [PropertyObject] public class Tournament { private int m_ParticipantsPerMatch; private int m_PlayersPerParticipant; private int m_LevelRequirement; private bool m_FactionRestricted; private TournyPyramid m_Pyramid; private Ruleset m_Ruleset; private ArrayList m_Arenas; private ArrayList m_Participants; private ArrayList m_Undefeated; private TimeSpan m_SignupPeriod; private DateTime m_SignupStart; private TournamentStage m_Stage; private GroupingType m_GroupType; private TieType m_TieType; private TimeSpan m_SuddenDeath; private TournyType m_TournyType; private int m_SuddenDeathRounds; private EventController m_EventController; public bool IsNotoRestricted { get { return ( m_TournyType != TournyType.Standard ); } } [CommandProperty( AccessLevel.GameMaster )] public EventController EventController { get { return m_EventController; } set { m_EventController = value; } } [CommandProperty( AccessLevel.GameMaster )] public int SuddenDeathRounds { get{ return m_SuddenDeathRounds; } set{ m_SuddenDeathRounds = value; } } [CommandProperty( AccessLevel.GameMaster )] public TournyType TournyType { get{ return m_TournyType; } set{ m_TournyType = value; } } [CommandProperty( AccessLevel.GameMaster )] public GroupingType GroupType { get{ return m_GroupType; } set{ m_GroupType = value; } } [CommandProperty( AccessLevel.GameMaster )] public TieType TieType { get{ return m_TieType; } set{ m_TieType = value; } } [CommandProperty( AccessLevel.GameMaster )] public TimeSpan SuddenDeath { get{ return m_SuddenDeath; } set{ m_SuddenDeath = value; } } public Ruleset Ruleset { get{ return m_Ruleset; } set{ m_Ruleset = value; } } [CommandProperty( AccessLevel.GameMaster )] public int ParticipantsPerMatch { get{ return m_ParticipantsPerMatch; } set{ if ( value < 2 ) value = 2; else if ( value > 10 ) value = 10; m_ParticipantsPerMatch = value; } } [CommandProperty( AccessLevel.GameMaster )] public int PlayersPerParticipant { get{ return m_PlayersPerParticipant; } set{ if ( value < 1 ) value = 1; else if ( value > 10 ) value = 10; m_PlayersPerParticipant = value; } } [CommandProperty( AccessLevel.GameMaster )] public int LevelRequirement { get{ return m_LevelRequirement; } set{ m_LevelRequirement = value; } } [CommandProperty( AccessLevel.GameMaster )] public bool FactionRestricted { get{ return m_FactionRestricted; } set{ m_FactionRestricted = value; } } [CommandProperty( AccessLevel.GameMaster )] public TimeSpan SignupPeriod { get{ return m_SignupPeriod; } set{ m_SignupPeriod = value; } } [CommandProperty( AccessLevel.GameMaster )] public DateTime SignupStart { get{ return m_SignupStart; } set{ m_SignupStart = value; } } [CommandProperty( AccessLevel.GameMaster )] public TournamentStage CurrentStage { get{ return m_Stage; } } public TournamentStage Stage { get{ return m_Stage; } set{ m_Stage = value; } } public TournyPyramid Pyramid { get{ return m_Pyramid; } set{ m_Pyramid = value; } } public ArrayList Arenas { get{ return m_Arenas; } set{ m_Arenas = value; } } public ArrayList Participants { get{ return m_Participants; } set{ m_Participants = value; } } public ArrayList Undefeated { get{ return m_Undefeated; } set{ m_Undefeated = value; } } public bool IsFactionRestricted { get { return ( m_FactionRestricted || m_TournyType == TournyType.Faction ); } } public bool HasParticipant( Mobile mob ) { for ( int i = 0; i < m_Participants.Count; ++i ) { TournyParticipant part = (TournyParticipant)m_Participants[i]; if ( part.Players.Contains( mob ) ) return true; } return false; } public void Serialize( GenericWriter writer ) { writer.WriteEncodedInt( (int) 5 ); // version writer.Write( (bool) m_FactionRestricted ); writer.Write( (Item) m_EventController ); writer.WriteEncodedInt( (int) m_SuddenDeathRounds ); writer.WriteEncodedInt( (int) m_TournyType ); writer.WriteEncodedInt( (int) m_GroupType ); writer.WriteEncodedInt( (int) m_TieType ); writer.Write( (TimeSpan) m_SuddenDeath ); writer.WriteEncodedInt( (int) m_ParticipantsPerMatch ); writer.WriteEncodedInt( (int) m_PlayersPerParticipant ); writer.Write( (TimeSpan) m_SignupPeriod ); } public Tournament( GenericReader reader ) { int version = reader.ReadEncodedInt(); switch ( version ) { case 5: { m_FactionRestricted = reader.ReadBool(); goto case 4; } case 4: { m_EventController = reader.ReadItem() as EventController; goto case 3; } case 3: { m_SuddenDeathRounds = reader.ReadEncodedInt(); goto case 2; } case 2: { m_TournyType = (TournyType)reader.ReadEncodedInt(); goto case 1; } case 1: { m_GroupType = (GroupingType)reader.ReadEncodedInt(); m_TieType = (TieType)reader.ReadEncodedInt(); m_SignupPeriod = reader.ReadTimeSpan(); goto case 0; } case 0: { if ( version < 3 ) m_SuddenDeathRounds = 3; m_ParticipantsPerMatch = reader.ReadEncodedInt(); m_PlayersPerParticipant = reader.ReadEncodedInt(); m_SignupPeriod = reader.ReadTimeSpan(); m_Stage = TournamentStage.Inactive; m_Pyramid = new TournyPyramid(); m_Ruleset = new Ruleset( RulesetLayout.Root ); m_Ruleset.ApplyDefault( m_Ruleset.Layout.Defaults[0] ); m_Participants = new ArrayList(); m_Undefeated = new ArrayList(); m_Arenas = new ArrayList(); break; } } Timer.DelayCall( SliceInterval, SliceInterval, new TimerCallback( Slice ) ); } public Tournament() { m_ParticipantsPerMatch = 2; m_PlayersPerParticipant = 1; m_Pyramid = new TournyPyramid(); m_Ruleset = new Ruleset( RulesetLayout.Root ); m_Ruleset.ApplyDefault( m_Ruleset.Layout.Defaults[0] ); m_Participants = new ArrayList(); m_Undefeated = new ArrayList(); m_Arenas = new ArrayList(); m_SignupPeriod = TimeSpan.FromMinutes( 10.0 ); Timer.DelayCall( SliceInterval, SliceInterval, new TimerCallback( Slice ) ); } public void HandleTie( Arena arena, TournyMatch match, ArrayList remaining ) { if ( remaining.Count == 1 ) HandleWon( arena, match, (TournyParticipant)remaining[0] ); if ( remaining.Count < 2 ) return; StringBuilder sb = new StringBuilder(); sb.Append( "The match has ended in a tie " ); if ( remaining.Count == 2 ) sb.Append( "between " ); else sb.Append( "among " ); sb.Append( remaining.Count ); if ( ((TournyParticipant)remaining[0]).Players.Count == 1 ) sb.Append( " players: " ); else sb.Append( " teams: " ); bool hasAppended = false; for ( int j = 0; j < match.Participants.Count; ++j ) { TournyParticipant part = (TournyParticipant)match.Participants[j]; if ( remaining.Contains( part ) ) { if ( hasAppended ) sb.Append( ", " ); sb.Append( part.NameList ); hasAppended = true; } else { m_Undefeated.Remove( part ); } } sb.Append( ". " ); string whole = ( remaining.Count == 2 ? "both" : "all" ); TieType tieType = m_TieType; if ( tieType == TieType.FullElimination && remaining.Count >= m_Undefeated.Count ) tieType = TieType.FullAdvancement; switch ( m_TieType ) { case TieType.FullAdvancement: { sb.AppendFormat( "In accordance with the rules, {0} parties are advanced.", whole ); break; } case TieType.FullElimination: { for ( int j = 0; j < remaining.Count; ++j ) m_Undefeated.Remove( remaining[j] ); sb.AppendFormat( "In accordance with the rules, {0} parties are eliminated.", whole ); break; } case TieType.Random: { TournyParticipant advanced = (TournyParticipant)remaining[Utility.Random( remaining.Count )]; for ( int i = 0; i < remaining.Count; ++i ) { if ( remaining[i] != advanced ) m_Undefeated.Remove( remaining[i] ); } if ( advanced != null ) sb.AppendFormat( "In accordance with the rules, {0} {1} advanced.", advanced.NameList, advanced.Players.Count == 1 ? "is" : "are" ); break; } case TieType.Highest: { TournyParticipant advanced = null; for ( int i = 0; i < remaining.Count; ++i ) { TournyParticipant part = (TournyParticipant)remaining[i]; if ( advanced == null || part.TotalLadderXP > advanced.TotalLadderXP ) advanced = part; } for ( int i = 0; i < remaining.Count; ++i ) { if ( remaining[i] != advanced ) m_Undefeated.Remove( remaining[i] ); } if ( advanced != null ) sb.AppendFormat( "In accordance with the rules, {0} {1} advanced.", advanced.NameList, advanced.Players.Count == 1 ? "is" : "are" ); break; } case TieType.Lowest: { TournyParticipant advanced = null; for ( int i = 0; i < remaining.Count; ++i ) { TournyParticipant part = (TournyParticipant)remaining[i]; if ( advanced == null || part.TotalLadderXP < advanced.TotalLadderXP ) advanced = part; } for ( int i = 0; i < remaining.Count; ++i ) { if ( remaining[i] != advanced ) m_Undefeated.Remove( remaining[i] ); } if ( advanced != null ) sb.AppendFormat( "In accordance with the rules, {0} {1} advanced.", advanced.NameList, advanced.Players.Count == 1 ? "is" : "are" ); break; } } Alert( arena, sb.ToString() ); } public void OnEliminated( DuelPlayer player ) { Participant part = player.Participant; if ( !part.Eliminated ) return; if ( m_TournyType == TournyType.FreeForAll ) { int rem = 0; for ( int i = 0; i < part.Context.Participants.Count; ++i ) { Participant check = (Participant)part.Context.Participants[i]; if ( check != null && !check.Eliminated ) ++rem; } TournyParticipant tp = part.TournyPart; if ( tp == null ) return; if ( rem == 1 ) GiveAwards( tp.Players, TrophyRank.Silver, ComputeCashAward() / 2 ); else if ( rem == 2 ) GiveAwards( tp.Players, TrophyRank.Bronze, ComputeCashAward() / 4 ); } } public void HandleWon( Arena arena, TournyMatch match, TournyParticipant winner ) { StringBuilder sb = new StringBuilder(); sb.Append( "The match is complete. " ); sb.Append( winner.NameList ); if ( winner.Players.Count > 1 ) sb.Append( " have bested " ); else sb.Append( " has bested " ); if ( match.Participants.Count > 2 ) sb.AppendFormat( "{0} other {1}: ", match.Participants.Count - 1, winner.Players.Count == 1 ? "players" : "teams" ); bool hasAppended = false; for ( int j = 0; j < match.Participants.Count; ++j ) { TournyParticipant part = (TournyParticipant)match.Participants[j]; if ( part == winner ) continue; m_Undefeated.Remove( part ); if ( hasAppended ) sb.Append( ", " ); sb.Append( part.NameList ); hasAppended = true; } sb.Append( "." ); if ( m_TournyType == TournyType.Standard ) Alert( arena, sb.ToString() ); } private static readonly TimeSpan SliceInterval = TimeSpan.FromSeconds( 12.0 ); private int ComputeCashAward() { return m_Participants.Count * m_PlayersPerParticipant * 2500; } private void GiveAwards() { switch ( m_TournyType ) { case TournyType.FreeForAll: { if ( m_Pyramid.Levels.Count < 1 ) break; PyramidLevel top = m_Pyramid.Levels[m_Pyramid.Levels.Count - 1] as PyramidLevel; if ( top.FreeAdvance != null || top.Matches.Count != 1 ) break; TournyMatch match = top.Matches[0] as TournyMatch; TournyParticipant winner = match.Winner; if ( winner != null ) GiveAwards( winner.Players, TrophyRank.Gold, ComputeCashAward() ); break; } case TournyType.Standard: { if ( m_Pyramid.Levels.Count < 2 ) break; PyramidLevel top = m_Pyramid.Levels[m_Pyramid.Levels.Count - 1] as PyramidLevel; if ( top.FreeAdvance != null || top.Matches.Count != 1 ) break; int cash = ComputeCashAward(); TournyMatch match = top.Matches[0] as TournyMatch; TournyParticipant winner = match.Winner; for ( int i = 0; i < match.Participants.Count; ++i ) { TournyParticipant part = (TournyParticipant) match.Participants[i]; if ( part == winner ) GiveAwards( part.Players, TrophyRank.Gold, cash ); else GiveAwards( part.Players, TrophyRank.Silver, cash / 2 ); } PyramidLevel next = m_Pyramid.Levels[m_Pyramid.Levels.Count - 2] as PyramidLevel; if ( next.Matches.Count > 2 ) break; for ( int i = 0; i < next.Matches.Count; ++i ) { match = (TournyMatch)next.Matches[i]; winner = match.Winner; for ( int j = 0; j < match.Participants.Count; ++j ) { TournyParticipant part = (TournyParticipant) match.Participants[j]; if ( part != winner ) GiveAwards( part.Players, TrophyRank.Bronze, cash / 4 ); } } break; } } } private void GiveAwards( ArrayList players, TrophyRank rank, int cash ) { if ( players.Count == 0 ) return; if ( players.Count > 1 ) cash /= ( players.Count - 1 ); cash += 500; cash /= 1000; cash *= 1000; StringBuilder sb = new StringBuilder(); if ( m_TournyType == TournyType.FreeForAll ) { sb.Append( m_Participants.Count * m_PlayersPerParticipant ); sb.Append( "-man FFA" ); } else if ( m_TournyType == TournyType.RandomTeam ) { sb.Append( m_ParticipantsPerMatch ); sb.Append( "-Team" ); } else if ( m_TournyType == TournyType.Faction ) { sb.Append( m_ParticipantsPerMatch ); sb.Append( "-Team Faction" ); } else if ( m_TournyType == TournyType.RedVsBlue ) { sb.Append( "Red v Blue" ); } else { for ( int i = 0; i < m_ParticipantsPerMatch; ++i ) { if ( sb.Length > 0 ) sb.Append( 'v' ); sb.Append( m_PlayersPerParticipant ); } } if ( m_EventController != null ) sb.Append( ' ' ).Append( m_EventController.Title ); sb.Append( " Champion" ); string title = sb.ToString(); for ( int i = 0; i < players.Count; ++i ) { Mobile mob = (Mobile) players[i]; if ( mob == null || mob.Deleted ) continue; Item item = new Trophy( title, rank ); if ( !mob.PlaceInBackpack( item ) ) mob.BankBox.DropItem( item ); if ( cash > 0 ) { item = new BankCheck( cash ); if ( !mob.PlaceInBackpack( item ) ) mob.BankBox.DropItem( item ); mob.SendMessage( "You have been awarded a {0} trophy and {1:N0}gp for your participation in this tournament.", rank.ToString().ToLower(), cash ); } else { mob.SendMessage( "You have been awarded a {0} trophy for your participation in this tournament.", rank.ToString().ToLower() ); } } } public void Slice() { if ( m_Stage == TournamentStage.Signup ) { TimeSpan until = ( m_SignupStart + m_SignupPeriod ) - DateTime.UtcNow; if ( until <= TimeSpan.Zero ) { for ( int i = m_Participants.Count - 1; i >= 0; --i ) { TournyParticipant part = (TournyParticipant)m_Participants[i]; bool bad = false; for ( int j = 0; j < part.Players.Count; ++j ) { Mobile check = (Mobile) part.Players[j]; if ( check.Deleted || check.Map == null || check.Map == Map.Internal || !check.Alive || Factions.Sigil.ExistsOn( check ) || check.Region.IsPartOf( typeof( Regions.Jail ) ) ) { bad = true; break; } } if ( bad ) { for ( int j = 0; j < part.Players.Count; ++j ) ((Mobile)part.Players[j]).SendMessage( "You have been disqualified from the tournament." ); m_Participants.RemoveAt( i ); } } if ( m_Participants.Count >= 2 ) { m_Stage = TournamentStage.Fighting; m_Undefeated.Clear(); m_Pyramid.Levels.Clear(); m_Pyramid.AddLevel( m_ParticipantsPerMatch, m_Participants, m_GroupType, m_TournyType ); PyramidLevel level = (PyramidLevel)m_Pyramid.Levels[0]; if ( level.FreeAdvance != null ) m_Undefeated.Add( level.FreeAdvance ); for ( int i = 0; i < level.Matches.Count; ++i ) { TournyMatch match = (TournyMatch)level.Matches[i]; m_Undefeated.AddRange( match.Participants ); } Alert( "Hear ye! Hear ye!", "The tournament will begin shortly." ); } else { /*Alert( "Is this all?", "Pitiful. Signup extended." ); m_SignupStart = DateTime.UtcNow;*/ Alert("Is this all?", "Pitiful. Tournament cancelled."); m_Stage = TournamentStage.Inactive; } } else if ( Math.Abs( until.TotalSeconds - TimeSpan.FromMinutes( 1.0 ).TotalSeconds ) < (SliceInterval.TotalSeconds/2) ) { Alert( "Last call!", "If you wish to enter the tournament, sign up with the registrar now." ); } else if ( Math.Abs( until.TotalSeconds - TimeSpan.FromMinutes( 5.0 ).TotalSeconds ) < (SliceInterval.TotalSeconds/2) ) { Alert( "The tournament will begin in 5 minutes.", "Sign up now before it's too late." ); } } else if ( m_Stage == TournamentStage.Fighting ) { if ( m_Undefeated.Count == 1 ) { TournyParticipant winner = (TournyParticipant)m_Undefeated[0]; try { if ( m_EventController != null ) Alert( "The tournament has completed!", String.Format( "Team {0} has won!", m_EventController.GetTeamName( ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf( winner ) ) ) ); else if ( m_TournyType == TournyType.RandomTeam ) Alert( "The tournament has completed!", String.Format( "Team {0} has won!", ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf( winner ) + 1 ) ); else if ( m_TournyType == TournyType.Faction ) { if ( m_ParticipantsPerMatch == 4 ) { string name = "(null)"; switch ( ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf( winner ) ) { case 0: { name = "Minax"; break; } case 1: { name = "Council of Mages"; break; } case 2: { name = "True Britannians"; break; } case 3: { name = "Shadowlords"; break; } } Alert( "The tournament has completed!", String.Format( "The {0} team has won!", name ) ); } else if ( m_ParticipantsPerMatch == 2 ) { Alert( "The tournament has completed!", String.Format( "The {0} team has won!", ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf( winner ) == 0 ? "Evil" : "Hero" ) ); } else { Alert( "The tournament has completed!", String.Format( "Team {0} has won!", ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf( winner ) + 1 ) ); } } else if ( m_TournyType == TournyType.RedVsBlue ) Alert( "The tournament has completed!", String.Format( "Team {0} has won!", ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf( winner ) == 0 ? "Red" : "Blue" ) ); else Alert( "The tournament has completed!", String.Format( "{0} {1} the champion{2}.", winner.NameList, winner.Players.Count > 1 ? "are" : "is", winner.Players.Count == 1 ? "" : "s" ) ); } catch { } GiveAwards(); m_Stage = TournamentStage.Inactive; m_Undefeated.Clear(); } else if ( m_Pyramid.Levels.Count > 0 ) { PyramidLevel activeLevel = (PyramidLevel)m_Pyramid.Levels[m_Pyramid.Levels.Count - 1]; bool stillGoing = false; for ( int i = 0; i < activeLevel.Matches.Count; ++i ) { TournyMatch match = (TournyMatch)activeLevel.Matches[i]; if ( match.Winner == null ) { stillGoing = true; if ( !match.InProgress ) { for ( int j = 0; j < m_Arenas.Count; ++j ) { Arena arena = (Arena)m_Arenas[j]; if ( !arena.IsOccupied ) { match.Start( arena, this ); break; } } } } } if ( !stillGoing ) { for ( int i = m_Undefeated.Count - 1; i >= 0; --i ) { TournyParticipant part = (TournyParticipant)m_Undefeated[i]; bool bad = false; for ( int j = 0; j < part.Players.Count; ++j ) { Mobile check = (Mobile) part.Players[j]; if ( check.Deleted || check.Map == null || check.Map == Map.Internal || !check.Alive || Factions.Sigil.ExistsOn( check ) || check.Region.IsPartOf( typeof( Regions.Jail ) ) ) { bad = true; break; } } if ( bad ) { for ( int j = 0; j < part.Players.Count; ++j ) ((Mobile)part.Players[j]).SendMessage( "You have been disqualified from the tournament." ); m_Undefeated.RemoveAt( i ); if ( m_Undefeated.Count == 1 ) { TournyParticipant winner = (TournyParticipant)m_Undefeated[0]; try { if ( m_EventController != null ) Alert( "The tournament has completed!", String.Format( "Team {0} has won", m_EventController.GetTeamName( ( (TournyMatch) ( (PyramidLevel) m_Pyramid.Levels[0] ).Matches[0] ).Participants.IndexOf( winner ) ) ) ); else if ( m_TournyType == TournyType.RandomTeam ) Alert( "The tournament has completed!", String.Format( "Team {0} has won!", ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf( winner ) + 1 ) ); else if ( m_TournyType == TournyType.Faction ) { if ( m_ParticipantsPerMatch == 4 ) { string name = "(null)"; switch ( ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf( winner ) ) { case 0: { name = "Minax"; break; } case 1: { name = "Council of Mages"; break; } case 2: { name = "True Britannians"; break; } case 3: { name = "Shadowlords"; break; } } Alert( "The tournament has completed!", String.Format( "The {0} team has won!", name ) ); } else if ( m_ParticipantsPerMatch == 2 ) { Alert( "The tournament has completed!", String.Format( "The {0} team has won!", ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf( winner ) == 0 ? "Evil" : "Hero" ) ); } else { Alert( "The tournament has completed!", String.Format( "Team {0} has won!", ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf( winner ) + 1 ) ); } } else if ( m_TournyType == TournyType.RedVsBlue ) Alert( "The tournament has completed!", String.Format( "Team {0} has won!", ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf( winner ) == 0 ? "Red" : "Blue" ) ); else Alert( "The tournament has completed!", String.Format( "{0} {1} the champion{2}.", winner.NameList, winner.Players.Count > 1 ? "are" : "is", winner.Players.Count == 1 ? "" : "s" ) ); } catch { } GiveAwards(); m_Stage = TournamentStage.Inactive; m_Undefeated.Clear(); break; } } } if ( m_Undefeated.Count > 1 ) m_Pyramid.AddLevel( m_ParticipantsPerMatch, m_Undefeated, m_GroupType, m_TournyType ); } } } } public void Alert( params string[] alerts ) { for ( int i = 0; i < m_Arenas.Count; ++i ) Alert( (Arena) m_Arenas[i], alerts ); } public void Alert( Arena arena, params string[] alerts ) { if ( arena != null && arena.Announcer != null ) { for ( int j = 0; j < alerts.Length; ++j ) Timer.DelayCall( TimeSpan.FromSeconds( Math.Max( j-0.5, 0.0 ) ), new TimerStateCallback( Alert_Callback ), new object[]{ arena.Announcer, alerts[j] } ); } } private void Alert_Callback( object state ) { object[] states = (object[])state; if ( states[0] != null ) ((Mobile)states[0]).PublicOverheadMessage( MessageType.Regular, 0x35, false, (string)states[1] ); } } public class TournyPyramid { private ArrayList m_Levels; public ArrayList Levels { get{ return m_Levels; } set{ m_Levels = value; } } public TournyPyramid() { m_Levels = new ArrayList(); } public void AddLevel( int partsPerMatch, ArrayList participants, GroupingType groupType, TournyType tournyType ) { ArrayList copy = new ArrayList( participants ); if ( groupType == GroupingType.Nearest || groupType == GroupingType.HighVsLow ) copy.Sort(); PyramidLevel level = new PyramidLevel(); switch ( tournyType ) { case TournyType.RedVsBlue: { TournyParticipant[] parts = new TournyParticipant[2]; for ( int i = 0; i < parts.Length; ++i ) parts[i] = new TournyParticipant( new ArrayList() ); for ( int i = 0; i < copy.Count; ++i ) { ArrayList players = ((TournyParticipant)copy[i]).Players; for ( int j = 0; j < players.Count; ++j ) { Mobile mob = (Mobile) players[j]; if ( mob.Kills >= 5 ) parts[0].Players.Add( mob ); else parts[1].Players.Add( mob ); } } level.Matches.Add( new TournyMatch( new ArrayList( parts ) ) ); break; } case TournyType.Faction: { TournyParticipant[] parts = new TournyParticipant[partsPerMatch]; for ( int i = 0; i < parts.Length; ++i ) parts[i] = new TournyParticipant( new ArrayList() ); for ( int i = 0; i < copy.Count; ++i ) { ArrayList players = ((TournyParticipant)copy[i]).Players; for ( int j = 0; j < players.Count; ++j ) { Mobile mob = (Mobile) players[j]; int index = -1; if ( partsPerMatch == 4 ) { Faction fac = Faction.Find( mob ); if ( fac != null ) { index = fac.Definition.Sort; } } else if ( partsPerMatch == 2 ) { if ( Ethic.Evil.IsEligible( mob ) ) { index = 0; } else if ( Ethic.Hero.IsEligible( mob ) ) { index = 1; } } if ( index < 0 || index >= partsPerMatch ) { index = i % partsPerMatch; } parts[index].Players.Add( mob ); } } level.Matches.Add( new TournyMatch( new ArrayList( parts ) ) ); break; } case TournyType.RandomTeam: { TournyParticipant[] parts = new TournyParticipant[partsPerMatch]; for ( int i = 0; i < partsPerMatch; ++i ) parts[i] = new TournyParticipant( new ArrayList() ); for ( int i = 0; i < copy.Count; ++i ) parts[i % parts.Length].Players.AddRange( ((TournyParticipant)copy[i]).Players ); level.Matches.Add( new TournyMatch( new ArrayList( parts ) ) ); break; } case TournyType.FreeForAll: { level.Matches.Add( new TournyMatch( copy ) ); break; } case TournyType.Standard: { if ( partsPerMatch >= 2 && participants.Count % partsPerMatch == 1 ) { int lowAdvances = int.MaxValue; for ( int i = 0; i < participants.Count; ++i ) { TournyParticipant p = (TournyParticipant)participants[i]; if ( p.FreeAdvances < lowAdvances ) lowAdvances = p.FreeAdvances; } ArrayList toAdvance = new ArrayList(); for ( int i = 0; i < participants.Count; ++i ) { TournyParticipant p = (TournyParticipant)participants[i]; if ( p.FreeAdvances == lowAdvances ) toAdvance.Add( p ); } if ( toAdvance.Count == 0 ) toAdvance = copy; // sanity int idx = Utility.Random( toAdvance.Count ); ((TournyParticipant)toAdvance[idx]).AddLog( "Advanced automatically due to an odd number of challengers." ); level.FreeAdvance = (TournyParticipant)toAdvance[idx]; ++level.FreeAdvance.FreeAdvances; copy.Remove( toAdvance[idx] ); } while ( copy.Count >= partsPerMatch ) { ArrayList thisMatch = new ArrayList(); for ( int i = 0; i < partsPerMatch; ++i ) { int idx = 0; switch ( groupType ) { case GroupingType.HighVsLow: idx = (i * (copy.Count - 1)) / (partsPerMatch - 1); break; case GroupingType.Nearest: idx = 0; break; case GroupingType.Random: idx = Utility.Random( copy.Count ); break; } thisMatch.Add( copy[idx] ); copy.RemoveAt( idx ); } level.Matches.Add( new TournyMatch( thisMatch ) ); } if ( copy.Count > 1 ) level.Matches.Add( new TournyMatch( copy ) ); break; } } m_Levels.Add( level ); } } public class PyramidLevel { private ArrayList m_Matches; private TournyParticipant m_FreeAdvance; public ArrayList Matches { get{ return m_Matches; } set{ m_Matches = value; } } public TournyParticipant FreeAdvance { get{ return m_FreeAdvance; } set{ m_FreeAdvance = value; } } public PyramidLevel() { m_Matches = new ArrayList(); } } public class TournyMatch { private ArrayList m_Participants; private TournyParticipant m_Winner; private DuelContext m_Context; public ArrayList Participants { get{ return m_Participants; } set{ m_Participants = value; } } public TournyParticipant Winner { get{ return m_Winner; } set{ m_Winner = value; } } public DuelContext Context { get{ return m_Context; } set{ m_Context = value; } } public bool InProgress { get{ return ( m_Context != null && m_Context.Registered ); } } public void Start( Arena arena, Tournament tourny ) { TournyParticipant first = (TournyParticipant)m_Participants[0]; DuelContext dc = new DuelContext( (Mobile)first.Players[0], tourny.Ruleset.Layout, false ); dc.Ruleset.Options.SetAll(false); dc.Ruleset.Options.Or(tourny.Ruleset.Options); for ( int i = 0; i < m_Participants.Count; ++i ) { TournyParticipant tournyPart = (TournyParticipant)m_Participants[i]; Participant duelPart = new Participant( dc, tournyPart.Players.Count ); duelPart.TournyPart = tournyPart; for ( int j = 0; j < tournyPart.Players.Count; ++j ) duelPart.Add( (Mobile) tournyPart.Players[j] ); for ( int j = 0; j < duelPart.Players.Length; ++j ) { if ( duelPart.Players[j] != null ) duelPart.Players[j].Ready = true; } dc.Participants.Add( duelPart ); } if ( tourny.EventController != null ) dc.m_EventGame = tourny.EventController.Construct( dc ); dc.m_Tournament = tourny; dc.m_Match = this; dc.m_OverrideArena = arena; if ( tourny.SuddenDeath > TimeSpan.Zero && (tourny.SuddenDeathRounds == 0 || tourny.Pyramid.Levels.Count <= tourny.SuddenDeathRounds) ) dc.StartSuddenDeath( tourny.SuddenDeath ); dc.SendReadyGump( 0 ); if ( dc.StartedBeginCountdown ) { m_Context = dc; for ( int i = 0; i < m_Participants.Count; ++i ) { TournyParticipant p = (TournyParticipant)m_Participants[i]; for ( int j = 0; j < p.Players.Count; ++j ) { Mobile mob = (Mobile)p.Players[j]; foreach ( Mobile view in mob.GetMobilesInRange( 18 ) ) { if ( !mob.CanSee( view ) ) mob.Send( view.RemovePacket ); } mob.LocalOverheadMessage( MessageType.Emote, 0x3B2, false, "* Your mind focuses intently on the fight and all other distractions fade away *" ); } } } else { dc.Unregister(); dc.StopCountdown(); } } public TournyMatch( ArrayList participants ) { m_Participants = participants; for ( int i = 0; i < participants.Count; ++i ) { TournyParticipant part = (TournyParticipant)participants[i]; StringBuilder sb = new StringBuilder(); sb.Append( "Matched in a duel against " ); if ( participants.Count > 2 ) sb.AppendFormat( "{0} other {1}: ", participants.Count - 1, part.Players.Count == 1 ? "players" : "teams" ); bool hasAppended = false; for ( int j = 0; j < participants.Count; ++j ) { if ( i == j ) continue; if ( hasAppended ) sb.Append( ", " ); sb.Append( ((TournyParticipant)participants[j]).NameList ); hasAppended = true; } sb.Append( "." ); part.AddLog( sb.ToString() ); } } } public class TournyParticipant : IComparable { private ArrayList m_Players; private ArrayList m_Log; private int m_FreeAdvances; public ArrayList Players { get{ return m_Players; } set{ m_Players = value; } } public ArrayList Log { get{ return m_Log; } set{ m_Log = value; } } public int FreeAdvances { get{ return m_FreeAdvances; } set{ m_FreeAdvances = value; } } public int TotalLadderXP { get { Ladder ladder = Ladder.Instance; if ( ladder == null ) return 0; int total = 0; for ( int i = 0; i < m_Players.Count; ++i ) { Mobile mob = (Mobile)m_Players[i]; LadderEntry entry = ladder.Find( mob ); if ( entry != null ) total += entry.Experience; } return total; } } public string NameList { get { StringBuilder sb = new StringBuilder(); for ( int i = 0; i < m_Players.Count; ++i ) { if ( m_Players[i] == null ) continue; Mobile mob = (Mobile) m_Players[i]; if ( sb.Length > 0 ) { if ( m_Players.Count == 2 ) sb.Append( " and " ); else if ( (i+1) < m_Players.Count ) sb.Append( ", " ); else sb.Append( ", and " ); } sb.Append( mob.Name ); } if ( sb.Length == 0 ) return "Empty"; return sb.ToString(); } } public void AddLog( string text ) { m_Log.Add( text ); } public void AddLog( string format, params object[] args ) { AddLog( String.Format( format, args ) ); } public void WonMatch( TournyMatch match ) { AddLog( "Match won." ); } public void LostMatch( TournyMatch match ) { AddLog( "Match lost." ); } public TournyParticipant( Mobile owner ) { m_Log = new ArrayList(); m_Players = new ArrayList(); m_Players.Add( owner ); } public TournyParticipant( ArrayList players ) { m_Log = new ArrayList(); m_Players = players; } public int CompareTo( object obj ) { TournyParticipant p = (TournyParticipant)obj; return p.TotalLadderXP - this.TotalLadderXP; } } public enum TournyBracketGumpType { Index, Rules_Info, Participant_List, Participant_Info, Round_List, Round_Info, Match_Info, Player_Info } public class TournamentBracketGump : Gump { private Mobile m_From; private Tournament m_Tournament; private TournyBracketGumpType m_Type; private ArrayList m_List; private int m_Page; private int m_PerPage; private object m_Object; private const int BlackColor32 = 0x000008; private const int LabelColor32 = 0xFFFFFF; public string Center( string text ) { return String.Format( "
{0}
", text ); } public string Color( string text, int color ) { return String.Format( "{1}", color, text ); } private void AddBorderedText( int x, int y, int width, int height, string text, int color, int borderColor ) { AddColoredText( x - 1, y - 1, width, height, text, borderColor ); AddColoredText( x - 1, y + 1, width, height, text, borderColor ); AddColoredText( x + 1, y - 1, width, height, text, borderColor ); AddColoredText( x + 1, y + 1, width, height, text, borderColor ); AddColoredText( x, y, width, height, text, color ); } private void AddColoredText( int x, int y, int width, int height, string text, int color ) { if ( color == 0 ) AddHtml( x, y, width, height, text, false, false ); else AddHtml( x, y, width, height, Color( text, color ), false, false ); } public void AddRightArrow( int x, int y, int bid, string text ) { AddButton( x, y, 0x15E1, 0x15E5, bid, GumpButtonType.Reply, 0 ); if ( text != null ) AddHtml( x + 20, y - 1, 230, 20, text, false, false ); } public void AddRightArrow( int x, int y, int bid ) { AddRightArrow( x, y, bid, null ); } public void AddLeftArrow( int x, int y, int bid, string text ) { AddButton( x, y, 0x15E3, 0x15E7, bid, GumpButtonType.Reply, 0 ); if ( text != null ) AddHtml( x + 20, y - 1, 230, 20, text, false, false ); } public void AddLeftArrow( int x, int y, int bid ) { AddLeftArrow( x, y, bid, null ); } public int ToButtonID( int type, int index ) { return 1 + (index * 7) + type; } public bool FromButtonID( int bid, out int type, out int index ) { type = ( bid - 1 ) % 7; index = ( bid - 1 ) / 7; return ( bid >= 1 ); } public void StartPage( out int index, out int count, out int y, int perPage ) { m_PerPage = perPage; index = Math.Max( m_Page * perPage, 0 ); count = Math.Max( Math.Min( m_List.Count - index, perPage ), 0 ); y = 53 + ((12 - perPage) * 18); if ( m_Page > 0 ) AddLeftArrow( 242, 35, ToButtonID( 1, 0 ) ); if ( (m_Page + 1) * perPage < m_List.Count ) AddRightArrow( 260, 35, ToButtonID( 1, 1 ) ); } public TournamentBracketGump( Mobile from, Tournament tourny, TournyBracketGumpType type, ArrayList list, int page, object obj ) : base( 50, 50 ) { m_From = from; m_Tournament = tourny; m_Type = type; m_List = list; m_Page = page; m_Object = obj; m_PerPage = 12; switch ( type ) { case TournyBracketGumpType.Index: { AddPage( 0 ); AddBackground( 0, 0, 300, 300, 9380 ); StringBuilder sb = new StringBuilder(); if ( tourny.TournyType == TournyType.FreeForAll ) { sb.Append( "FFA" ); } else if ( tourny.TournyType == TournyType.RandomTeam ) { sb.Append( tourny.ParticipantsPerMatch ); sb.Append( "-Team" ); } else if ( tourny.TournyType == TournyType.RedVsBlue ) { sb.Append( "Red v Blue" ); } else if ( tourny.TournyType == TournyType.Faction ) { sb.Append( tourny.ParticipantsPerMatch ); sb.Append( "-Team Faction" ); } else { for ( int i = 0; i < tourny.ParticipantsPerMatch; ++i ) { if ( sb.Length > 0 ) sb.Append( 'v' ); sb.Append( tourny.PlayersPerParticipant ); } } if ( tourny.EventController != null ) sb.Append( ' ' ).Append( tourny.EventController.Title ); sb.Append( " Tournament Bracket" ); AddHtml( 25, 35, 250, 20, Center( sb.ToString() ), false, false ); AddRightArrow( 25, 53, ToButtonID( 0, 4 ), "Rules" ); AddRightArrow( 25, 71, ToButtonID( 0, 1 ), "Participants" ); if ( m_Tournament.Stage == TournamentStage.Signup ) { TimeSpan until = ( m_Tournament.SignupStart + m_Tournament.SignupPeriod ) - DateTime.UtcNow; string text; int secs = (int) until.TotalSeconds; if ( secs > 0 ) { int mins = secs / 60; secs %= 60; if ( mins > 0 && secs > 0 ) text = String.Format( "The tournament will begin in {0} minute{1} and {2} second{3}.", mins, mins==1?"":"s", secs, secs==1?"":"s" ); else if ( mins > 0 ) text = String.Format( "The tournament will begin in {0} minute{1}.", mins, mins==1?"":"s" ); else if ( secs > 0 ) text = String.Format( "The tournament will begin in {0} second{1}.", secs, secs==1?"":"s" ); else text = "The tournament will begin shortly."; } else { text = "The tournament will begin shortly."; } AddHtml( 25, 92, 250, 40, text, false, false ); } else { AddRightArrow( 25, 89, ToButtonID( 0, 2 ), "Rounds" ); } break; } case TournyBracketGumpType.Rules_Info: { Ruleset ruleset = tourny.Ruleset; Ruleset basedef = ruleset.Base; BitArray defs; if ( ruleset.Flavors.Count > 0 ) { defs = new BitArray( basedef.Options ); for ( int i = 0; i < ruleset.Flavors.Count; ++i ) defs.Or( ((Ruleset)ruleset.Flavors[i]).Options ); } else { defs = basedef.Options; } int changes = 0; BitArray opts = ruleset.Options; for ( int i = 0; i < opts.Length; ++i ) { if ( defs[i] != opts[i] ) ++changes; } AddPage( 0 ); AddBackground( 0, 0, 300, 60 + 18 + 20 + 20 + 20 + 8 + 20 + (ruleset.Flavors.Count * 18) + 4 + 20 + (changes * 22) + 6, 9380 ); AddLeftArrow( 25, 11, ToButtonID( 0, 0 ) ); AddHtml( 25, 35, 250, 20, Center( "Rules" ), false, false ); int y = 53; string groupText = null; switch ( tourny.GroupType ) { case GroupingType.HighVsLow: groupText = "High vs Low"; break; case GroupingType.Nearest: groupText = "Closest opponent"; break; case GroupingType.Random: groupText = "Random"; break; } AddHtml( 35, y, 190, 20, String.Format( "Grouping: {0}", groupText ), false, false ); y += 20; string tieText = null; switch ( tourny.TieType ) { case TieType.Random: tieText = "Random"; break; case TieType.Highest: tieText = "Highest advances"; break; case TieType.Lowest: tieText = "Lowest advances"; break; case TieType.FullAdvancement: tieText = ( tourny.ParticipantsPerMatch == 2 ? "Both advance" : "Everyone advances" ); break; case TieType.FullElimination: tieText = ( tourny.ParticipantsPerMatch == 2 ? "Both eliminated" : "Everyone eliminated" ); break; } AddHtml( 35, y, 190, 20, String.Format( "Tiebreaker: {0}", tieText ), false, false ); y += 20; string sdText = "Off"; if ( tourny.SuddenDeath > TimeSpan.Zero ) { sdText = String.Format( "{0}:{1:D2}", (int) tourny.SuddenDeath.TotalMinutes, tourny.SuddenDeath.Seconds ); if ( tourny.SuddenDeathRounds > 0 ) sdText = String.Format( "{0} (first {1} rounds)", sdText, tourny.SuddenDeathRounds ); else sdText = String.Format( "{0} (all rounds)", sdText ); } AddHtml( 35, y, 240, 20, String.Format( "Sudden Death: {0}", sdText ), false, false ); y += 20; y += 8; AddHtml( 35, y, 190, 20, String.Format( "Ruleset: {0}", basedef.Title ), false, false ); y += 20; for ( int i = 0; i < ruleset.Flavors.Count; ++i, y += 18 ) AddHtml( 35, y, 190, 20, String.Format( " + {0}", ((Ruleset)ruleset.Flavors[i]).Title ), false, false ); y += 4; if ( changes > 0 ) { AddHtml( 35, y, 190, 20, "Modifications:", false, false ); y += 20; for ( int i = 0; i < opts.Length; ++i ) { if ( defs[i] != opts[i] ) { string name = ruleset.Layout.FindByIndex( i ); if ( name != null ) // sanity { AddImage( 35, y, opts[i] ? 0xD3 : 0xD2 ); AddHtml( 60, y, 165, 22, name, false, false ); } y += 22; } } } else { AddHtml( 35, y, 190, 20, "Modifications: None", false, false ); y += 20; } break; } case TournyBracketGumpType.Participant_List: { AddPage( 0 ); AddBackground( 0, 0, 300, 300, 9380 ); if ( m_List == null ) m_List = new ArrayList( tourny.Participants ); AddLeftArrow( 25, 11, ToButtonID( 0, 0 ) ); AddHtml( 25, 35, 250, 20, Center( String.Format( "{0} Participant{1}", m_List.Count, m_List.Count == 1 ? "" : "s" ) ), false, false ); int index, count, y; StartPage( out index, out count, out y, 12 ); for ( int i = 0; i < count; ++i, y += 18 ) { TournyParticipant part = (TournyParticipant)m_List[index + i]; string name = part.NameList; if ( m_Tournament.TournyType != TournyType.Standard && part.Players.Count == 1 ) { PlayerMobile pm = part.Players[0] as PlayerMobile; if ( pm != null && pm.DuelPlayer != null ) name = Color( name, pm.DuelPlayer.Eliminated ? 0x6633333 : 0x336666 ); } AddRightArrow( 25, y, ToButtonID( 2, index + i ), name ); } break; } case TournyBracketGumpType.Participant_Info: { TournyParticipant part = obj as TournyParticipant; if ( part == null ) break; AddPage( 0 ); AddBackground( 0, 0, 300, 60 + 18 + 20 + (part.Players.Count * 18) + 20 + 20 + 160, 9380 ); AddLeftArrow( 25, 11, ToButtonID( 0, 1 ) ); AddHtml( 25, 35, 250, 20, Center( "Participants" ), false, false ); int y = 53; AddHtml( 25, y, 200, 20, part.Players.Count == 1 ? "Players" : "Team", false, false ); y += 20; for ( int i = 0; i < part.Players.Count; ++i ) { Mobile mob = (Mobile)part.Players[i]; string name = mob.Name; if ( m_Tournament.TournyType != TournyType.Standard ) { PlayerMobile pm = mob as PlayerMobile; if ( pm != null && pm.DuelPlayer != null ) name = Color( name, pm.DuelPlayer.Eliminated ? 0x6633333 : 0x336666 ); } AddRightArrow( 35, y, ToButtonID( 4, i ), name ); y += 18; } AddHtml( 25, y, 200, 20, String.Format( "Free Advances: {0}", part.FreeAdvances == 0 ? "None" : part.FreeAdvances.ToString() ), false, false ); y += 20; AddHtml( 25, y, 200, 20, "Log:", false, false ); y += 20; StringBuilder sb = new StringBuilder(); for ( int i = 0; i < part.Log.Count; ++i ) { if ( sb.Length > 0 ) sb.Append( "
" ); sb.Append( part.Log[i] ); } if ( sb.Length == 0 ) sb.Append( "Nothing logged yet." ); AddHtml( 25, y, 250, 150, Color( sb.ToString(), BlackColor32 ), false, true ); break; } case TournyBracketGumpType.Player_Info: { AddPage( 0 ); AddBackground( 0, 0, 300, 300, 9380 ); AddLeftArrow( 25, 11, ToButtonID( 0, 3 ) ); AddHtml( 25, 35, 250, 20, Center( "Participants" ), false, false ); Mobile mob = obj as Mobile; if ( mob == null ) break; Ladder ladder = Ladder.Instance; LadderEntry entry = ( ladder == null ? null : ladder.Find( mob ) ); AddHtml( 25, 53, 250, 20, String.Format( "Name: {0}", mob.Name ), false, false ); AddHtml( 25, 73, 250, 20, String.Format( "Guild: {0}", mob.Guild == null ? "None" : mob.Guild.Name + " [" + mob.Guild.Abbreviation + "]" ), false, false ); AddHtml( 25, 93, 250, 20, String.Format( "Rank: {0}", entry == null ? "N/A" : LadderGump.Rank( entry.Index + 1 ) ), false, false ); AddHtml( 25, 113, 250, 20, String.Format( "Level: {0}", entry == null ? 0 : Ladder.GetLevel( entry.Experience ) ), false, false ); AddHtml( 25, 133, 250, 20, String.Format( "Wins: {0:N0}", entry == null ? 0 : entry.Wins ), false, false ); AddHtml( 25, 153, 250, 20, String.Format( "Losses: {0:N0}", entry == null ? 0 : entry.Losses ), false, false ); break; } case TournyBracketGumpType.Round_List: { AddPage( 0 ); AddBackground( 0, 0, 300, 300, 9380 ); AddLeftArrow( 25, 11, ToButtonID( 0, 0 ) ); AddHtml( 25, 35, 250, 20, Center( "Rounds" ), false, false ); if ( m_List == null ) m_List = new ArrayList( tourny.Pyramid.Levels ); int index, count, y; StartPage( out index, out count, out y, 12 ); for ( int i = 0; i < count; ++i, y += 18 ) { PyramidLevel level = (PyramidLevel)m_List[index + i]; AddRightArrow( 25, y, ToButtonID( 3, index + i ), "Round #" + (index + i + 1) ); } break; } case TournyBracketGumpType.Round_Info: { AddPage( 0 ); AddBackground( 0, 0, 300, 300, 9380 ); AddLeftArrow( 25, 11, ToButtonID( 0, 2 ) ); AddHtml( 25, 35, 250, 20, Center( "Rounds" ), false, false ); PyramidLevel level = m_Object as PyramidLevel; if ( level == null ) break; if ( m_List == null ) m_List = new ArrayList( level.Matches ); AddRightArrow( 25, 53, ToButtonID( 5, 0 ), String.Format( "Free Advance: {0}", level.FreeAdvance == null ? "None" : level.FreeAdvance.NameList ) ); AddHtml( 25, 73, 200, 20, String.Format( "{0} Match{1}", m_List.Count, m_List.Count == 1 ? "" : "es" ), false, false ); int index, count, y; StartPage( out index, out count, out y, 10 ); for ( int i = 0; i < count; ++i, y += 18 ) { TournyMatch match = (TournyMatch)m_List[index + i]; int color = -1; if ( match.InProgress ) color = 0x336666; else if ( match.Context != null && match.Winner == null ) color = 0x666666; StringBuilder sb = new StringBuilder(); if ( m_Tournament.TournyType == TournyType.Standard ) { for ( int j = 0; j < match.Participants.Count; ++j ) { if ( sb.Length > 0 ) sb.Append( " vs " ); TournyParticipant part = (TournyParticipant)match.Participants[j]; string txt = part.NameList; if ( color == -1 && match.Context != null && match.Winner == part ) txt = Color( txt, 0x336633 ); else if ( color == -1 && match.Context != null ) txt = Color( txt, 0x663333 ); sb.Append( txt ); } } else if ( m_Tournament.EventController != null || m_Tournament.TournyType == TournyType.RandomTeam || m_Tournament.TournyType == TournyType.RedVsBlue || m_Tournament.TournyType == TournyType.Faction ) { for ( int j = 0; j < match.Participants.Count; ++j ) { if ( sb.Length > 0 ) sb.Append( " vs " ); TournyParticipant part = (TournyParticipant)match.Participants[j]; string txt; if ( m_Tournament.EventController != null ) txt = String.Format( "Team {0} ({1})", m_Tournament.EventController.GetTeamName( j ), part.Players.Count ); else if ( m_Tournament.TournyType == TournyType.RandomTeam ) txt = String.Format( "Team {0} ({1})", j + 1, part.Players.Count ); else if ( m_Tournament.TournyType == TournyType.Faction ) { if ( m_Tournament.ParticipantsPerMatch == 4 ) { string name = "(null)"; switch ( j ) { case 0: { name = "Minax"; break; } case 1: { name = "Council of Mages"; break; } case 2: { name = "True Britannians"; break; } case 3: { name = "Shadowlords"; break; } } txt = String.Format( "{0} ({1})", name, part.Players.Count ); } else if ( m_Tournament.ParticipantsPerMatch == 2 ) { txt = String.Format( "{0} Team ({1})", j==0?"Evil":"Hero", part.Players.Count ); } else { txt = String.Format( "Team {0} ({1})", j + 1, part.Players.Count ); } } else txt = String.Format( "Team {0} ({1})", j == 0 ? "Red" : "Blue", part.Players.Count ); if ( color == -1 && match.Context != null && match.Winner == part ) txt = Color( txt, 0x336633 ); else if ( color == -1 && match.Context != null ) txt = Color( txt, 0x663333 ); sb.Append( txt ); } } else if ( m_Tournament.TournyType == TournyType.FreeForAll ) { sb.Append( "Free For All" ); } string str = sb.ToString(); if ( color >= 0 ) str = Color( str, color ); AddRightArrow( 25, y, ToButtonID( 5, index + i + 1 ), str ); } break; } case TournyBracketGumpType.Match_Info: { TournyMatch match = obj as TournyMatch; if ( match == null ) break; int ct = ( m_Tournament.TournyType == TournyType.FreeForAll ? 2 : match.Participants.Count ); AddPage( 0 ); AddBackground( 0, 0, 300, 60 + 18 + 20 + 20 + 20 + (ct*18) + 6, 9380 ); AddLeftArrow( 25, 11, ToButtonID( 0, 5 ) ); AddHtml( 25, 35, 250, 20, Center( "Rounds" ), false, false ); AddHtml( 25, 53, 250, 20, String.Format( "Winner: {0}", match.Winner == null ? "N/A" : match.Winner.NameList ), false, false ); AddHtml( 25, 73, 250, 20, String.Format( "State: {0}", match.InProgress ? "In progress" : match.Context != null ? "Complete" : "Waiting" ), false, false ); AddHtml( 25, 93, 250, 20, String.Format( "Participants:" ), false, false ); if ( m_Tournament.TournyType == TournyType.Standard ) { for ( int i = 0; i < match.Participants.Count; ++i ) { TournyParticipant part = (TournyParticipant)match.Participants[i]; AddRightArrow( 25, 113 + (i * 18), ToButtonID( 6, i ), part.NameList ); } } else if ( m_Tournament.EventController != null || m_Tournament.TournyType == TournyType.RandomTeam || m_Tournament.TournyType == TournyType.RedVsBlue || m_Tournament.TournyType == TournyType.Faction ) { for ( int i = 0; i < match.Participants.Count; ++i ) { TournyParticipant part = (TournyParticipant)match.Participants[i]; if ( m_Tournament.EventController != null ) AddRightArrow( 25, 113 + (i * 18), ToButtonID( 6, i ), String.Format( "Team {0} ({1})", m_Tournament.EventController.GetTeamName( i ), part.Players.Count ) ); else if ( m_Tournament.TournyType == TournyType.RandomTeam ) AddRightArrow( 25, 113 + (i * 18), ToButtonID( 6, i ), String.Format( "Team {0} ({1})", i+1, part.Players.Count ) ); else if ( m_Tournament.TournyType == TournyType.Faction ) { if ( m_Tournament.ParticipantsPerMatch == 4 ) { string name = "(null)"; switch ( i ) { case 0: { name = "Minax"; break; } case 1: { name = "Council of Mages"; break; } case 2: { name = "True Britannians"; break; } case 3: { name = "Shadowlords"; break; } } AddRightArrow( 25, 113 + (i * 18), ToButtonID( 6, i ), String.Format( "{0} ({1})", name, part.Players.Count ) ); } else if ( m_Tournament.ParticipantsPerMatch == 2 ) { AddRightArrow( 25, 113 + (i * 18), ToButtonID( 6, i ), String.Format( "{0} Team ({1})", i==0?"Evil":"Hero", part.Players.Count ) ); } else { AddRightArrow( 25, 113 + (i * 18), ToButtonID( 6, i ), String.Format( "Team {0} ({1})", i+1, part.Players.Count ) ); } } else AddRightArrow( 25, 113 + (i * 18), ToButtonID( 6, i ), String.Format( "Team {0} ({1})", i==0?"Red":"Blue", part.Players.Count ) ); } } else if ( m_Tournament.TournyType == TournyType.FreeForAll ) { AddHtml( 25, 113, 250, 20, "Free For All", false, false ); } break; } } } public override void OnResponse( NetState sender, RelayInfo info ) { int type, index; if ( !FromButtonID( info.ButtonID, out type, out index ) ) return; switch ( type ) { case 0: { switch ( index ) { case 0: m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, TournyBracketGumpType.Index, null, 0, null ) ); break; case 1: m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, TournyBracketGumpType.Participant_List, null, 0, null ) ); break; case 2: m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, TournyBracketGumpType.Round_List, null, 0, null ) ); break; case 4: m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, TournyBracketGumpType.Rules_Info, null, 0, null ) ); break; case 3: { Mobile mob = m_Object as Mobile; for ( int i = 0; i < m_Tournament.Participants.Count; ++i ) { TournyParticipant part = (TournyParticipant)m_Tournament.Participants[i]; if ( part.Players.Contains( mob ) ) { m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, TournyBracketGumpType.Participant_Info, null, 0, part ) ); break; } } break; } case 5: { TournyMatch match = m_Object as TournyMatch; if ( match == null ) break; for ( int i = 0; i < m_Tournament.Pyramid.Levels.Count; ++i ) { PyramidLevel level = (PyramidLevel)m_Tournament.Pyramid.Levels[i]; if ( level.Matches.Contains( match ) ) m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, TournyBracketGumpType.Round_Info, null, 0, level ) ); } break; } } break; } case 1: { switch ( index ) { case 0: { if ( m_List != null && m_Page > 0 ) m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, m_Type, m_List, m_Page - 1, m_Object ) ); break; } case 1: { if ( m_List != null && ((m_Page + 1) * m_PerPage) < m_List.Count ) m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, m_Type, m_List, m_Page + 1, m_Object ) ); break; } } break; } case 2: { if ( m_Type != TournyBracketGumpType.Participant_List ) break; if ( index >= 0 && index < m_List.Count ) m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, TournyBracketGumpType.Participant_Info, null, 0, m_List[index] ) ); break; } case 3: { if ( m_Type != TournyBracketGumpType.Round_List ) break; if ( index >= 0 && index < m_List.Count ) m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, TournyBracketGumpType.Round_Info, null, 0, m_List[index] ) ); break; } case 4: { if ( m_Type != TournyBracketGumpType.Participant_Info ) break; TournyParticipant part = m_Object as TournyParticipant; if ( part != null && index >= 0 && index < part.Players.Count ) m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, TournyBracketGumpType.Player_Info, null, 0, part.Players[index] ) ); break; } case 5: { if ( m_Type != TournyBracketGumpType.Round_Info ) break; PyramidLevel level = m_Object as PyramidLevel; if ( level == null ) break; if ( index == 0 ) { if ( level.FreeAdvance != null ) m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, TournyBracketGumpType.Participant_Info, null, 0, level.FreeAdvance ) ); else m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, m_Type, m_List, m_Page, m_Object ) ); } else if ( index >= 1 && index <= level.Matches.Count ) { m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, TournyBracketGumpType.Match_Info, null, 0, level.Matches[index-1] ) ); } break; } case 6: { if ( m_Type != TournyBracketGumpType.Match_Info ) break; TournyMatch match = m_Object as TournyMatch; if ( match != null && index >= 0 && index < match.Participants.Count ) m_From.SendGump( new TournamentBracketGump( m_From, m_Tournament, TournyBracketGumpType.Participant_Info, null, 0, match.Participants[index] ) ); break; } } } } public class TournamentBracketItem : Item { private TournamentController m_Tournament; [CommandProperty( AccessLevel.GameMaster )] public TournamentController Tournament{ get{ return m_Tournament; } set{ m_Tournament = value; } } public override string DefaultName { get { return "tournament bracket"; } } [Constructable] public TournamentBracketItem() : base( 3774 ) { Movable = false; } public override void OnDoubleClick(Mobile from) { if ( !from.InRange( GetWorldLocation(), 2 ) ) { from.LocalOverheadMessage( MessageType.Regular, 0x3B2, 1019045 ); // I can't reach that } else if ( m_Tournament != null ) { Tournament tourny = m_Tournament.Tournament; if ( tourny != null ) { from.CloseGump( typeof( TournamentBracketGump ) ); from.SendGump( new TournamentBracketGump( from, tourny, TournyBracketGumpType.Index, null, 0, null ) ); /*if ( tourny.Stage == TournamentStage.Fighting && tourny.Pyramid.Levels.Count > 0 ) from.SendGump( new TournamentBracketGump( tourny, (PyramidLevel)tourny.Pyramid.Levels[tourny.Pyramid.Levels.Count - 1] ) ); else from.SendGump( new TournamentBracketGump( tourny, 0 ) );*/ } } } public TournamentBracketItem( Serial serial ) : base( serial ) { } public override void Serialize( GenericWriter writer ) { base.Serialize( writer ); writer.Write( (int) 0 ); writer.Write( (Item) m_Tournament ); } public override void Deserialize( GenericReader reader ) { base.Deserialize( reader ); int version = reader.ReadInt(); switch ( version ) { case 0: { m_Tournament = reader.ReadItem() as TournamentController; break; } } } } }