ModernUO/Scripts/Engines/ConPVP/Tournament.cs
2018-09-14 08:46:14 -07:00

3578 lines
100 KiB
C#

using System;
using System.Text;
using System.Collections;
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;
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 => m_Tournament;
set => m_Tournament = value;
}
[Constructible]
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 => m_Tournament;
set => m_Tournament = value;
}
[CommandProperty( AccessLevel.GameMaster )]
public Mobile Registrar{ get => m_Registrar;
set => m_Registrar = value;
}
public override string DefaultName => "tournament signup book";
[Constructible]
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
{
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:
{
m_Registrar?.PrivateOverheadMessage( MessageType.Regular,
0x35, false, "The tournament is closed.", from.NetState );
break;
}
case TournamentStage.Signup:
{
Ladder ladder = Ladder.Instance;
LadderEntry entry = ladder?.Find( from );
if ( entry != null && Ladder.GetLevel( entry.Experience ) < tourny.LevelRequirement )
{
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 )
{
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 ) ) )
{
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 ) ) )
{
m_Registrar?.PrivateOverheadMessage( MessageType.Regular,
0x22, false, "You must first cancel your duel offer.", from.NetState );
}
else if ( from is PlayerMobile mobile && mobile.DuelContext != null )
{
m_Registrar?.PrivateOverheadMessage( MessageType.Regular,
0x22, false, "You are already participating in a duel.", mobile.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
{
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( "<CENTER>{0}</CENTER>", text );
}
public string Color( string text, int color )
{
return String.Format( "<BASEFONT COLOR=#{0:X6}>{1}</BASEFONT>", 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?.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;
}
if ( tourny.IsFactionRestricted && Faction.Find( mob ) == 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;
}
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;
}
if ( mob is PlayerMobile mobile && mobile.DuelContext != 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.", mobile.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 )
{
if ( !(obj is Mobile mob) || mob == from )
{
m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) );
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 ) );
m_Registrar?.PrivateOverheadMessage( MessageType.Regular,
0x22, false, "They ignore your invitation.", from.NetState );
}
else
{
if ( !(mob is PlayerMobile pm) )
return;
if ( pm.DuelContext != null )
{
m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) );
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 ) );
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 ) );
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 ) );
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 ) );
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 ) );
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 ) );
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( "<CENTER>{0}</CENTER>", text );
}
public string Color( string text, int color )
{
return String.Format( "<BASEFONT COLOR=#{0:X6}>{1}</BASEFONT>", 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 ) )
{
if ( !(mob is PlayerMobile pm) )
return;
if ( AcceptDuelGump.IsIgnored( mob, from ) || mob.Blessed )
{
m_From.SendGump( new ConfirmSignupGump( m_From, m_Registrar, m_Tournament, m_Players ) );
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 ) );
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 ) );
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 ) );
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 ) );
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 => 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 => "tournament controller";
[Constructible]
public TournamentController() : base( 0x1B7A )
{
Visible = false;
Movable = false;
m_Tournament = new Tournament();
m_Instances.Add( this );
}
public override void GetContextMenuEntries( Mobile from, List<ContextMenuEntry> 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 => ( m_TournyType != TournyType.Standard );
[CommandProperty( AccessLevel.GameMaster )]
public EventController EventController
{
get => m_EventController;
set => m_EventController = value;
}
[CommandProperty( AccessLevel.GameMaster )]
public int SuddenDeathRounds
{
get => m_SuddenDeathRounds;
set => m_SuddenDeathRounds = value;
}
[CommandProperty( AccessLevel.GameMaster )]
public TournyType TournyType
{
get => m_TournyType;
set => m_TournyType = value;
}
[CommandProperty( AccessLevel.GameMaster )]
public GroupingType GroupType
{
get => m_GroupType;
set => m_GroupType = value;
}
[CommandProperty( AccessLevel.GameMaster )]
public TieType TieType
{
get => m_TieType;
set => m_TieType = value;
}
[CommandProperty( AccessLevel.GameMaster )]
public TimeSpan SuddenDeath
{
get => m_SuddenDeath;
set => m_SuddenDeath = value;
}
public Ruleset Ruleset
{
get => m_Ruleset;
set => m_Ruleset = value;
}
[CommandProperty( AccessLevel.GameMaster )]
public int ParticipantsPerMatch
{
get => m_ParticipantsPerMatch;
set{ if ( value < 2 ) value = 2; else if ( value > 10 ) value = 10; m_ParticipantsPerMatch = value; }
}
[CommandProperty( AccessLevel.GameMaster )]
public int PlayersPerParticipant
{
get => m_PlayersPerParticipant;
set{ if ( value < 1 ) value = 1; else if ( value > 10 ) value = 10; m_PlayersPerParticipant = value; }
}
[CommandProperty( AccessLevel.GameMaster )]
public int LevelRequirement
{
get => m_LevelRequirement;
set => m_LevelRequirement = value;
}
[CommandProperty( AccessLevel.GameMaster )]
public bool FactionRestricted
{
get => m_FactionRestricted;
set => m_FactionRestricted = value;
}
[CommandProperty( AccessLevel.GameMaster )]
public TimeSpan SignupPeriod
{
get => m_SignupPeriod;
set => m_SignupPeriod = value;
}
[CommandProperty( AccessLevel.GameMaster )]
public DateTime SignupStart
{
get => m_SignupStart;
set => m_SignupStart = value;
}
[CommandProperty( AccessLevel.GameMaster )]
public TournamentStage CurrentStage => m_Stage;
public TournamentStage Stage
{
get => m_Stage;
set => m_Stage = value;
}
public TournyPyramid Pyramid
{
get => m_Pyramid;
set => m_Pyramid = value;
}
public ArrayList Arenas
{
get => m_Arenas;
set => m_Arenas = value;
}
public ArrayList Participants
{
get => m_Participants;
set => m_Participants = value;
}
public ArrayList Undefeated
{
get => m_Undefeated;
set => m_Undefeated = value;
}
public bool IsFactionRestricted => ( 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 => 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 => m_Matches;
set => m_Matches = value;
}
public TournyParticipant FreeAdvance
{
get => 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 => m_Participants;
set => m_Participants = value;
}
public TournyParticipant Winner
{
get => m_Winner;
set => m_Winner = value;
}
public DuelContext Context
{
get => m_Context;
set => m_Context = value;
}
public bool InProgress => ( 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 => m_Players;
set => m_Players = value;
}
public ArrayList Log
{
get => m_Log;
set => m_Log = value;
}
public int FreeAdvances
{
get => 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( "<CENTER>{0}</CENTER>", text );
}
public string Color( string text, int color )
{
return String.Format( "<BASEFONT COLOR=#{0:X6}>{1}</BASEFONT>", 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 )
{
if ( part.Players[0] is PlayerMobile pm && pm.DuelPlayer != null )
name = Color( name, pm.DuelPlayer.Eliminated ? 0x6633333 : 0x336666 );
}
AddRightArrow( 25, y, ToButtonID( 2, index + i ), name );
}
break;
}
case TournyBracketGumpType.Participant_Info:
{
if ( !(obj is TournyParticipant part) )
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 )
{
if ( mob is PlayerMobile pm && 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( "<br>" );
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 );
if ( !(obj is Mobile mob) )
break;
Ladder ladder = Ladder.Instance;
LadderEntry entry = 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 );
if ( !(m_Object is PyramidLevel level) )
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:
{
if ( !(obj is TournyMatch match) )
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, "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:
{
if ( !(m_Object is TournyMatch match) )
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;
if ( m_Object is TournyParticipant part && 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;
if ( !(m_Object is PyramidLevel level) )
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;
if ( m_Object is TournyMatch match && 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 => m_Tournament;
set => m_Tournament = value;
}
public override string DefaultName => "tournament bracket";
[Constructible]
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
{
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;
}
}
}
}
}