diff --git a/Scripts/Engines/ConPVP/Games/BombingRun.cs b/Scripts/Engines/ConPVP/Games/BombingRun.cs
new file mode 100644
index 000000000..4683b18d5
--- /dev/null
+++ b/Scripts/Engines/ConPVP/Games/BombingRun.cs
@@ -0,0 +1,1959 @@
+
+using System;
+using System.Collections;
+using System.Text;
+using Server;
+using Server.Items;
+using Server.Mobiles;
+using Server.Network;
+using Server.Targeting;
+using Server.Gumps;
+
+namespace Server.Engines.ConPVP
+{
+ public class BRBomb : Item
+ {
+ private BRGame m_Game;
+ private Mobile m_Thrower;
+ private EffectTimer m_Timer;
+ private bool m_Flying;
+
+ private ArrayList m_Helpers;
+
+ private Mobile FindOwner( object parent )
+ {
+ if ( parent is Item )
+ return ( (Item) parent ).RootParent as Mobile;
+
+ if ( parent is Mobile )
+ return (Mobile) parent;
+
+ return null;
+ }
+
+ public BRBomb( BRGame game ) : base( 0x103C ) // 0x103C = bread, 0x1042 = pie, 0x1364 = rock, 0x13a8 = pillow, 0x2256 = bagball
+ {
+ Name = "da bomb";
+ Movable = false;
+ Hue = 0x35;
+
+ m_Game = game;
+
+ m_Helpers = new ArrayList();
+
+ m_Timer = new EffectTimer( this );
+ m_Timer.Start();
+ }
+
+ private class EffectTimer : Timer
+ {
+ private BRBomb m_Bomb;
+ private int m_Count;
+
+ public EffectTimer( BRBomb bomb ) : base( TimeSpan.Zero, TimeSpan.FromSeconds( 1.0 ) )
+ {
+ m_Bomb = bomb;
+ m_Count = 0;
+ Priority = TimerPriority.FiftyMS;
+ }
+
+ protected override void OnTick()
+ {
+ if ( m_Bomb.Parent == null && m_Bomb.m_Game != null && m_Bomb.m_Game.Controller != null )
+ {
+ if ( !m_Bomb.m_Flying && m_Bomb.Map != Map.Internal )
+ Effects.SendLocationEffect( m_Bomb.GetWorldLocation(), m_Bomb.Map, 0x377A, 16, 10, m_Bomb.Hue, 0 );
+
+ if ( m_Bomb.Location != m_Bomb.m_Game.Controller.BombHome )
+ {
+ if ( ++m_Count >= 30 )
+ {
+ m_Bomb.m_Game.ReturnBomb();
+ m_Bomb.m_Game.Alert( "The bomb has been returned to it's starting point." );
+
+ m_Count = 0;
+ m_Bomb.m_Helpers.Clear();
+ }
+ }
+ else
+ {
+ m_Count = 0;
+ }
+ }
+ else
+ {
+ m_Count = 0;
+ }
+ }
+ }
+
+ public BRBomb( Serial serial ) : base( serial )
+ {
+ }
+
+ public override void Deserialize(GenericReader reader)
+ {
+ base.Deserialize (reader);
+
+ int version = reader.ReadInt();
+
+ switch ( version )
+ {
+ case 0:
+ {
+ break;
+ }
+ }
+
+ Timer.DelayCall( TimeSpan.Zero, new TimerCallback( Delete ) ).Start(); // delete this after the world loads
+ }
+
+ public override void Serialize(GenericWriter writer)
+ {
+ base.Serialize (writer);
+
+ writer.Write( (int) 0 ); // version
+ }
+
+ public override void OnAdded(IEntity parent)
+ {
+ base.OnAdded( parent );
+
+ Mobile mob = FindOwner( parent );
+
+ if ( mob != null )
+ {
+ mob.SolidHueOverride = 0x0499;
+
+ //int fighterRank = mob.Skills.Tactics.Value + mob.Skills.Anatomy + mob.Skills.Healing.Value + mob.Skills.Swords.Value + mob.Skills.Macing.Value + mob.Skills.Fencing.Value + mob.Skills.Archery.Value + mob.Skills.Parrying.Value;
+ //int mageRank = mob.Skills.Magery.Value + mob.Skills.Meditation.Value + mob.Skills.EvalInt.Value + mob.Skills.Inscribe.Value + mob.Skills.Wrestling.Value + mob.Skills.MagicResist;
+ //int theifRank = mob.Skills.Stealing.Value + mob.Skills.Snooping.Value + mob.Skills.Hiding.Value + mob.Skills.Stealth.Value + mob.Skills.RemoveTrap.Value + mob.Skills.Lockpicking.Value + mob.Skills.ItemID.Value;
+
+ // To Do: Give them a special ability while holding the ball maybe based on skills?
+ }
+ }
+
+ public override void OnRemoved(IEntity parent)
+ {
+ base.OnRemoved( parent );
+
+ Mobile mob = FindOwner( parent );
+
+ if ( mob != null && m_Game != null )
+ mob.SolidHueOverride = m_Game.GetColor( mob );
+ }
+
+ public void DropTo( Mobile mob, Mobile killer )
+ {
+ if ( mob != null && !mob.Deleted )
+ this.MoveToWorld( mob.Location, mob.Map );
+ else if ( killer != null && !killer.Deleted )
+ this.MoveToWorld( killer.Location, killer.Map );
+ else if ( m_Game != null )
+ m_Game.ReturnBomb();
+ }
+
+ public override bool OnMoveOver( Mobile m )
+ {
+ if ( m_Flying || !Visible || m_Game == null || m == null || !m.Alive )
+ return true;
+
+ BRTeamInfo useTeam = m_Game.GetTeamInfo( m );
+ if ( useTeam == null )
+ return true;
+
+ return TakeBomb( m, useTeam, "picked up" );
+ }
+
+ public override void OnLocationChange(Point3D oldLocation)
+ {
+ base.OnLocationChange(oldLocation);
+
+ if ( m_Flying || !Visible || m_Game == null || this.Parent != null )
+ return;
+
+ IPooledEnumerable eable = this.GetClientsInRange( 0 );
+ foreach ( NetState ns in eable )
+ {
+ Mobile m = ns.Mobile;
+
+ if ( m == null || !m.Player || !m.Alive )
+ continue;
+
+ BRTeamInfo useTeam = m_Game.GetTeamInfo( m );
+ if ( useTeam != null )
+ TakeBomb( m, useTeam, "got" );
+ }
+ }
+
+ public override void OnAfterDelete()
+ {
+ base.OnAfterDelete ();
+
+ if ( m_Timer != null )
+ m_Timer.Stop();
+ }
+
+ public override void OnDoubleClick( Mobile m )
+ {
+ if ( m_Game == null || !Visible || m == null || !m.Alive )
+ return;
+
+ if ( !m_Flying && IsChildOf( m.Backpack ) )
+ {
+ m.Target = new BombTarget( this, m );
+ }
+ else if ( this.Parent == null )
+ {
+ if ( m.InRange( this.Location, 1 ) && m.Location.Z != this.Z )
+ {
+ BRTeamInfo useTeam = m_Game.GetTeamInfo( m );
+ if ( useTeam == null )
+ return;
+
+ TakeBomb( m, useTeam, "grabbed" );
+ }
+ }
+ }
+
+ private class BombTarget : Target
+ {
+ private BRBomb m_Bomb;
+ private Mobile m_Mob;
+ private bool m_Resend = true;
+
+ public BombTarget( BRBomb bomb, Mobile from ) : base( 10, true, TargetFlags.None )
+ {
+ CheckLOS = false;
+
+ m_Bomb = bomb;
+ m_Mob = from;
+
+ m_Mob.SendMessage( 0x26, "Where do you want to throw it?" );
+ }
+
+ protected override void OnTarget( Mobile from, object targeted )
+ {
+ m_Resend = !m_Bomb.OnBombTarget( from, targeted );
+ }
+
+ protected override void OnTargetUntargetable( Mobile from, object targeted )
+ {
+ m_Resend = !m_Bomb.OnBombTarget( from, targeted );
+ }
+
+ protected override void OnTargetFinish( Mobile from )
+ {
+ base.OnTargetFinish( from );
+
+ // has to be delayed in case some other target canceled us...
+ if ( m_Resend )
+ Timer.DelayCall( TimeSpan.Zero, new TimerCallback( ResendBombTarget ) ).Start();
+ }
+
+ private void ResendBombTarget()
+ {
+ // Make sure they still have the bomb, then give them the target back
+ if ( m_Bomb != null && !m_Bomb.Deleted && m_Mob != null && !m_Mob.Deleted && m_Mob.Alive )
+ {
+ if ( m_Bomb.IsChildOf( m_Mob ) )
+ m_Mob.Target = new BombTarget( m_Bomb, m_Mob );
+ }
+ }
+ }
+
+ private bool OnBombTarget( Mobile from, object obj )
+ {
+ if ( m_Game == null )
+ return true;
+
+ if ( !IsChildOf( from.Backpack ) )
+ return true;
+
+ // don't let them throw it to themselves
+ if ( obj == from )
+ return false;
+
+ if ( !(obj is IPoint3D) )
+ return false;
+
+ Point3D pt = new Point3D( (IPoint3D)obj );
+
+ if ( obj is Mobile )
+ pt.Z += 10;
+ else if ( obj is Item )
+ pt.Z += ((Item)obj).ItemData.CalcHeight + 1;
+
+ m_Flying = true;
+ this.Visible = false;
+ m_Thrower = from;
+ this.MoveToWorld( this.GetWorldLocation(), from.Map );
+
+ BeginFlight( pt );
+ return true;
+ }
+
+ private void HitObject( Point3D ballLoc, int objZ, int objHeight )
+ {
+ DoAnim( this.GetWorldLocation(), ballLoc, this.Map );
+ this.MoveToWorld( ballLoc );
+
+ m_Path.Clear();
+ m_PathIdx = 0;
+
+ Timer.DelayCall( TimeSpan.FromSeconds( 0.05 ), new TimerCallback( ContinueFlight ) ).Start();
+ }
+
+ private bool CheckCatch( Mobile m, Point3D myLoc )
+ {
+ if ( m == null || !m.Alive || !m.Player || m_Game == null )
+ return false;
+
+ if ( m_Game.GetTeamInfo( m ) == null )
+ return false;
+
+ int zdiff = myLoc.Z - m.Z;
+
+ if ( zdiff < 0 )
+ return false;
+ else if ( zdiff < 12 )
+ return true;
+ else if ( zdiff < 16 )
+ return Utility.RandomBool(); // 50% chance
+ else
+ return false;
+ }
+
+ private void DoAnim( Point3D start, Point3D end, Map map )
+ {
+ Effects.SendMovingEffect( new Entity( Serial.Zero, start, map ), new Entity( Serial.Zero, end, map ),
+ this.ItemID, 15, 0, false, false, this.Hue, 0 );
+ }
+
+ private void DoCatch( Mobile m )
+ {
+ m_Flying = false;
+ this.Visible = true;
+
+ if ( m == null || !m.Alive || !m.Player || m_Game == null )
+ return;
+
+ BRTeamInfo useTeam = m_Game.GetTeamInfo( m );
+
+ if ( useTeam == null )
+ return;
+
+ DoAnim( this.GetWorldLocation(), m.Location, m.Map );
+
+ string verb = "caught";
+
+ if ( m_Thrower != null && m_Game.GetTeamInfo( m_Thrower ) != useTeam )
+ verb = "intercepted";
+
+ if ( !TakeBomb( m, useTeam, verb ) )
+ this.MoveToWorld( m.Location, m.Map );
+ }
+
+ private Point3DList m_Path = new Point3DList();
+ private int m_PathIdx = 0;
+
+ private void BeginFlight( Point3D dest )
+ {
+ Point3D org = this.GetWorldLocation();
+
+ org.Z += 10; // always add 10 at the start cause we're coming from a mobile's eye level
+
+ /*if ( org.X > dest.X || ( org.X == dest.X && org.Y > dest.Y ) || ( org.X == dest.X && org.Y == dest.Y && org.Z > dest.Z ) )
+ {
+ Point3D swap = org;
+ org = dest;
+ dest = swap;
+ }*/
+
+ ArrayList list = new ArrayList();
+ double rise, run, zslp;
+ double dist3d, dist2d;
+ double x, y, z;
+ int xd, yd, zd;
+ Point3D p;
+
+ xd = dest.X - org.X;
+ yd = dest.Y - org.Y;
+ zd = dest.Z - org.Z;
+ dist2d = Math.Sqrt( xd * xd + yd * yd );
+ if ( zd != 0 )
+ dist3d = Math.Sqrt( dist2d * dist2d + zd * zd );
+ else
+ dist3d = dist2d;
+
+ rise = ( (float) yd ) / dist3d;
+ run = ( (float) xd ) / dist3d;
+ zslp = ( (float) zd ) / dist3d;
+
+ x = (int) org.X;
+ y = (int) org.Y;
+ z = (int) org.Z;
+ while ( Utility.NumberBetween( x, dest.X, org.X, 0.5 ) && Utility.NumberBetween( y, dest.Y, org.Y, 0.5 ) && Utility.NumberBetween( z, dest.Z, org.Z, 0.5 ) )
+ {
+ int ix = (int) Math.Round( x );
+ int iy = (int) Math.Round( y );
+ int iz = (int) Math.Round( z );
+
+ if ( list.Count > 0 )
+ {
+ p = (Point3D)list[list.Count-1];
+
+ if ( p.X != ix || p.Y != iy || p.Z != iz )
+ list.Add( new Point3D( ix, iy, iz ) );
+ }
+ else
+ {
+ list.Add( new Point3D( ix, iy, iz ) );
+ }
+
+ x += run;
+ y += rise;
+ z += zslp;
+ }
+
+ if ( list.Count > 0 )
+ {
+ if ( ((Point3D)list[list.Count-1]) != dest )
+ list.Add( dest );
+ }
+
+ /*if ( dist3d > 4 && ( dest.X != org.X || dest.Y != org.Y ) )
+ {
+ int count = list.Count;
+ int i;
+ int climb = count / 2;
+ if ( climb > 3 )
+ climb = 3;
+
+ for ( i = 0; i < climb; i++ )
+ {
+ p = ((Point3D)list[i]);
+ p.Z += (i+1) * 4;
+ list[i] = p;
+ }
+
+ for ( ; i < count - climb; i++ )
+ {
+ p = ((Point3D)list[i]);
+ p.Z += 16;
+ list[i] = p;
+ }
+
+ for ( i = climb; i > 0; i-- )
+ {
+ p = ((Point3D)list[i]);
+ p.Z += i * 4;
+ list[i] = p;
+ }
+ }*/
+
+ if ( dist2d > 1 )
+ {
+ int count = list.Count;
+ double height = count * 2 * ( Utility.RandomDouble() * 0.40 + 0.10 ); // 10 - 50%
+ double coeff = ( -height / ( (count*count)/4.0 ) );
+
+ for ( int i = 0; i < count; i++ )
+ {
+ p = ((Point3D)list[i]);
+
+ int xp = ( i - (count / 2) );
+
+ p.Z += (int)Math.Ceiling( coeff * xp * xp + height );
+
+ list[i] = p;
+ }
+ }
+
+ m_Path.Clear();
+ for (int i = 0; i < list.Count; i++)
+ m_Path.Add( (Point3D)list[i] );
+
+ m_PathIdx = 0;
+
+ ContinueFlight();
+ }
+
+ private void ContinueFlight()
+ {
+ int height;
+ bool found = false;
+
+ if ( m_PathIdx < m_Path.Count && this.Map != null && this.Map.Tiles != null && this.Map != Map.Internal )
+ {
+ int pathCheckEnd = m_PathIdx + 5;
+
+ if ( m_Path.Count < pathCheckEnd )
+ pathCheckEnd = m_Path.Count;
+
+ this.Visible = false;
+
+ if ( m_PathIdx > 0 ) // move to the next location
+ this.MoveToWorld( m_Path[m_PathIdx - 1] );
+
+ Point3D pTop = new Point3D( this.GetWorldLocation() ), pBottom = new Point3D( m_Path[pathCheckEnd-1] );
+ Utility.FixPoints( ref pTop, ref pBottom );
+
+ for ( int i = m_PathIdx; i < pathCheckEnd; i++ )
+ {
+ Point3D point = m_Path[i];
+
+ LandTile landTile = this.Map.Tiles.GetLandTile( point.X, point.Y );
+ int landZ = 0, landAvg = 0, landTop = 0;
+ this.Map.GetAverageZ( point.X, point.Y, ref landZ, ref landAvg, ref landTop );
+
+ if ( landZ <= point.Z && landTop >= point.Z && !landTile.Ignored )
+ {
+ HitObject( point, landTop, 0 );
+ return;
+ }
+
+ StaticTile[] statics = this.Map.Tiles.GetStaticTiles( point.X, point.Y, true );
+
+ if ( landTile.ID == 0x244 && statics.Length == 0 ) // 0x244 = invalid land tile
+ {
+ bool empty = true;
+ IPooledEnumerable eable = this.Map.GetItemsInRange( point, 0 );
+
+ foreach ( Item item in eable )
+ {
+ if ( item != this )
+ {
+ empty = false;
+ break;
+ }
+ }
+
+ eable.Free();
+
+ if ( empty )
+ {
+ HitObject( point, landTop, 0 );
+ return;
+ }
+ }
+
+ for ( int j = 0; j < statics.Length; j++ )
+ {
+ StaticTile t = statics[j];
+
+ ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue];
+ height = id.CalcHeight;
+
+ if ( t.Z <= point.Z && t.Z + height >= point.Z && ( id.Flags & ( TileFlag.Impassable | TileFlag.Wall | TileFlag.NoShoot ) ) != 0 )
+ {
+ if ( i > m_PathIdx )
+ point = m_Path[i-1];
+ else
+ point = this.GetWorldLocation();
+ HitObject( point, t.Z, height );
+ return;
+ }
+ }
+ }
+
+ Rectangle2D rect = new Rectangle2D( pTop.X, pTop.Y, ( pBottom.X - pTop.X ) + 1, ( pBottom.Y - pTop.Y ) + 1 );
+
+ IPooledEnumerable area = this.Map.GetItemsInBounds( rect );
+ foreach ( Item i in area )
+ {
+ if ( i == this || i.ItemID >= 0x4000 )
+ continue;
+
+ if ( i is BRGoal )
+ {
+ height = 17;
+ }
+ else if ( i is Blocker )
+ {
+ height = 20;
+ }
+ else
+ {
+ ItemData id = i.ItemData;
+ if ( ( id.Flags & (TileFlag.Impassable | TileFlag.Wall | TileFlag.NoShoot)) == 0 )
+ continue;
+ height = id.CalcHeight;
+ }
+
+ Point3D point = i.Location;
+ Point3D loc = i.Location;
+ for ( int j = m_PathIdx; j < pathCheckEnd; j++ )
+ {
+ point = m_Path[j];
+
+ if ( loc.X == point.X && loc.Y == point.Y &&
+ ( (i is Blocker ) || ( loc.Z <= point.Z && loc.Z + height >= point.Z ) ) )
+ {
+ found = true;
+ if ( j > m_PathIdx )
+ point = m_Path[j-1];
+ else
+ point = this.GetWorldLocation();
+ break;
+ }
+ }
+
+ if ( !found )
+ continue;
+
+ area.Free();
+ if ( i is BRGoal )
+ {
+ Point3D oldLoc = new Point3D( this.GetWorldLocation() );
+ if ( CheckScore( (BRGoal)i, m_Thrower, 3 ) )
+ DoAnim( oldLoc, point, this.Map );
+ else
+ HitObject( point, loc.Z, height );
+ }
+ else
+ {
+ HitObject( point, loc.Z, height );
+ }
+ return;
+ }
+
+ area.Free();
+
+ area = this.Map.GetClientsInBounds( rect );
+ foreach ( NetState ns in area )
+ {
+ Mobile m = ns.Mobile;
+
+ if ( m == null || m == m_Thrower )
+ continue;
+
+ Point3D point;
+ Point3D loc = m.Location;
+
+ for ( int j = m_PathIdx; j < pathCheckEnd && !found; j++ )
+ {
+ point = m_Path[j];
+
+ if ( loc.X == point.X && loc.Y == point.Y &&
+ loc.Z <= point.Z && loc.Z + 16 >= point.Z )
+ {
+ found = CheckCatch( m, point );
+ }
+ }
+
+ if ( !found )
+ continue;
+
+ area.Free();
+
+ // TODO: probably need to change this a lot...
+ DoCatch( m );
+
+ return;
+ }
+
+ area.Free();
+
+ m_PathIdx = pathCheckEnd;
+
+ if ( m_PathIdx > 0 && m_PathIdx - 1 < m_Path.Count )
+ DoAnim( this.GetWorldLocation(), m_Path[m_PathIdx - 1], this.Map );
+
+ Timer.DelayCall( TimeSpan.FromSeconds( 0.1 ), new TimerCallback( ContinueFlight ) ).Start();
+ }
+ else
+ {
+ if ( m_PathIdx > 0 && m_PathIdx - 1 < m_Path.Count )
+ this.MoveToWorld( m_Path[m_PathIdx - 1] );
+ else if ( m_Path.Count > 0 )
+ this.MoveToWorld( m_Path.Last );
+
+ int myZ = this.Map.GetAverageZ( this.X, this.Y );
+
+ StaticTile[] statics = this.Map.Tiles.GetStaticTiles( this.X, this.Y, true );
+ for ( int j = 0; j < statics.Length; j++ )
+ {
+ StaticTile t = statics[j];
+
+ ItemData id = TileData.ItemTable[t.ID & TileData.MaxItemValue];
+ height = id.CalcHeight;
+
+ if ( t.Z + height > myZ && t.Z + height <= this.Z )
+ myZ = t.Z + height;
+ }
+
+ IPooledEnumerable eable = this.GetItemsInRange( 0 );
+ foreach ( Item item in eable )
+ {
+ if ( item.Visible && item != this )
+ {
+ height = item.ItemData.CalcHeight;
+ if ( item.Z + height > myZ && item.Z + height <= this.Z )
+ myZ = item.Z + height;
+ }
+ }
+ eable.Free();
+
+ this.Z = myZ;
+ m_Flying = false;
+ this.Visible = true;
+
+ m_Path.Clear();
+ m_PathIdx = 0;
+ }
+ }
+
+ public Mobile Thrower { get { return m_Thrower; } }
+
+ public bool CheckScore( BRGoal goal, Mobile m, int points )
+ {
+ if ( m_Game == null || m == null || goal == null )
+ return false;
+
+ BRTeamInfo team = m_Game.GetTeamInfo( m );
+ if ( team == null || goal.Team == null || team == goal.Team )
+ return false;
+
+ if ( points > 3 )
+ m_Game.Alert( "Touchdown {0} ({1})!", team.Name, m.Name );
+ else
+ m_Game.Alert( "Field goal {0} ({1})!", team.Name, m.Name );
+
+ for (int i = m_Helpers.Count - 1; i >= 0; i--)
+ {
+ Mobile mob = (Mobile)m_Helpers[i];
+
+ BRPlayerInfo pi = team[mob];
+ if ( pi != null )
+ {
+ if ( mob == m )
+ pi.Captures += points;
+
+ pi.Score += points + 1;
+
+ points /= 2;
+ }
+ }
+
+ m_Game.ReturnBomb();
+
+ m_Flying = false;
+ this.Visible = true;
+ m_Path.Clear();
+ m_PathIdx = 0;
+
+ Target.Cancel( m );
+
+ return true;
+ }
+
+ private bool TakeBomb( Mobile m, BRTeamInfo team, string verb )
+ {
+ if ( !m.Player || !m.Alive || m.NetState == null )
+ return false;
+
+ if ( m.PlaceInBackpack( this ) )
+ {
+ m.RevealingAction();
+
+ m.LocalOverheadMessage( MessageType.Regular, 0x59, false, "You got the bomb!" );
+ m_Game.Alert( "{1} ({2}) {0} the bomb!", verb, m.Name, team.Name );
+
+ m.Target = new BombTarget( this, m );
+
+ if ( m_Helpers.Contains( m ) )
+ m_Helpers.Remove( m );
+
+ if ( m_Helpers.Count > 0 )
+ {
+ Mobile last = (Mobile)m_Helpers[0];
+
+ if ( m_Game.GetTeamInfo( last ) != team )
+ m_Helpers.Clear();
+ }
+
+ m_Helpers.Add( m );
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ public class BRGoal : BaseAddon
+ {
+ private bool m_North = false;
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public bool North { get { return m_North; } set { m_North = value; Remake(); } }
+
+ private static AddonComponent SetHue( AddonComponent ac, int hue )
+ {
+ ac.Hue = hue;
+ return ac;
+ }
+
+ private void Remake()
+ {
+ foreach ( AddonComponent ac in this.Components )
+ {
+ ac.Addon = null;
+ ac.Delete();
+ }
+
+ this.Components.Clear();
+
+ // stairs
+ this.AddComponent( new AddonComponent( 0x74D ), -1, +1, -5 );
+ this.AddComponent( new AddonComponent( 0x71F ), 0, +1, -5 );
+ this.AddComponent( new AddonComponent( 0x74B ), +1, +1, -5 );
+ this.AddComponent( new AddonComponent( 0x736 ), +1, 0, -5 );
+ this.AddComponent( new AddonComponent( 0x74C ), +1, -1, -5 );
+ this.AddComponent( new AddonComponent( 0x737 ), 0, -1, -5 );
+ this.AddComponent( new AddonComponent( 0x74A ), -1, -1, -5 );
+ this.AddComponent( new AddonComponent( 0x749 ), -1, 0, -5 );
+
+ // Center Sparkle
+ this.AddComponent( new AddonComponent( 0x375A ), 0, 0, -1 );
+
+ if ( !m_North )
+ {
+ // Pillars
+ this.AddComponent( new AddonComponent( 0x0CE ), 0, +1, -2 );
+ this.AddComponent( new AddonComponent( 0x0CC ), 0, -1, -2 );
+ this.AddComponent( new AddonComponent( 0x0D0 ), 0, 0, -2 );
+
+ // Yellow parts
+ this.AddComponent( SetHue( new AddonComponent( 0x0DF ), 0x499 ), 0, +1, 7 );
+ this.AddComponent( SetHue( new AddonComponent( 0x0DF ), 0x499 ), 0, 0, 16 );
+ this.AddComponent( SetHue( new AddonComponent( 0x0DF ), 0x499 ), 0, -1, 7 );
+
+ // Blue Sparkles
+ this.AddComponent( SetHue( new AddonComponent( 0x377A ), 0x84C ), 0, +1, 12 );
+ this.AddComponent( SetHue( new AddonComponent( 0x377A ), 0x84C ), 0, +1, -1 );
+ this.AddComponent( SetHue( new AddonComponent( 0x377A ), 0x84C ), 0, -1, 12 );
+ this.AddComponent( SetHue( new AddonComponent( 0x377A ), 0x84C ), 0, -1, -1 );
+ }
+ else
+ {
+ // Pillars
+ this.AddComponent( new AddonComponent( 0x0CF ), +1, 0, -2 );
+ this.AddComponent( new AddonComponent( 0x0CC ), -1, 0, -2 );
+ this.AddComponent( new AddonComponent( 0x0D1 ), 0, 0, -2 );
+
+ // Yellow parts
+ this.AddComponent( SetHue( new AddonComponent( 0x0DF ), 0x499 ), +1, 0, 7 );
+ this.AddComponent( SetHue( new AddonComponent( 0x0DF ), 0x499 ), 0, 0, 16 );
+ this.AddComponent( SetHue( new AddonComponent( 0x0DF ), 0x499 ), -1, 0, 7 );
+
+ // Blue Sparkles
+ this.AddComponent( SetHue( new AddonComponent( 0x377A ), 0x84C ), +1, 0, 12 );
+ this.AddComponent( SetHue( new AddonComponent( 0x377A ), 0x84C ), +1, 0, -1 );
+ this.AddComponent( SetHue( new AddonComponent( 0x377A ), 0x84C ), -1, 0, 12 );
+ this.AddComponent( SetHue( new AddonComponent( 0x377A ), 0x84C ), -1, 0, -1 );
+ }
+ }
+
+ [Constructable]
+ public BRGoal()
+ {
+ Name = "Bombing Run Goal";
+
+ this.ItemID = 0x51D;
+ this.Hue = 0x84C;
+ this.Visible = true;
+
+ Remake();
+ }
+
+ public BRGoal( Serial serial ) : base( serial )
+ {
+ }
+
+ public override void Serialize(GenericWriter writer)
+ {
+ base.Serialize (writer);
+
+ writer.Write( (int)1 ); // version
+
+ writer.Write( m_North );
+ }
+
+ public override void Deserialize(GenericReader reader)
+ {
+ base.Deserialize (reader);
+
+ int version = reader.ReadInt();
+
+ switch ( version )
+ {
+ case 1:
+ {
+ m_North = reader.ReadBool();
+ goto case 0;
+ }
+ case 0:
+ {
+ break;
+ }
+ }
+
+ this.Hue = 0x84C;
+ }
+
+ public override bool ShareHue{ get{ return false; } }
+
+ public BRTeamInfo Team
+ {
+ get { return m_Team; }
+ set
+ {
+ m_Team = value;
+ if ( m_Team != null && m_Team.Color != 0 )
+ this.Hue = m_Team.Color;
+ else
+ this.Hue = 0x84C;
+ }
+ }
+
+ private BRTeamInfo m_Team;
+
+ public override bool OnMoveOver( Mobile m )
+ {
+ if ( !Visible )
+ return true;
+
+ if ( m == null || !m.Player || !m.Alive || m.Backpack == null || m_Team == null || m_Team.Game == null )
+ return true;
+
+ if ( !base.OnMoveOver( m ) )
+ return false;
+
+ if ( m_Team != null && m_Team.Color != 0 )
+ this.Hue = m_Team.Color;
+ else
+ this.Hue = 0x84C;
+
+ BRBomb b = m.Backpack.FindItemByType( typeof( BRBomb ), true ) as BRBomb;
+
+ if ( b != null )
+ b.CheckScore( this, m, 7 );
+
+ return true;
+ }
+ }
+
+ public sealed class BRBoard : Item
+ {
+ public BRTeamInfo m_TeamInfo;
+
+ [Constructable]
+ public BRBoard()
+ : base( 7774 )
+ {
+ Name = "Scoreboard";
+ Movable = false;
+ }
+
+ public override void OnDoubleClick( Mobile from )
+ {
+ if ( m_TeamInfo != null && m_TeamInfo.Game != null )
+ {
+ from.CloseGump( typeof( BRBoardGump ) );
+ from.SendGump( new BRBoardGump( from, m_TeamInfo.Game ) );
+ }
+ }
+
+ public BRBoard( Serial serial )
+ : base( serial )
+ {
+ }
+
+ public override void Serialize( GenericWriter writer )
+ {
+ base.Serialize( writer );
+
+ writer.Write( (int) 0 );
+ }
+
+ public override void Deserialize( GenericReader reader )
+ {
+ base.Deserialize( reader );
+
+ int version = reader.ReadInt();
+ }
+ }
+
+ public class BRBoardGump : Gump
+ {
+ 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 );
+ }
+
+ private const int LabelColor32 = 0xFFFFFF;
+ private const int BlackColor32 = 0x000000;
+
+ private BRGame m_Game;
+
+ public BRBoardGump( Mobile mob, BRGame game )
+ : this( mob, game, null )
+ {
+ }
+
+ public BRBoardGump( Mobile mob, BRGame game, BRTeamInfo section )
+ : base( 60, 60 )
+ {
+ m_Game = game;
+
+ BRTeamInfo ourTeam = game.GetTeamInfo( mob );
+
+ ArrayList entries = new ArrayList();
+
+ if ( section == null )
+ {
+ for ( int i = 0; i < game.Context.Participants.Count; ++i )
+ {
+ BRTeamInfo teamInfo = game.Controller.TeamInfo[i % game.Controller.TeamInfo.Length];
+
+ if ( teamInfo == null )
+ continue;
+
+ entries.Add( teamInfo );
+ }
+ }
+ else
+ {
+ foreach ( BRPlayerInfo player in section.Players.Values )
+ {
+ if ( player.Score > 0 )
+ entries.Add( player );
+ }
+ }
+
+ entries.Sort();
+ /*
+ delegate( IRankedCTF a, IRankedCTF b )
+ {
+ return b.Score - a.Score;
+ } );*/
+
+ int height = 0;
+
+ if ( section == null )
+ height = 73 + ( entries.Count * 75 ) + 28;
+
+ Closable = false;
+
+ AddPage( 0 );
+
+ AddBackground( 1, 1, 398, height, 3600 );
+
+ AddImageTiled( 16, 15, 369, height - 29, 3604 );
+
+ for ( int i = 0; i < entries.Count; i += 1 )
+ AddImageTiled( 22, 58 + ( i * 75 ), 357, 70, 0x2430 );
+
+ AddAlphaRegion( 16, 15, 369, height - 29 );
+
+ AddImage( 215, -45, 0xEE40 );
+ //AddImage( 330, 141, 0x8BA );
+
+ AddBorderedText( 22, 22, 294, 20, Center( "BR Scoreboard" ), LabelColor32, BlackColor32 );
+
+ AddImageTiled( 32, 50, 264, 1, 9107 );
+ AddImageTiled( 42, 52, 264, 1, 9157 );
+
+ if ( section == null )
+ {
+ for ( int i = 0; i < entries.Count; ++i )
+ {
+ BRTeamInfo teamInfo = entries[i] as BRTeamInfo;
+
+ AddImage( 30, 70 + ( i * 75 ), 10152 );
+ AddImage( 30, 85 + ( i * 75 ), 10151 );
+ AddImage( 30, 100 + ( i * 75 ), 10151 );
+ AddImage( 30, 106 + ( i * 75 ), 10154 );
+
+ AddImage( 24, 60 + ( i * 75 ), teamInfo == ourTeam ? 9730 : 9727, teamInfo.Color - 1 );
+
+ int nameColor = LabelColor32;
+ int borderColor = BlackColor32;
+
+ switch ( teamInfo.Color )
+ {
+ case 0x47E:
+ nameColor = 0xFFFFFF;
+ break;
+
+ case 0x4F2:
+ nameColor = 0x3399FF;
+ break;
+
+ case 0x4F7:
+ nameColor = 0x33FF33;
+ break;
+
+ case 0x4FC:
+ nameColor = 0xFF00FF;
+ break;
+
+ case 0x021:
+ nameColor = 0xFF3333;
+ break;
+
+ case 0x01A:
+ nameColor = 0xFF66FF;
+ break;
+
+ case 0x455:
+ nameColor = 0x333333;
+ borderColor = 0xFFFFFF;
+ break;
+ }
+
+ AddBorderedText( 60, 65 + ( i * 75 ), 250, 20, String.Format( "{0}: {1}", LadderGump.Rank( 1 + i ), teamInfo.Name ), nameColor, borderColor );
+
+ AddBorderedText( 50 + 10, 85 + ( i * 75 ), 100, 20, "Score:", 0xFFC000, BlackColor32 );
+ AddBorderedText( 50 + 15, 105 + ( i * 75 ), 100, 20, teamInfo.Score.ToString( "N0" ), 0xFFC000, BlackColor32 );
+
+ AddBorderedText( 110 + 10, 85 + ( i * 75 ), 100, 20, "Kills:", 0xFFC000, BlackColor32 );
+ AddBorderedText( 110 + 15, 105 + ( i * 75 ), 100, 20, teamInfo.Kills.ToString( "N0" ), 0xFFC000, BlackColor32 );
+
+ AddBorderedText( 160 + 10, 85 + ( i * 75 ), 100, 20, "Points:", 0xFFC000, BlackColor32 );
+ AddBorderedText( 160 + 15, 105 + ( i * 75 ), 100, 20, teamInfo.Captures.ToString( "N0" ), 0xFFC000, BlackColor32 );
+
+ BRPlayerInfo pl = teamInfo.Leader;
+
+ AddBorderedText( 235 + 10, 85 + ( i * 75 ), 250, 20, "Leader:", 0xFFC000, BlackColor32 );
+
+ if ( pl != null )
+ AddBorderedText( 235 + 15, 105 + ( i * 75 ), 250, 20, pl.Player.Name, 0xFFC000, BlackColor32 );
+ }
+ }
+ else
+ {
+ }
+
+ AddButton( 314, height - 42, 247, 248, 1, GumpButtonType.Reply, 0 );
+ }
+ }
+
+ public sealed class BRPlayerInfo : IRankedCTF, IComparable
+ {
+ private BRTeamInfo m_TeamInfo;
+
+ private Mobile m_Player;
+
+ private int m_Kills;
+ private int m_Captures;
+
+ private int m_Score;
+
+ public Mobile Player { get { return m_Player; } }
+
+ public int CompareTo( object obj )
+ {
+ BRPlayerInfo pi = (BRPlayerInfo)obj;
+ int res = pi.Captures.CompareTo( this.Captures );
+ if ( res == 0 )
+ {
+ res = pi.Score.CompareTo( this.Score );
+
+ if ( res == 0 )
+ res = pi.Kills.CompareTo( this.Kills );
+ }
+ return res;
+ }
+
+ public string Name
+ {
+ get { return m_Player.Name; }
+ }
+
+ public int Kills
+ {
+ get
+ {
+ return m_Kills;
+ }
+ set
+ {
+ m_TeamInfo.Kills += ( value - m_Kills );
+ m_Kills = value;
+ }
+ }
+
+ public int Captures
+ {
+ get
+ {
+ return m_Captures;
+ }
+ set
+ {
+ m_TeamInfo.Captures += ( value - m_Captures );
+ m_Captures = value;
+ }
+ }
+
+ public int Score
+ {
+ get
+ {
+ return m_Score;
+ }
+ set
+ {
+ m_TeamInfo.Score += ( value - m_Score );
+ m_Score = value;
+
+ if ( m_TeamInfo.Leader == null || m_Score > m_TeamInfo.Leader.Score )
+ m_TeamInfo.Leader = this;
+ }
+ }
+
+ public BRPlayerInfo( BRTeamInfo teamInfo, Mobile player )
+ {
+ m_TeamInfo = teamInfo;
+ m_Player = player;
+ }
+ }
+
+ [PropertyObject]
+ public sealed class BRTeamInfo : IRankedCTF, IComparable
+ {
+ private BRGame m_Game;
+ private int m_TeamID;
+
+ private int m_Color;
+ private string m_Name;
+
+ private BRBoard m_Board;
+ private BRGoal m_Goal;
+
+ private int m_Kills;
+ private int m_Captures;
+
+ private int m_Score;
+
+ private Hashtable m_Players;
+
+ public int CompareTo( object obj )
+ {
+ BRTeamInfo ti = (BRTeamInfo)obj;
+ int res = ti.Captures.CompareTo( this.Captures );
+ if ( res == 0 )
+ {
+ res = ti.Score.CompareTo( this.Score );
+
+ if ( res == 0 )
+ res = ti.Kills.CompareTo( this.Kills );
+ }
+ return res;
+ }
+
+ public string Name
+ {
+ get { return String.Format( "{0} Team", m_Name ); }
+ }
+
+ public BRGame Game { get { return m_Game; } set { m_Game = value; } }
+ public int TeamID { get { return m_TeamID; } }
+
+ public int Kills { get { return m_Kills; } set { m_Kills = value; } }
+ public int Captures { get { return m_Captures; } set { m_Captures = value; } }
+
+ public int Score { get { return m_Score; } set { m_Score = value; } }
+
+ private BRPlayerInfo m_Leader;
+
+ public BRPlayerInfo Leader
+ {
+ get { return m_Leader; }
+ set { m_Leader = value; }
+ }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public BRBoard Board
+ {
+ get { return m_Board; }
+ set { m_Board = value; }
+ }
+
+ public Hashtable Players
+ {
+ get { return m_Players; }
+ }
+
+ public BRPlayerInfo this[Mobile mob]
+ {
+ get
+ {
+ if ( mob == null )
+ return null;
+
+ BRPlayerInfo val = m_Players[mob] as BRPlayerInfo;
+
+ if ( val == null )
+ m_Players[mob] = val = new BRPlayerInfo( this, mob );
+
+ return val;
+ }
+ }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public int Color
+ {
+ get { return m_Color; }
+ set { m_Color = value; }
+ }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public string TeamName
+ {
+ get { return m_Name; }
+ set { m_Name = value; }
+ }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public BRGoal Goal
+ {
+ get { return m_Goal; }
+ set
+ {
+ m_Goal = value;
+ if ( m_Goal != null )
+ m_Goal.Team = this;
+ }
+ }
+
+ public BRTeamInfo( int teamID )
+ {
+ m_TeamID = teamID;
+ m_Players = new Hashtable();
+ }
+
+ public void Reset()
+ {
+ m_Kills = 0;
+ m_Captures = 0;
+ m_Score = 0;
+
+ m_Leader = null;
+
+ m_Players.Clear();
+
+ if ( m_Board != null )
+ m_Board.m_TeamInfo = this;
+ if ( m_Goal != null )
+ m_Goal.Team = this;
+ }
+
+ public BRTeamInfo( int teamID, GenericReader ip )
+ {
+ m_TeamID = teamID;
+ m_Players = new Hashtable();
+
+ int version = ip.ReadEncodedInt();
+
+ switch ( version )
+ {
+ case 0:
+ {
+ m_Board = ip.ReadItem() as BRBoard;
+ m_Name = ip.ReadString();
+ m_Color = ip.ReadEncodedInt();
+ m_Goal = ip.ReadItem() as BRGoal;
+ break;
+ }
+ }
+ }
+
+ public void Serialize( GenericWriter op )
+ {
+ op.WriteEncodedInt( 0 ); // version
+
+ op.Write( m_Board );
+
+ op.Write( m_Name );
+
+ op.WriteEncodedInt( m_Color );
+
+ op.Write( m_Goal );
+ }
+
+ public override string ToString()
+ {
+ if ( m_Name != null )
+ return String.Format( "({0}) ...", this.Name );
+ else
+ return "...";
+ }
+ }
+
+ public sealed class BRController : EventController
+ {
+ private BRTeamInfo[] m_TeamInfo;
+ private TimeSpan m_Duration;
+ private Point3D m_BombHome;
+
+ public BRTeamInfo[] TeamInfo { get { return m_TeamInfo; } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public BRTeamInfo Team1 { get { return m_TeamInfo[0]; } set { } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public BRTeamInfo Team2 { get { return m_TeamInfo[1]; } set { } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public BRTeamInfo Team3 { get { return m_TeamInfo[2]; } set { } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public BRTeamInfo Team4 { get { return m_TeamInfo[3]; } set { } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public TimeSpan Duration
+ {
+ get { return m_Duration; }
+ set { m_Duration = value; }
+ }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public Point3D BombHome
+ {
+ get { return m_BombHome; }
+ set { m_BombHome = value; }
+ }
+
+ public override string Title
+ {
+ get { return "Bombing Run"; }
+ }
+
+ public override string GetTeamName( int teamID )
+ {
+ return m_TeamInfo[teamID % m_TeamInfo.Length].Name;
+ }
+
+ public override EventGame Construct( DuelContext context )
+ {
+ return new BRGame( this, context );
+ }
+
+ [Constructable]
+ public BRController()
+ {
+ Visible = false;
+ Movable = false;
+
+ Name = "Bombing Run Controller";
+
+ m_Duration = TimeSpan.FromMinutes( 30.0 );
+
+ m_BombHome = Point3D.Zero;
+
+ m_TeamInfo = new BRTeamInfo[4];
+
+ for ( int i = 0; i < m_TeamInfo.Length; ++i )
+ m_TeamInfo[i] = new BRTeamInfo( i );
+ }
+
+ public BRController( Serial serial )
+ : base( serial )
+ {
+ }
+
+ public override void Serialize( GenericWriter writer )
+ {
+ base.Serialize( writer );
+
+ writer.Write( (int) 0 );
+
+ writer.Write( m_BombHome );
+
+ writer.Write( m_Duration );
+
+ writer.WriteEncodedInt( m_TeamInfo.Length );
+
+ for ( int i = 0; i < m_TeamInfo.Length; ++i )
+ m_TeamInfo[i].Serialize( writer );
+ }
+
+ public override void Deserialize( GenericReader reader )
+ {
+ base.Deserialize( reader );
+
+ int version = reader.ReadInt();
+
+ switch ( version )
+ {
+ case 0:
+ {
+ m_BombHome = reader.ReadPoint3D();
+
+ m_Duration = reader.ReadTimeSpan();
+
+ m_TeamInfo = new BRTeamInfo[reader.ReadEncodedInt()];
+
+ for ( int i = 0; i < m_TeamInfo.Length; ++i )
+ m_TeamInfo[i] = new BRTeamInfo( i, reader );
+
+ break;
+ }
+ }
+ }
+ }
+
+ public sealed class BRGame : EventGame
+ {
+ public override bool CantDoAnything( Mobile mob )
+ {
+ if ( mob == null || mob.Backpack == null || GetTeamInfo( mob ) == null )
+ return false;
+
+ Item bomb = mob.Backpack.FindItemByType( typeof( BRBomb ), true );
+
+ if ( bomb != null )
+ return true;
+
+ return false;
+ }
+
+ private BRBomb m_Bomb;
+
+ private TimerCallback m_UnhideCallback = null;
+
+ public void ReturnBomb()
+ {
+ if ( m_Bomb != null && m_Controller != null )
+ {
+ if ( m_UnhideCallback == null )
+ m_UnhideCallback = new TimerCallback( UnhideBomb );
+ m_Bomb.Visible = false;
+ m_Bomb.MoveToWorld( m_Controller.BombHome, m_Controller.Map );
+ Timer.DelayCall( TimeSpan.FromSeconds( Utility.RandomMinMax( 5, 15 ) ), m_UnhideCallback );
+ }
+ }
+
+ private void UnhideBomb()
+ {
+ if ( m_Bomb != null )
+ {
+ m_Bomb.Visible = true;
+ m_Bomb.OnLocationChange( m_Bomb.Location );
+ }
+ }
+
+ private BRController m_Controller;
+
+ public BRController Controller { get { return m_Controller; } }
+
+ public void Alert( string text )
+ {
+ if ( m_Context.m_Tournament != null )
+ m_Context.m_Tournament.Alert( text );
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ {
+ Participant p = m_Context.Participants[i] as Participant;
+
+ for ( int j = 0; j < p.Players.Length; ++j )
+ {
+ if ( p.Players[j] != null )
+ p.Players[j].Mobile.SendMessage( 0x35, text );
+ }
+ }
+ }
+
+ public void Alert( string format, params object[] args )
+ {
+ Alert( String.Format( format, args ) );
+ }
+
+ public BRGame( BRController controller, DuelContext context ) : base( context )
+ {
+ m_Controller = controller;
+ }
+
+ public Map Facet
+ {
+ get
+ {
+ if ( m_Context.Arena != null )
+ return m_Context.Arena.Facet;
+
+ return m_Controller.Map;
+ }
+ }
+
+ public BRTeamInfo GetTeamInfo( Mobile mob )
+ {
+ int teamID = GetTeamID( mob );
+
+ if ( teamID >= 0 )
+ return m_Controller.TeamInfo[teamID % m_Controller.TeamInfo.Length];
+
+ return null;
+ }
+
+ public int GetTeamID( Mobile mob )
+ {
+ PlayerMobile pm = mob as PlayerMobile;
+
+ if ( pm == null )
+ {
+ if ( mob is BaseCreature )
+ return ((BaseCreature)mob).Team - 1;
+ else
+ return -1;
+ }
+
+ if ( pm.DuelContext == null || pm.DuelContext != m_Context )
+ return -1;
+
+ if ( pm.DuelPlayer == null || pm.DuelPlayer.Eliminated )
+ return -1;
+
+ return pm.DuelContext.Participants.IndexOf( pm.DuelPlayer.Participant );
+ }
+
+ public int GetColor( Mobile mob )
+ {
+ BRTeamInfo teamInfo = GetTeamInfo( mob );
+
+ if ( teamInfo != null )
+ return teamInfo.Color;
+
+ return -1;
+ }
+
+ private void ApplyHues( Participant p, int hueOverride )
+ {
+ for ( int i = 0; i < p.Players.Length; ++i )
+ {
+ if ( p.Players[i] != null )
+ p.Players[i].Mobile.SolidHueOverride = hueOverride;
+ }
+ }
+
+ public void DelayBounce( TimeSpan ts, Mobile mob, Container corpse )
+ {
+ Timer.DelayCall( ts, new TimerStateCallback( DelayBounce_Callback ), new object[] { mob, corpse } );
+ }
+
+ private void DelayBounce_Callback( object state )
+ {
+ object[] states = (object[]) state;
+ Mobile mob = (Mobile) states[0];
+ Container corpse = (Container) states[1];
+
+ DuelPlayer dp = null;
+
+ if ( mob is PlayerMobile )
+ dp = ( mob as PlayerMobile ).DuelPlayer;
+
+ m_Context.RemoveAggressions( mob );
+
+ if ( dp != null && !dp.Eliminated )
+ mob.MoveToWorld( m_Context.Arena.GetBaseStartPoint( GetTeamID( mob ) ), Facet );
+ else
+ m_Context.SendOutside( mob );
+
+ m_Context.Refresh( mob, corpse );
+ DuelContext.Debuff( mob );
+ DuelContext.CancelSpell( mob );
+ mob.Frozen = false;
+ }
+
+ public override bool OnDeath( Mobile mob, Container corpse )
+ {
+ Mobile killer = mob.FindMostRecentDamager( false );
+
+ bool hadBomb = false;
+
+ Item[] bombs = corpse.FindItemsByType( typeof( BRBomb ), false );
+
+ for ( int i = 0; i < bombs.Length; ++i )
+ ( bombs[i] as BRBomb ).DropTo( mob, killer );
+
+ hadBomb = ( hadBomb || bombs.Length > 0 );
+
+ if ( mob.Backpack != null )
+ {
+ bombs = mob.Backpack.FindItemsByType( typeof( BRBomb ), false );
+
+ for ( int i = 0; i < bombs.Length; ++i )
+ ( bombs[i] as BRBomb ).DropTo( mob, killer );
+
+ hadBomb = ( hadBomb || bombs.Length > 0 );
+ }
+
+ if ( killer != null && killer.Player )
+ {
+ BRTeamInfo teamInfo = GetTeamInfo( killer );
+ BRTeamInfo victInfo = GetTeamInfo( mob );
+
+ if ( teamInfo != null && teamInfo != victInfo )
+ {
+ BRPlayerInfo playerInfo = teamInfo[killer];
+
+ if ( playerInfo != null )
+ {
+ playerInfo.Kills += 1;
+ playerInfo.Score += 1; // base frag
+
+ if ( hadBomb )
+ playerInfo.Score += 4; // fragged bomb carrier
+ }
+ }
+ }
+
+ mob.CloseGump( typeof( BRBoardGump ) );
+ mob.SendGump( new BRBoardGump( mob, this ) );
+
+ m_Context.Requip( mob, corpse );
+ DelayBounce( TimeSpan.FromSeconds( 30.0 ), mob, corpse );
+
+ return false;
+ }
+
+ private Timer m_FinishTimer;
+
+ public override void OnStart()
+ {
+ for ( int i = 0; i < m_Controller.TeamInfo.Length; ++i )
+ {
+ BRTeamInfo teamInfo = m_Controller.TeamInfo[i];
+
+ teamInfo.Game = this;
+ teamInfo.Reset();
+ }
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ ApplyHues( m_Context.Participants[i] as Participant, m_Controller.TeamInfo[i % m_Controller.TeamInfo.Length].Color );
+
+ if ( m_FinishTimer != null )
+ m_FinishTimer.Stop();
+
+ m_Bomb = new BRBomb( this );
+ ReturnBomb();
+
+ m_FinishTimer = Timer.DelayCall( m_Controller.Duration, new TimerCallback( Finish_Callback ) );
+ }
+
+ private void Finish_Callback()
+ {
+ ArrayList teams = new ArrayList();
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ {
+ BRTeamInfo teamInfo = m_Controller.TeamInfo[i % m_Controller.TeamInfo.Length];
+
+ if ( teamInfo == null )
+ continue;
+
+ teams.Add( teamInfo );
+ }
+
+ teams.Sort();
+
+ Tournament tourny = m_Context.m_Tournament;
+
+ StringBuilder sb = new StringBuilder();
+
+ if ( tourny != null && tourny.TournyType == TournyType.FreeForAll )
+ {
+ sb.Append( m_Context.Participants.Count * tourny.PlayersPerParticipant );
+ sb.Append( "-man FFA" );
+ }
+ else if ( tourny != null && tourny.TournyType == TournyType.RandomTeam )
+ {
+ sb.Append( tourny.ParticipantsPerMatch );
+ sb.Append( "-team" );
+ }
+ else if ( tourny != null && tourny.TournyType == TournyType.RedVsBlue )
+ {
+ sb.Append( "Red v Blue" );
+ }
+ else if ( tourny != null && tourny.TournyType == TournyType.Faction )
+ {
+ sb.Append( tourny.ParticipantsPerMatch );
+ sb.Append( "-team Faction" );
+ }
+ else if ( tourny != null )
+ {
+ for ( int i = 0; i < tourny.ParticipantsPerMatch; ++i )
+ {
+ if ( sb.Length > 0 )
+ sb.Append( 'v' );
+
+ sb.Append( tourny.PlayersPerParticipant );
+ }
+ }
+
+ if ( m_Controller != null )
+ sb.Append( ' ' ).Append( m_Controller.Title );
+
+ string title = sb.ToString();
+
+ BRTeamInfo winner = (BRTeamInfo)( teams.Count > 0 ? teams[0] : null );
+
+ for ( int i = 0; i < teams.Count; ++i )
+ {
+ TrophyRank rank = TrophyRank.Bronze;
+
+ if ( i == 0 )
+ rank = TrophyRank.Gold;
+ else if ( i == 1 )
+ rank = TrophyRank.Silver;
+
+ BRPlayerInfo leader = ((BRTeamInfo)teams[i]).Leader;
+
+ foreach ( BRPlayerInfo pl in ((BRTeamInfo)teams[i]).Players.Values )
+ {
+ Mobile mob = pl.Player;
+
+ if ( mob == null )
+ continue;
+
+ sb = new StringBuilder();
+
+ sb.Append( title );
+
+ if ( pl == leader )
+ sb.Append( " Leader" );
+
+ if ( pl.Score > 0 )
+ {
+ sb.Append( ": " );
+
+ //sb.Append( pl.Score.ToString( "N0" ) );
+ //sb.Append( pl.Score == 1 ? " point" : " points" );
+
+ sb.Append( pl.Kills.ToString( "N0" ) );
+ sb.Append( pl.Kills == 1 ? " kill" : " kills" );
+
+ if ( pl.Captures > 0 )
+ {
+ sb.Append( ", " );
+ sb.Append( pl.Captures.ToString( "N0" ) );
+ sb.Append( pl.Captures == 1 ? " point" : " points" );
+ }
+ }
+
+ Item item = new Trophy( sb.ToString(), rank );
+
+ if ( pl == leader )
+ item.ItemID = 4810;
+
+ item.Name = String.Format( "{0}, {1} team", item.Name, ((BRTeamInfo)teams[i]).Name.ToLower() );
+
+ if ( !mob.PlaceInBackpack( item ) )
+ mob.BankBox.DropItem( item );
+
+ int cash = pl.Score * 250;
+
+ 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() );
+ }
+ }
+ }
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ {
+ Participant p = m_Context.Participants[i] as Participant;
+
+ if ( p == null || p.Players == null )
+ continue;
+
+ for ( int j = 0; j < p.Players.Length; ++j )
+ {
+ DuelPlayer dp = p.Players[j];
+
+ if ( dp != null && dp.Mobile != null )
+ {
+ dp.Mobile.CloseGump( typeof( BRBoardGump ) );
+ dp.Mobile.SendGump( new BRBoardGump( dp.Mobile, this ) );
+ }
+ }
+
+ if ( i == winner.TeamID )
+ continue;
+
+ if ( p != null && p.Players != null )
+ {
+ for ( int j = 0; j < p.Players.Length; ++j )
+ {
+ if ( p.Players[j] != null )
+ p.Players[j].Eliminated = true;
+ }
+ }
+ }
+
+ m_Context.Finish( m_Context.Participants[winner.TeamID] as Participant );
+ }
+
+ public override void OnStop()
+ {
+ for ( int i = 0; i < m_Controller.TeamInfo.Length; ++i )
+ {
+ BRTeamInfo teamInfo = m_Controller.TeamInfo[i];
+
+ if ( teamInfo.Board != null )
+ teamInfo.Board.m_TeamInfo = null;
+
+ teamInfo.Game = null;
+ }
+
+ ReturnBomb();
+
+ if( m_Bomb != null )
+ m_Bomb.Delete();
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ ApplyHues( m_Context.Participants[i] as Participant, -1 );
+
+ if ( m_FinishTimer != null )
+ m_FinishTimer.Stop();
+
+ m_FinishTimer = null;
+ }
+ }
+}
diff --git a/Scripts/Engines/ConPVP/Games/CTF.cs b/Scripts/Engines/ConPVP/Games/CTF.cs
new file mode 100644
index 000000000..5e22ae4f3
--- /dev/null
+++ b/Scripts/Engines/ConPVP/Games/CTF.cs
@@ -0,0 +1,1332 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Server;
+using Server.Items;
+using Server.Mobiles;
+using Server.Network;
+using Server.Targeting;
+using Server.Gumps;
+
+namespace Server.Engines.ConPVP
+{
+ public sealed class CTFBoard : Item
+ {
+ public CTFTeamInfo m_TeamInfo;
+
+ public override string DefaultName
+ {
+ get { return "scoreboard"; }
+ }
+
+ [Constructable]
+ public CTFBoard()
+ : base( 7774 )
+ {
+ Movable = false;
+ }
+
+ public override void OnDoubleClick( Mobile from )
+ {
+ if ( m_TeamInfo != null && m_TeamInfo.Game != null )
+ {
+ from.CloseGump( typeof( CTFBoardGump ) );
+ from.SendGump( new CTFBoardGump( from, m_TeamInfo.Game ) );
+ }
+ }
+
+ public CTFBoard( Serial serial )
+ : base( serial )
+ {
+ }
+
+ public override void Serialize( GenericWriter writer )
+ {
+ base.Serialize( writer );
+
+ writer.Write( (int) 0 );
+ }
+
+ public override void Deserialize( GenericReader reader )
+ {
+ base.Deserialize( reader );
+
+ int version = reader.ReadInt();
+ }
+ }
+
+ public class CTFBoardGump : Gump
+ {
+ 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 );
+ }
+
+ private const int LabelColor32 = 0xFFFFFF;
+ private const int BlackColor32 = 0x000000;
+
+ private CTFGame m_Game;
+
+ public CTFBoardGump( Mobile mob, CTFGame game )
+ : this( mob, game, null )
+ {
+ }
+
+ public CTFBoardGump( Mobile mob, CTFGame game, CTFTeamInfo section )
+ : base( 60, 60 )
+ {
+ m_Game = game;
+
+ CTFTeamInfo ourTeam = game.GetTeamInfo( mob );
+
+ List entries = new List();
+
+ if ( section == null )
+ {
+ for ( int i = 0; i < game.Context.Participants.Count; ++i )
+ {
+ CTFTeamInfo teamInfo = game.Controller.TeamInfo[i % 8];
+
+ if ( teamInfo == null || teamInfo.Flag == null )
+ continue;
+
+ entries.Add( teamInfo );
+ }
+ }
+ else
+ {
+ foreach ( CTFPlayerInfo player in section.Players.Values )
+ {
+ if ( player.Score > 0 )
+ entries.Add( player );
+ }
+ }
+
+ entries.Sort( delegate( IRankedCTF a, IRankedCTF b )
+ {
+ return b.Score - a.Score;
+ } );
+
+ int height = 0;
+
+ if ( section == null )
+ height = 73 + ( entries.Count * 75 ) + 28;
+
+ Closable = false;
+
+ AddPage( 0 );
+
+ AddBackground( 1, 1, 398, height, 3600 );
+
+ AddImageTiled( 16, 15, 369, height - 29, 3604 );
+
+ for ( int i = 0; i < entries.Count; i += 1 )
+ AddImageTiled( 22, 58 + ( i * 75 ), 357, 70, 0x2430 );
+
+ AddAlphaRegion( 16, 15, 369, height - 29 );
+
+ AddImage( 215, -45, 0xEE40 );
+ //AddImage( 330, 141, 0x8BA );
+
+ AddBorderedText( 22, 22, 294, 20, Center( "CTF Scoreboard" ), LabelColor32, BlackColor32 );
+
+ AddImageTiled( 32, 50, 264, 1, 9107 );
+ AddImageTiled( 42, 52, 264, 1, 9157 );
+
+ if ( section == null )
+ {
+ for ( int i = 0; i < entries.Count; ++i )
+ {
+ CTFTeamInfo teamInfo = entries[i] as CTFTeamInfo;
+
+ AddImage( 30, 70 + ( i * 75 ), 10152 );
+ AddImage( 30, 85 + ( i * 75 ), 10151 );
+ AddImage( 30, 100 + ( i * 75 ), 10151 );
+ AddImage( 30, 106 + ( i * 75 ), 10154 );
+
+ AddImage( 24, 60 + ( i * 75 ), teamInfo == ourTeam ? 9730 : 9727, teamInfo.Color - 1 );
+
+ int nameColor = LabelColor32;
+ int borderColor = BlackColor32;
+
+ switch ( teamInfo.Color )
+ {
+ case 0x47E:
+ nameColor = 0xFFFFFF;
+ break;
+
+ case 0x4F2:
+ nameColor = 0x3399FF;
+ break;
+
+ case 0x4F7:
+ nameColor = 0x33FF33;
+ break;
+
+ case 0x4FC:
+ nameColor = 0xFF00FF;
+ break;
+
+ case 0x021:
+ nameColor = 0xFF3333;
+ break;
+
+ case 0x01A:
+ nameColor = 0xFF66FF;
+ break;
+
+ case 0x455:
+ nameColor = 0x333333;
+ borderColor = 0xFFFFFF;
+ break;
+ }
+
+ AddBorderedText( 60, 65 + ( i * 75 ), 250, 20, String.Format( "{0}: {1} Team", LadderGump.Rank( 1 + i ), teamInfo.Name ), nameColor, borderColor );
+
+ AddBorderedText( 50 + 10, 85 + ( i * 75 ), 100, 20, "Score:", 0xFFC000, BlackColor32 );
+ AddBorderedText( 50 + 15, 105 + ( i * 75 ), 100, 20, teamInfo.Score.ToString( "N0" ), 0xFFC000, BlackColor32 );
+
+ AddBorderedText( 110 + 10, 85 + ( i * 75 ), 100, 20, "Kills:", 0xFFC000, BlackColor32 );
+ AddBorderedText( 110 + 15, 105 + ( i * 75 ), 100, 20, teamInfo.Kills.ToString( "N0" ), 0xFFC000, BlackColor32 );
+
+ AddBorderedText( 160 + 10, 85 + ( i * 75 ), 100, 20, "Captures:", 0xFFC000, BlackColor32 );
+ AddBorderedText( 160 + 15, 105 + ( i * 75 ), 100, 20, teamInfo.Captures.ToString( "N0" ), 0xFFC000, BlackColor32 );
+
+ CTFPlayerInfo pl = teamInfo.Leader;
+
+ AddBorderedText( 235 + 10, 85 + ( i * 75 ), 250, 20, "Leader:", 0xFFC000, BlackColor32 );
+
+ if ( pl != null )
+ AddBorderedText( 235 + 15, 105 + ( i * 75 ), 250, 20, pl.Player.Name, 0xFFC000, BlackColor32 );
+ }
+ }
+ else
+ {
+ }
+
+ AddButton( 314, height - 42, 247, 248, 1, GumpButtonType.Reply, 0 );
+ }
+ }
+
+ public sealed class CTFFlag : Item
+ {
+ public CTFTeamInfo m_TeamInfo;
+
+ public override string DefaultName
+ {
+ get { return "old people cookies"; }
+ }
+
+ public Mobile m_Fragger;
+ public DateTime m_FragTime;
+
+ public Mobile m_Returner;
+ public DateTime m_ReturnTime;
+
+ private int m_ReturnCount;
+ private Timer m_ReturnTimer;
+
+ [Constructable]
+ public CTFFlag()
+ : base( 5643 )
+ {
+ Movable = false;
+ }
+
+ public override void OnDoubleClick( Mobile from )
+ {
+ if ( m_TeamInfo != null && m_TeamInfo.Game != null )
+ {
+ CTFTeamInfo ourTeam = m_TeamInfo;
+ CTFTeamInfo useTeam = m_TeamInfo.Game.GetTeamInfo( from );
+
+ if ( ourTeam == null || useTeam == null )
+ return;
+
+ if ( IsChildOf( from.Backpack ) )
+ {
+ from.BeginTarget( 1, false, TargetFlags.None, new TargetCallback( Flag_OnTarget ) );
+ }
+ else if ( !from.InRange( this, 1 ) || !from.InLOS( this ) )
+ {
+ from.LocalOverheadMessage( MessageType.Regular, 0x26, 1019045 ); // I can't reach that
+ }
+ else if ( ourTeam == useTeam )
+ {
+ if ( this.Location == m_TeamInfo.Origin && this.Map == m_TeamInfo.Game.Facet )
+ {
+ from.Send( new UnicodeMessage( this.Serial, this.ItemID, MessageType.Regular, 0x3B2, 3, "ENU", this.Name, "Touch me not for I am chaste." ) );
+ }
+ else
+ {
+ CTFPlayerInfo playerInfo = useTeam[from];
+
+ if ( playerInfo != null )
+ playerInfo.Score += 4; // return
+
+ m_Returner = from;
+ m_ReturnTime = DateTime.UtcNow;
+
+ SendHome();
+
+ from.LocalOverheadMessage( MessageType.Regular, 0x59, false, "You returned the cookies!" );
+ m_TeamInfo.Game.Alert( "The {1} cookies have been returned by {0}.", from.Name, ourTeam.Name );
+ }
+ }
+ else if ( !from.PlaceInBackpack( this ) )
+ {
+ from.LocalOverheadMessage( MessageType.Regular, 0x26, false, "I can't hold that." );
+ }
+ else
+ {
+ from.RevealingAction();
+
+ from.LocalOverheadMessage( MessageType.Regular, 0x59, false, "You stole the cookies!" );
+ m_TeamInfo.Game.Alert( "The {1} cookies have been stolen by {0} ({2}).", from.Name, ourTeam.Name, useTeam.Name );
+
+ BeginCountdown( 120 );
+ }
+ }
+ }
+
+ public override void Delete()
+ {
+ if ( Parent != null )
+ {
+ SendHome();
+ return;
+ }
+
+ base.Delete();
+ }
+
+ public void DropTo( Mobile mob, Mobile killer )
+ {
+ m_Fragger = killer;
+ m_FragTime = DateTime.UtcNow;
+
+ if ( mob != null )
+ {
+ MoveToWorld( new Point3D( mob.X, mob.Y, mob.Z + 2 ), mob.Map );
+
+ m_ReturnCount = Math.Min( m_ReturnCount, 10 );
+ }
+ else
+ {
+ SendHome();
+ }
+ }
+
+ private void StopCountdown()
+ {
+ if ( m_ReturnTimer != null )
+ m_ReturnTimer.Stop();
+
+ m_ReturnTimer = null;
+ }
+
+ private void BeginCountdown( int returnCount )
+ {
+ StopCountdown();
+
+ m_ReturnTimer = Timer.DelayCall( TimeSpan.FromSeconds( 1.0 ), TimeSpan.FromSeconds( 1.0 ), new TimerCallback( Countdown_OnTick ) );
+ m_ReturnCount = returnCount;
+ }
+
+ private void Countdown_OnTick()
+ {
+ Mobile owner = this.RootParent as Mobile;
+
+ switch ( m_ReturnCount )
+ {
+ case 60:
+ case 30:
+ case 15:
+ case 10:
+ case 5:
+ case 4:
+ case 3:
+ case 2:
+ case 1:
+ {
+ if ( owner != null )
+ owner.SendMessage( 0x26, "You have {0} {1} to capture the cookies!", m_ReturnCount, m_ReturnCount == 1 ? "second" : "seconds" );
+
+ break;
+ }
+
+ case 0:
+ {
+ if ( owner != null )
+ {
+ owner.SendMessage( 0x26, "You have taken too long to capture the cookies!" );
+ owner.Kill();
+ }
+
+ SendHome();
+
+ if ( m_TeamInfo != null && m_TeamInfo.Game != null )
+ m_TeamInfo.Game.Alert( "The {0} cookies have been returned.", m_TeamInfo.Name );
+
+ return;
+ }
+ }
+
+ --m_ReturnCount;
+ }
+
+ private void Flag_OnTarget( Mobile from, object obj )
+ {
+ if ( m_TeamInfo == null )
+ return;
+
+ if ( !IsChildOf( from.Backpack ) )
+ return;
+
+ CTFTeamInfo ourTeam = m_TeamInfo;
+ CTFTeamInfo useTeam = m_TeamInfo.Game.GetTeamInfo( from );
+
+ if ( obj is CTFFlag )
+ {
+ if ( obj == useTeam.Flag )
+ {
+ from.LocalOverheadMessage( MessageType.Regular, 0x59, false, "You captured the cookies!" );
+ m_TeamInfo.Game.Alert( "{0} captured the {1} cookies!", from.Name, ourTeam.Name );
+
+ SendHome();
+
+ CTFPlayerInfo playerInfo = useTeam[from];
+
+ if ( playerInfo != null )
+ {
+ playerInfo.Captures += 1;
+ playerInfo.Score += 50; // capture
+
+ CTFFlag teamFlag = useTeam.Flag;
+
+ if ( teamFlag.m_Fragger != null && DateTime.UtcNow < ( teamFlag.m_FragTime + TimeSpan.FromSeconds( 5.0 ) ) && m_TeamInfo.Game.GetTeamInfo( teamFlag.m_Fragger ) == useTeam )
+ {
+ CTFPlayerInfo assistInfo = useTeam[teamFlag.m_Fragger];
+
+ if ( assistInfo != null )
+ assistInfo.Score += 6; // frag assist
+ }
+
+ if ( teamFlag.m_Returner != null && DateTime.UtcNow < ( teamFlag.m_ReturnTime + TimeSpan.FromSeconds( 5.0 ) ) )
+ {
+ CTFPlayerInfo assistInfo = useTeam[teamFlag.m_Returner];
+
+ if ( assistInfo != null )
+ assistInfo.Score += 4; // return assist
+ }
+ }
+ }
+ else
+ {
+ from.LocalOverheadMessage( MessageType.Regular, 0x26, false, "Those are not my cookies." );
+ }
+ }
+ else if ( obj is Mobile )
+ {
+ Mobile passTo = obj as Mobile;
+
+ CTFTeamInfo passTeam = m_TeamInfo.Game.GetTeamInfo( passTo );
+
+ if ( passTo == from )
+ {
+ from.LocalOverheadMessage( MessageType.Regular, 0x26, false, "I can't pass to them." );
+ }
+ else if ( passTeam == useTeam && passTo.PlaceInBackpack( this ) )
+ {
+ passTo.LocalOverheadMessage( MessageType.Regular, 0x59, false, String.Format( "{0} has passed you the cookies!", from.Name ) );
+ }
+ else
+ {
+ from.LocalOverheadMessage( MessageType.Regular, 0x26, false, "I can't pass to them." );
+ }
+ }
+ }
+
+ public void SendHome()
+ {
+ StopCountdown();
+
+ if ( m_TeamInfo == null )
+ return;
+
+ MoveToWorld( m_TeamInfo.Origin, m_TeamInfo.Game.Facet );
+ }
+
+ private Mobile FindOwner( object parent )
+ {
+ if ( parent is Item )
+ return ( (Item) parent ).RootParent as Mobile;
+
+ if ( parent is Mobile )
+ return (Mobile) parent;
+
+ return null;
+ }
+
+ public override void OnAdded(IEntity parent)
+ {
+ base.OnAdded( parent );
+
+ Mobile mob = FindOwner( parent );
+
+ if ( mob != null )
+ mob.SolidHueOverride = 0x4001;
+ }
+
+ public override void OnRemoved(IEntity parent)
+ {
+ base.OnRemoved( parent );
+
+ Mobile mob = FindOwner( parent );
+
+ if ( mob != null )
+ mob.SolidHueOverride = ( m_TeamInfo == null ? -1 : m_TeamInfo.Game.GetColor( mob ) );
+ }
+
+ public CTFFlag( Serial serial )
+ : base( serial )
+ {
+ }
+
+ public override void Serialize( GenericWriter writer )
+ {
+ base.Serialize( writer );
+
+ writer.Write( (int) 0 );
+ }
+
+ public override void Deserialize( GenericReader reader )
+ {
+ base.Deserialize( reader );
+
+ int version = reader.ReadInt();
+ }
+ }
+
+ public interface IRankedCTF
+ {
+ int Kills { get; }
+ int Captures { get; }
+ int Score { get; }
+ string Name { get; }
+ }
+
+ public sealed class CTFPlayerInfo : IRankedCTF
+ {
+ private CTFTeamInfo m_TeamInfo;
+
+ private Mobile m_Player;
+
+ private int m_Kills;
+ private int m_Captures;
+
+ private int m_Score;
+
+ public Mobile Player { get { return m_Player; } }
+
+ string IRankedCTF.Name
+ {
+ get { return m_Player.Name; }
+ }
+
+ public int Kills
+ {
+ get
+ {
+ return m_Kills;
+ }
+ set
+ {
+ m_TeamInfo.Kills += ( value - m_Kills );
+ m_Kills = value;
+ }
+ }
+
+ public int Captures
+ {
+ get
+ {
+ return m_Captures;
+ }
+ set
+ {
+ m_TeamInfo.Captures += ( value - m_Captures );
+ m_Captures = value;
+ }
+ }
+
+ public int Score
+ {
+ get
+ {
+ return m_Score;
+ }
+ set
+ {
+ m_TeamInfo.Score += ( value - m_Score );
+ m_Score = value;
+
+ if ( m_TeamInfo.Leader == null || m_Score > m_TeamInfo.Leader.Score )
+ m_TeamInfo.Leader = this;
+ }
+ }
+
+ public CTFPlayerInfo( CTFTeamInfo teamInfo, Mobile player )
+ {
+ m_TeamInfo = teamInfo;
+ m_Player = player;
+ }
+ }
+
+ [PropertyObject]
+ public sealed class CTFTeamInfo : IRankedCTF
+ {
+ private CTFGame m_Game;
+ private int m_TeamID;
+
+ private int m_Color;
+ private string m_Name;
+
+ private CTFBoard m_Board;
+
+ private CTFFlag m_Flag;
+ private Point3D m_Origin;
+
+ private int m_Kills;
+ private int m_Captures;
+
+ private int m_Score;
+
+ private Dictionary m_Players;
+
+ string IRankedCTF.Name
+ {
+ get { return String.Format( "{0} Team", m_Name ); }
+ }
+
+ public CTFGame Game { get { return m_Game; } set { m_Game = value; } }
+ public int TeamID { get { return m_TeamID; } }
+
+ public int Kills { get { return m_Kills; } set { m_Kills = value; } }
+ public int Captures { get { return m_Captures; } set { m_Captures = value; } }
+
+ public int Score { get { return m_Score; } set { m_Score = value; } }
+
+ private CTFPlayerInfo m_Leader;
+
+ public CTFPlayerInfo Leader
+ {
+ get { return m_Leader; }
+ set { m_Leader = value; }
+ }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public CTFBoard Board
+ {
+ get { return m_Board; }
+ set { m_Board = value; }
+ }
+
+ public Dictionary Players
+ {
+ get { return m_Players; }
+ }
+
+ public CTFPlayerInfo this[Mobile mob]
+ {
+ get
+ {
+ if ( mob == null )
+ return null;
+
+ CTFPlayerInfo val;
+
+ if ( !m_Players.TryGetValue( mob, out val ) )
+ m_Players[mob] = val = new CTFPlayerInfo( this, mob );
+
+ return val;
+ }
+ }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public int Color
+ {
+ get { return m_Color; }
+ set { m_Color = value; }
+ }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public string Name
+ {
+ get { return m_Name; }
+ set { m_Name = value; }
+ }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public CTFFlag Flag
+ {
+ get { return m_Flag; }
+ set { m_Flag = value; }
+ }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public Point3D Origin
+ {
+ get { return m_Origin; }
+ set { m_Origin = value; }
+ }
+
+ public CTFTeamInfo( int teamID )
+ {
+ m_TeamID = teamID;
+ m_Players = new Dictionary();
+ }
+
+ public void Reset()
+ {
+ m_Kills = 0;
+ m_Captures = 0;
+
+ m_Score = 0;
+
+ m_Leader = null;
+
+ m_Players.Clear();
+
+ if ( m_Flag != null )
+ {
+ m_Flag.m_TeamInfo = this;
+ m_Flag.Hue = m_Color;
+ m_Flag.SendHome();
+ }
+
+ if ( m_Board != null )
+ m_Board.m_TeamInfo = this;
+ }
+
+ public CTFTeamInfo( int teamID, GenericReader ip )
+ {
+ m_TeamID = teamID;
+ m_Players = new Dictionary();
+
+ int version = ip.ReadEncodedInt();
+
+ switch ( version )
+ {
+ case 2:
+ {
+ m_Board = ip.ReadItem() as CTFBoard;
+
+ goto case 1;
+ }
+ case 1:
+ {
+ m_Name = ip.ReadString();
+
+ goto case 0;
+ }
+ case 0:
+ {
+ m_Color = ip.ReadEncodedInt();
+
+ m_Flag = ip.ReadItem() as CTFFlag;
+ m_Origin = ip.ReadPoint3D();
+ break;
+ }
+ }
+ }
+
+ public void Serialize( GenericWriter op )
+ {
+ op.WriteEncodedInt( 2 ); // version
+
+ op.Write( m_Board );
+
+ op.Write( m_Name );
+
+ op.WriteEncodedInt( m_Color );
+
+ op.Write( m_Flag );
+ op.Write( m_Origin );
+ }
+
+ public override string ToString()
+ {
+ return "...";
+ }
+ }
+
+ public sealed class CTFController : EventController
+ {
+ private CTFTeamInfo[] m_TeamInfo;
+
+ private TimeSpan m_Duration;
+
+ public CTFTeamInfo[] TeamInfo { get { return m_TeamInfo; } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public CTFTeamInfo Team1 { get { return m_TeamInfo[0]; } set { } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public CTFTeamInfo Team2 { get { return m_TeamInfo[1]; } set { } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public CTFTeamInfo Team3 { get { return m_TeamInfo[2]; } set { } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public CTFTeamInfo Team4 { get { return m_TeamInfo[3]; } set { } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public CTFTeamInfo Team5 { get { return m_TeamInfo[4]; } set { } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public CTFTeamInfo Team6 { get { return m_TeamInfo[5]; } set { } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public CTFTeamInfo Team7 { get { return m_TeamInfo[6]; } set { } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public CTFTeamInfo Team8 { get { return m_TeamInfo[7]; } set { } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public TimeSpan Duration
+ {
+ get { return m_Duration; }
+ set { m_Duration = value; }
+ }
+
+ public override string Title
+ {
+ get { return "CTF"; }
+ }
+
+ public override string GetTeamName( int teamID )
+ {
+ return m_TeamInfo[teamID % m_TeamInfo.Length].Name;
+ }
+
+ public override EventGame Construct( DuelContext context )
+ {
+ return new CTFGame( this, context );
+ }
+
+ [Constructable]
+ public CTFController()
+ {
+ Visible = false;
+ Movable = false;
+
+ m_Duration = TimeSpan.FromMinutes( 30.0 );
+
+ m_TeamInfo = new CTFTeamInfo[8];
+
+ for ( int i = 0; i < m_TeamInfo.Length; ++i )
+ m_TeamInfo[i] = new CTFTeamInfo( i );
+ }
+
+ public CTFController( Serial serial )
+ : base( serial )
+ {
+ }
+
+ public override void Serialize( GenericWriter writer )
+ {
+ base.Serialize( writer );
+
+ writer.Write( (int) 2 );
+
+ writer.Write( m_Duration );
+
+ writer.WriteEncodedInt( m_TeamInfo.Length );
+
+ for ( int i = 0; i < m_TeamInfo.Length; ++i )
+ m_TeamInfo[i].Serialize( writer );
+ }
+
+ public override void Deserialize( GenericReader reader )
+ {
+ base.Deserialize( reader );
+
+ int version = reader.ReadInt();
+
+ switch ( version )
+ {
+ case 2:
+ {
+ m_Duration = reader.ReadTimeSpan();
+
+ goto case 1;
+ }
+ case 1:
+ {
+ m_TeamInfo = new CTFTeamInfo[reader.ReadEncodedInt()];
+
+ for ( int i = 0; i < m_TeamInfo.Length; ++i )
+ m_TeamInfo[i] = new CTFTeamInfo( i, reader );
+
+ break;
+ }
+ case 0:
+ {
+ m_TeamInfo = new CTFTeamInfo[8];
+
+ for ( int i = 0; i < m_TeamInfo.Length; ++i )
+ m_TeamInfo[i] = new CTFTeamInfo( i );
+
+ break;
+ }
+ }
+
+ if ( version < 2 )
+ m_Duration = TimeSpan.FromMinutes( 30.0 );
+ }
+ }
+
+ public sealed class CTFGame : EventGame
+ {
+ public static void Initialize()
+ {
+ for ( int i = 0x7C9; i <= 0x7D0; ++i )
+ TileData.ItemTable[i].Flags |= TileFlag.NoShoot;
+ }
+
+ private CTFController m_Controller;
+
+ public CTFController Controller { get { return m_Controller; } }
+
+ public void Alert( string text )
+ {
+ if ( m_Context.m_Tournament != null )
+ m_Context.m_Tournament.Alert( text );
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ {
+ Participant p = m_Context.Participants[i] as Participant;
+
+ for ( int j = 0; j < p.Players.Length; ++j )
+ {
+ if ( p.Players[j] != null )
+ p.Players[j].Mobile.SendMessage( 0x35, text );
+ }
+ }
+ }
+
+ public void Alert( string format, params object[] args )
+ {
+ Alert( String.Format( format, args ) );
+ }
+
+ public CTFGame( CTFController controller, DuelContext context ) : base( context )
+ {
+ m_Controller = controller;
+ }
+
+ public Map Facet
+ {
+ get
+ {
+ if ( m_Context.Arena != null )
+ return m_Context.Arena.Facet;
+
+ return m_Controller.Map;
+ }
+ }
+
+ public CTFTeamInfo GetTeamInfo( Mobile mob )
+ {
+ int teamID = GetTeamID( mob );
+
+ if ( teamID >= 0 )
+ return m_Controller.TeamInfo[teamID % m_Controller.TeamInfo.Length];
+
+ return null;
+ }
+
+ public int GetTeamID( Mobile mob )
+ {
+ PlayerMobile pm = mob as PlayerMobile;
+
+ if ( pm == null )
+ return -1;
+
+ if ( pm.DuelContext == null || pm.DuelContext != m_Context )
+ return -1;
+
+ if ( pm.DuelPlayer == null || pm.DuelPlayer.Eliminated )
+ return -1;
+
+ return pm.DuelContext.Participants.IndexOf( pm.DuelPlayer.Participant );
+ }
+
+ public int GetColor( Mobile mob )
+ {
+ CTFTeamInfo teamInfo = GetTeamInfo( mob );
+
+ if ( teamInfo != null )
+ return teamInfo.Color;
+
+ return -1;
+ }
+
+ private void ApplyHues( Participant p, int hueOverride )
+ {
+ for ( int i = 0; i < p.Players.Length; ++i )
+ {
+ if ( p.Players[i] != null )
+ p.Players[i].Mobile.SolidHueOverride = hueOverride;
+ }
+ }
+
+ public void DelayBounce( TimeSpan ts, Mobile mob, Container corpse )
+ {
+ Timer.DelayCall( ts, new TimerStateCallback( DelayBounce_Callback ), new object[] { mob, corpse } );
+ }
+
+ private void DelayBounce_Callback( object state )
+ {
+ object[] states = (object[]) state;
+ Mobile mob = (Mobile) states[0];
+ Container corpse = (Container) states[1];
+
+ DuelPlayer dp = null;
+
+ if ( mob is PlayerMobile )
+ dp = ( mob as PlayerMobile ).DuelPlayer;
+
+ m_Context.RemoveAggressions( mob );
+
+ if ( dp != null && !dp.Eliminated )
+ mob.MoveToWorld( m_Context.Arena.GetBaseStartPoint( GetTeamID( mob ) ), Facet );
+ else
+ m_Context.SendOutside( mob );
+
+ m_Context.Refresh( mob, corpse );
+ DuelContext.Debuff( mob );
+ DuelContext.CancelSpell( mob );
+ mob.Frozen = false;
+ }
+
+ public override bool OnDeath( Mobile mob, Container corpse )
+ {
+ Mobile killer = mob.FindMostRecentDamager( false );
+
+ bool hadFlag = false;
+
+ Item[] flags = corpse.FindItemsByType( typeof( CTFFlag ), false );
+
+ for ( int i = 0; i < flags.Length; ++i )
+ ( flags[i] as CTFFlag ).DropTo( mob, killer );
+
+ hadFlag = ( hadFlag || flags.Length > 0 );
+
+ if ( mob.Backpack != null )
+ {
+ flags = mob.Backpack.FindItemsByType( typeof( CTFFlag ), false );
+
+ for ( int i = 0; i < flags.Length; ++i )
+ ( flags[i] as CTFFlag ).DropTo( mob, killer );
+
+ hadFlag = ( hadFlag || flags.Length > 0 );
+ }
+
+ if ( killer != null && killer.Player )
+ {
+ CTFTeamInfo teamInfo = GetTeamInfo( killer );
+ CTFTeamInfo victInfo = GetTeamInfo( mob );
+
+ if ( teamInfo != null && teamInfo != victInfo )
+ {
+ CTFPlayerInfo playerInfo = teamInfo[killer];
+
+ if ( playerInfo != null )
+ {
+ playerInfo.Kills += 1;
+ playerInfo.Score += 1; // base frag
+
+ if ( hadFlag )
+ playerInfo.Score += 4; // fragged flag carrier
+
+ if ( mob.InRange( teamInfo.Origin, 24 ) && mob.Map == this.Facet )
+ playerInfo.Score += 1; // fragged in base -- guarding
+
+ for ( int i = 0; i < m_Controller.TeamInfo.Length; ++i )
+ {
+ if ( m_Controller.TeamInfo[i] == teamInfo )
+ continue;
+
+ Mobile ourFlagCarrier = null;
+
+ if ( m_Controller.TeamInfo[i].Flag != null )
+ ourFlagCarrier = m_Controller.TeamInfo[i].Flag.RootParent as Mobile;
+
+ if ( ourFlagCarrier != null && GetTeamInfo( ourFlagCarrier ) == teamInfo )
+ {
+ for ( int j = 0; j < ourFlagCarrier.Aggressors.Count; ++j )
+ {
+ AggressorInfo aggr = ourFlagCarrier.Aggressors[j] as AggressorInfo;
+
+ if ( aggr == null || aggr.Defender != ourFlagCarrier || aggr.Attacker != mob )
+ continue;
+
+ playerInfo.Score += 2; // helped defend guy capturing enemy flag
+ break;
+ }
+
+ if ( mob.Map == ourFlagCarrier.Map && ourFlagCarrier.InRange( mob, 12 ) )
+ playerInfo.Score += 1; // helped defend guy capturing enemy flag
+ }
+ }
+ }
+ }
+ }
+
+ mob.CloseGump( typeof( CTFBoardGump ) );
+ mob.SendGump( new CTFBoardGump( mob, this ) );
+
+ m_Context.Requip( mob, corpse );
+ DelayBounce( TimeSpan.FromSeconds( 30.0 ), mob, corpse );
+
+ return false;
+ }
+
+ private Timer m_FinishTimer;
+
+ public override void OnStart()
+ {
+ for ( int i = 0; i < m_Controller.TeamInfo.Length; ++i )
+ {
+ CTFTeamInfo teamInfo = m_Controller.TeamInfo[i];
+
+ teamInfo.Game = this;
+ teamInfo.Reset();
+ }
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ ApplyHues( m_Context.Participants[i] as Participant, m_Controller.TeamInfo[i % 8].Color );
+
+ if ( m_FinishTimer != null )
+ m_FinishTimer.Stop();
+
+ m_FinishTimer = Timer.DelayCall( m_Controller.Duration, new TimerCallback( Finish_Callback ) );
+ }
+
+ private void Finish_Callback()
+ {
+ List teams = new List();
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ {
+ CTFTeamInfo teamInfo = m_Controller.TeamInfo[i % 8];
+
+ if ( teamInfo == null || teamInfo.Flag == null )
+ continue;
+
+ teams.Add( teamInfo );
+ }
+
+ teams.Sort( delegate( CTFTeamInfo a, CTFTeamInfo b )
+ {
+ return b.Score - a.Score;
+ } );
+
+ Tournament tourny = m_Context.m_Tournament;
+
+ StringBuilder sb = new StringBuilder();
+
+ if ( tourny != null && tourny.TournyType == TournyType.FreeForAll )
+ {
+ sb.Append( m_Context.Participants.Count * tourny.PlayersPerParticipant );
+ sb.Append( "-man FFA" );
+ }
+ else if ( tourny != null && tourny.TournyType == TournyType.RandomTeam )
+ {
+ sb.Append( tourny.ParticipantsPerMatch );
+ sb.Append( "-team" );
+ }
+ else if ( tourny != null && tourny.TournyType == TournyType.RedVsBlue )
+ {
+ sb.Append( "Red v Blue" );
+ }
+ else if ( tourny != null && tourny.TournyType == TournyType.Faction )
+ {
+ sb.Append( tourny.ParticipantsPerMatch );
+ sb.Append( "-team Faction" );
+ }
+ else if ( tourny != null )
+ {
+ for ( int i = 0; i < tourny.ParticipantsPerMatch; ++i )
+ {
+ if ( sb.Length > 0 )
+ sb.Append( 'v' );
+
+ sb.Append( tourny.PlayersPerParticipant );
+ }
+ }
+
+ if ( m_Controller != null )
+ sb.Append( ' ' ).Append( m_Controller.Title );
+
+ string title = sb.ToString();
+
+ CTFTeamInfo winner = ( teams.Count > 0 ? teams[0] : null );
+
+ for ( int i = 0; i < teams.Count; ++i )
+ {
+ TrophyRank rank = TrophyRank.Bronze;
+
+ if ( i == 0 )
+ rank = TrophyRank.Gold;
+ else if ( i == 1 )
+ rank = TrophyRank.Silver;
+
+ CTFPlayerInfo leader = teams[i].Leader;
+
+ foreach ( CTFPlayerInfo pl in teams[i].Players.Values )
+ {
+ Mobile mob = pl.Player;
+
+ if ( mob == null )
+ continue;
+
+ //"Red v Blue CTF Champion"
+
+ sb = new StringBuilder();
+
+ sb.Append( title );
+
+ if ( pl == leader )
+ sb.Append( " Leader" );
+
+ if ( pl.Score > 0 )
+ {
+ sb.Append( ": " );
+
+ sb.Append( pl.Score.ToString( "N0" ) );
+ sb.Append( pl.Score == 1 ? " point" : " points" );
+
+ if ( pl.Kills > 0 )
+ {
+ sb.Append( ", " );
+ sb.Append( pl.Kills.ToString( "N0" ) );
+ sb.Append( pl.Kills == 1 ? " kill" : " kills" );
+ }
+
+ if ( pl.Captures > 0 )
+ {
+ sb.Append( ", " );
+ sb.Append( pl.Captures.ToString( "N0" ) );
+ sb.Append( pl.Captures == 1 ? " capture" : " captures" );
+ }
+ }
+
+ Item item = new Trophy( sb.ToString(), rank );
+
+ if ( pl == leader )
+ item.ItemID = 4810;
+
+ item.Name = String.Format( "{0}, {1} team", item.Name, teams[i].Name.ToLower() );
+
+ if ( !mob.PlaceInBackpack( item ) )
+ mob.BankBox.DropItem( item );
+
+ int cash = pl.Score * 250;
+
+ 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() );
+ }
+ }
+ }
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ {
+ Participant p = m_Context.Participants[i] as Participant;
+
+ for ( int j = 0; j < p.Players.Length; ++j )
+ {
+ DuelPlayer dp = p.Players[j];
+
+ if ( dp != null && dp.Mobile != null )
+ {
+ dp.Mobile.CloseGump( typeof( CTFBoardGump ) );
+ dp.Mobile.SendGump( new CTFBoardGump( dp.Mobile, this ) );
+ }
+ }
+
+ if ( i == winner.TeamID )
+ continue;
+
+ for ( int j = 0; j < p.Players.Length; ++j )
+ {
+ if ( p.Players[j] != null )
+ p.Players[j].Eliminated = true;
+ }
+ }
+
+ m_Context.Finish( m_Context.Participants[winner.TeamID] as Participant );
+ }
+
+ public override void OnStop()
+ {
+ for ( int i = 0; i < m_Controller.TeamInfo.Length; ++i )
+ {
+ CTFTeamInfo teamInfo = m_Controller.TeamInfo[i];
+
+ if ( teamInfo.Flag != null )
+ {
+ teamInfo.Flag.SendHome();
+ teamInfo.Flag.m_TeamInfo = null;
+ }
+
+ if ( teamInfo.Board != null )
+ teamInfo.Board.m_TeamInfo = null;
+
+ teamInfo.Game = null;
+ }
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ ApplyHues( m_Context.Participants[i] as Participant, -1 );
+
+ if ( m_FinishTimer != null )
+ m_FinishTimer.Stop();
+
+ m_FinishTimer = null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Scripts/Engines/ConPVP/Games/DoubleDom.cs b/Scripts/Engines/ConPVP/Games/DoubleDom.cs
new file mode 100644
index 000000000..1749f9a6d
--- /dev/null
+++ b/Scripts/Engines/ConPVP/Games/DoubleDom.cs
@@ -0,0 +1,1250 @@
+using System;
+using System.Collections;
+using System.Text;
+using Server;
+using Server.Items;
+using Server.Mobiles;
+using Server.Network;
+using Server.Targeting;
+using Server.Gumps;
+using System.Collections.Generic;
+
+namespace Server.Engines.ConPVP
+{
+ public sealed class DDBoard : Item
+ {
+ public DDTeamInfo m_TeamInfo;
+
+ public override string DefaultName
+ {
+ get { return "scoreboard"; }
+ }
+
+ [Constructable]
+ public DDBoard()
+ : base( 7774 )
+ {
+ Movable = false;
+ }
+
+ public override void OnDoubleClick( Mobile from )
+ {
+ if ( m_TeamInfo != null && m_TeamInfo.Game != null )
+ {
+ from.CloseGump( typeof( DDBoardGump ) );
+ from.SendGump( new DDBoardGump( from, m_TeamInfo.Game ) );
+ }
+ }
+
+ public DDBoard( Serial serial )
+ : base( serial )
+ {
+ }
+
+ public override void Serialize( GenericWriter writer )
+ {
+ base.Serialize( writer );
+
+ writer.Write( (int) 0 );
+ }
+
+ public override void Deserialize( GenericReader reader )
+ {
+ base.Deserialize( reader );
+
+ int version = reader.ReadInt();
+ }
+ }
+
+ public class DDBoardGump : Gump
+ {
+ 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 );
+ }
+
+ private const int LabelColor32 = 0xFFFFFF;
+ private const int BlackColor32 = 0x000000;
+
+ private DDGame m_Game;
+
+ public DDBoardGump( Mobile mob, DDGame game )
+ : this( mob, game, null )
+ {
+ }
+
+ public DDBoardGump( Mobile mob, DDGame game, DDTeamInfo section )
+ : base( 60, 60 )
+ {
+ m_Game = game;
+
+ DDTeamInfo ourTeam = game.GetTeamInfo( mob );
+
+ List entries = new List();
+
+ if ( section == null )
+ {
+ for ( int i = 0; i < game.Context.Participants.Count; ++i )
+ {
+ DDTeamInfo teamInfo = game.Controller.TeamInfo[i % game.Controller.TeamInfo.Length];
+
+ if ( teamInfo != null )
+ entries.Add( teamInfo );
+ }
+ }
+ else
+ {
+ foreach ( DDPlayerInfo player in section.Players.Values )
+ {
+ if ( player.Score > 0 )
+ entries.Add( player );
+ }
+ }
+
+ entries.Sort( delegate( IRankedCTF a, IRankedCTF b )
+ {
+ return b.Score - a.Score;
+ } );
+
+ int height = 0;
+
+ if ( section == null )
+ height = 73 + ( entries.Count * 75 ) + 28;
+
+ Closable = false;
+
+ AddPage( 0 );
+
+ AddBackground( 1, 1, 398, height, 3600 );
+
+ AddImageTiled( 16, 15, 369, height - 29, 3604 );
+
+ for ( int i = 0; i < entries.Count; i += 1 )
+ AddImageTiled( 22, 58 + ( i * 75 ), 357, 70, 0x2430 );
+
+ AddAlphaRegion( 16, 15, 369, height - 29 );
+
+ AddImage( 215, -45, 0xEE40 );
+ //AddImage( 330, 141, 0x8BA );
+
+ AddBorderedText( 22, 22, 294, 20, Center( "DD Scoreboard" ), LabelColor32, BlackColor32 );
+
+ AddImageTiled( 32, 50, 264, 1, 9107 );
+ AddImageTiled( 42, 52, 264, 1, 9157 );
+
+ if ( section == null )
+ {
+ for ( int i = 0; i < entries.Count; ++i )
+ {
+ DDTeamInfo teamInfo = entries[i] as DDTeamInfo;
+
+ AddImage( 30, 70 + ( i * 75 ), 10152 );
+ AddImage( 30, 85 + ( i * 75 ), 10151 );
+ AddImage( 30, 100 + ( i * 75 ), 10151 );
+ AddImage( 30, 106 + ( i * 75 ), 10154 );
+
+ AddImage( 24, 60 + ( i * 75 ), teamInfo == ourTeam ? 9730 : 9727, teamInfo.Color - 1 );
+
+ int nameColor = LabelColor32;
+ int borderColor = BlackColor32;
+
+ switch ( teamInfo.Color )
+ {
+ case 0x47E:
+ nameColor = 0xFFFFFF;
+ break;
+
+ case 0x4F2:
+ nameColor = 0x3399FF;
+ break;
+
+ case 0x4F7:
+ nameColor = 0x33FF33;
+ break;
+
+ case 0x4FC:
+ nameColor = 0xFF00FF;
+ break;
+
+ case 0x021:
+ nameColor = 0xFF3333;
+ break;
+
+ case 0x01A:
+ nameColor = 0xFF66FF;
+ break;
+
+ case 0x455:
+ nameColor = 0x333333;
+ borderColor = 0xFFFFFF;
+ break;
+ }
+
+ AddBorderedText( 60, 65 + ( i * 75 ), 250, 20, String.Format( "{0}: {1}", LadderGump.Rank( 1 + i ), teamInfo.Name ), nameColor, borderColor );
+
+ AddBorderedText( 50 + 10, 85 + ( i * 75 ), 100, 20, "Score:", 0xFFC000, BlackColor32 );
+ AddBorderedText( 50 + 15, 105 + ( i * 75 ), 100, 20, teamInfo.Score.ToString( "N0" ), 0xFFC000, BlackColor32 );
+
+ AddBorderedText( 110 + 10, 85 + ( i * 75 ), 100, 20, "Kills:", 0xFFC000, BlackColor32 );
+ AddBorderedText( 110 + 15, 105 + ( i * 75 ), 100, 20, teamInfo.Kills.ToString( "N0" ), 0xFFC000, BlackColor32 );
+
+ AddBorderedText( 160 + 10, 85 + ( i * 75 ), 100, 20, "Captures:", 0xFFC000, BlackColor32 );
+ AddBorderedText( 160 + 15, 105 + ( i * 75 ), 100, 20, teamInfo.Captures.ToString( "N0" ), 0xFFC000, BlackColor32 );
+
+ DDPlayerInfo pl = teamInfo.Leader;
+
+ AddBorderedText( 235 + 10, 85 + ( i * 75 ), 250, 20, "Leader:", 0xFFC000, BlackColor32 );
+
+ if ( pl != null )
+ AddBorderedText( 235 + 15, 105 + ( i * 75 ), 250, 20, pl.Player.Name, 0xFFC000, BlackColor32 );
+ }
+ }
+ else
+ {
+ }
+
+ AddButton( 314, height - 42, 247, 248, 1, GumpButtonType.Reply, 0 );
+ }
+ }
+
+ public sealed class DDPlayerInfo : IRankedCTF
+ {
+ private DDTeamInfo m_TeamInfo;
+
+ private Mobile m_Player;
+
+ private int m_Kills;
+ private int m_Captures;
+
+ private int m_Score;
+
+ public Mobile Player { get { return m_Player; } }
+
+ public string Name
+ {
+ get { return m_Player.Name; }
+ }
+
+ public int Kills
+ {
+ get
+ {
+ return m_Kills;
+ }
+ set
+ {
+ m_TeamInfo.Kills += ( value - m_Kills );
+ m_Kills = value;
+ }
+ }
+
+ public int Captures
+ {
+ get
+ {
+ return m_Captures;
+ }
+ set
+ {
+ m_TeamInfo.Captures += ( value - m_Captures );
+ m_Captures = value;
+ }
+ }
+
+ public int Score
+ {
+ get
+ {
+ return m_Score;
+ }
+ set
+ {
+ m_TeamInfo.Score += ( value - m_Score );
+ m_Score = value;
+
+ if ( m_TeamInfo.Leader == null || m_Score > m_TeamInfo.Leader.Score )
+ m_TeamInfo.Leader = this;
+ }
+ }
+
+ public DDPlayerInfo( DDTeamInfo teamInfo, Mobile player )
+ {
+ m_TeamInfo = teamInfo;
+ m_Player = player;
+ }
+ }
+
+ [PropertyObject]
+ public sealed class DDTeamInfo : IRankedCTF
+ {
+ private DDGame m_Game;
+ private int m_TeamID;
+
+ private int m_Color;
+ private string m_Name;
+
+ private DDBoard m_Board;
+
+ private Point3D m_Origin;
+
+ private int m_Kills;
+ private int m_Captures;
+
+ private int m_Score;
+
+ private Dictionary m_Players;
+
+ public string Name
+ {
+ get { return String.Format( "{0} Team", m_Name ); }
+ }
+
+ public DDGame Game { get { return m_Game; } set { m_Game = value; } }
+ public int TeamID { get { return m_TeamID; } }
+
+ public int Kills { get { return m_Kills; } set { m_Kills = value; } }
+ public int Captures { get { return m_Captures; } set { m_Captures = value; } }
+
+ public int Score { get { return m_Score; } set { m_Score = value; } }
+
+ private DDPlayerInfo m_Leader;
+
+ public DDPlayerInfo Leader
+ {
+ get { return m_Leader; }
+ set { m_Leader = value; }
+ }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public DDBoard Board
+ {
+ get { return m_Board; }
+ set { m_Board = value; }
+ }
+
+ public Dictionary Players
+ {
+ get { return m_Players; }
+ }
+
+ public DDPlayerInfo this[Mobile mob]
+ {
+ get
+ {
+ if ( mob == null )
+ return null;
+
+ DDPlayerInfo val;
+
+ if ( !m_Players.TryGetValue( mob, out val ) )
+ m_Players[mob] = val = new DDPlayerInfo( this, mob );
+
+ return val;
+ }
+ }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public int Color
+ {
+ get { return m_Color; }
+ set { m_Color = value; }
+ }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public string TeamName
+ {
+ get { return m_Name; }
+ set { m_Name = value; }
+ }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public Point3D Origin
+ {
+ get { return m_Origin; }
+ set { m_Origin = value; }
+ }
+
+ public DDTeamInfo( int teamID )
+ {
+ m_TeamID = teamID;
+ m_Players = new Dictionary();
+ }
+
+ public void Reset()
+ {
+ m_Kills = 0;
+ m_Captures = 0;
+
+ m_Score = 0;
+
+ m_Leader = null;
+
+ m_Players.Clear();
+
+ if ( m_Board != null )
+ m_Board.m_TeamInfo = this;
+ }
+
+ public DDTeamInfo( int teamID, GenericReader ip )
+ {
+ m_TeamID = teamID;
+ m_Players = new Dictionary();
+
+ int version = ip.ReadEncodedInt();
+
+ switch ( version )
+ {
+ case 0:
+ {
+ m_Board = ip.ReadItem() as DDBoard;
+ m_Name = ip.ReadString();
+ m_Color = ip.ReadEncodedInt();
+ m_Origin = ip.ReadPoint3D();
+ break;
+ }
+ }
+ }
+
+ public void Serialize( GenericWriter op )
+ {
+ op.WriteEncodedInt( 0 ); // version
+
+ op.Write( m_Board );
+ op.Write( m_Name );
+ op.WriteEncodedInt( m_Color );
+ op.Write( m_Origin );
+ }
+
+ public override string ToString()
+ {
+ return "...";
+ }
+ }
+
+ public sealed class DDController : EventController
+ {
+ private DDTeamInfo[] m_TeamInfo;
+
+ private TimeSpan m_Duration;
+
+ public DDTeamInfo[] TeamInfo { get { return m_TeamInfo; } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public DDTeamInfo Team1 { get { return m_TeamInfo[0]; } set { } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public DDTeamInfo Team2 { get { return m_TeamInfo[1]; } set { } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public DDWayPoint PointA { get { return m_PointA; } set { m_PointA = value; } }
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public DDWayPoint PointB { get { return m_PointB; } set { m_PointB = value; } }
+
+ private DDWayPoint m_PointA, m_PointB;
+
+ [CommandProperty( AccessLevel.GameMaster )]
+ public TimeSpan Duration
+ {
+ get { return m_Duration; }
+ set { m_Duration = value; }
+ }
+
+ public override string Title
+ {
+ get { return "DoubleDom"; }
+ }
+
+ public override string GetTeamName( int teamID )
+ {
+ return m_TeamInfo[teamID % m_TeamInfo.Length].Name;
+ }
+
+ public override EventGame Construct( DuelContext context )
+ {
+ return new DDGame( this, context );
+ }
+
+ public override string DefaultName { get { return "DD Controller"; } }
+
+ [Constructable]
+ public DDController()
+ {
+ Visible = false;
+ Movable = false;
+
+ m_Duration = TimeSpan.FromMinutes( 30.0 );
+
+ m_TeamInfo = new DDTeamInfo[2];
+
+ for ( int i = 0; i < m_TeamInfo.Length; ++i )
+ m_TeamInfo[i] = new DDTeamInfo( i );
+ }
+
+ public DDController( Serial serial )
+ : base( serial )
+ {
+ }
+
+ public override void Serialize( GenericWriter writer )
+ {
+ base.Serialize( writer );
+
+ writer.Write( (int)0 );
+
+ writer.Write( m_Duration );
+
+ writer.WriteEncodedInt( m_TeamInfo.Length );
+
+ for ( int i = 0; i < m_TeamInfo.Length; ++i )
+ m_TeamInfo[i].Serialize( writer );
+
+ writer.Write( m_PointA );
+ writer.Write( m_PointB );
+ }
+
+ public override void Deserialize( GenericReader reader )
+ {
+ base.Deserialize( reader );
+
+ int version = reader.ReadInt();
+
+ switch ( version )
+ {
+ case 0:
+ {
+ m_Duration = reader.ReadTimeSpan();
+ m_TeamInfo = new DDTeamInfo[reader.ReadEncodedInt()];
+
+ for ( int i = 0; i < m_TeamInfo.Length; ++i )
+ m_TeamInfo[i] = new DDTeamInfo( i, reader );
+
+ m_PointA = reader.ReadItem() as DDWayPoint;
+ m_PointB = reader.ReadItem() as DDWayPoint;
+
+ break;
+ }
+ }
+ }
+ }
+
+ public sealed class DDGame : EventGame
+ {
+ private DDController m_Controller;
+
+ public DDController Controller { get { return m_Controller; } }
+
+ public void Alert( string text )
+ {
+ if ( m_Context.m_Tournament != null )
+ m_Context.m_Tournament.Alert( text );
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ {
+ Participant p = m_Context.Participants[i] as Participant;
+
+ for ( int j = 0; j < p.Players.Length; ++j )
+ {
+ if ( p.Players[j] != null )
+ p.Players[j].Mobile.SendMessage( 0x35, text );
+ }
+ }
+ }
+
+ public void Alert( string format, params object[] args )
+ {
+ Alert( String.Format( format, args ) );
+ }
+
+ public DDGame( DDController controller, DuelContext context ) : base( context )
+ {
+ m_Controller = controller;
+ }
+
+ public Map Facet
+ {
+ get
+ {
+ if ( m_Context.Arena != null )
+ return m_Context.Arena.Facet;
+
+ return m_Controller.Map;
+ }
+ }
+
+ public DDTeamInfo GetTeamInfo( Mobile mob )
+ {
+ int teamID = GetTeamID( mob );
+
+ if ( teamID >= 0 )
+ return m_Controller.TeamInfo[teamID % m_Controller.TeamInfo.Length];
+
+ return null;
+ }
+
+ public int GetTeamID( Mobile mob )
+ {
+ PlayerMobile pm = mob as PlayerMobile;
+
+ if ( pm == null )
+ return -1;
+
+ if ( pm.DuelContext == null || pm.DuelContext != m_Context )
+ return -1;
+
+ if ( pm.DuelPlayer == null || pm.DuelPlayer.Eliminated )
+ return -1;
+
+ return pm.DuelContext.Participants.IndexOf( pm.DuelPlayer.Participant );
+ }
+
+ public int GetColor( Mobile mob )
+ {
+ DDTeamInfo teamInfo = GetTeamInfo( mob );
+
+ if ( teamInfo != null )
+ return teamInfo.Color;
+
+ return -1;
+ }
+
+ private void ApplyHues( Participant p, int hueOverride )
+ {
+ for ( int i = 0; i < p.Players.Length; ++i )
+ {
+ if ( p.Players[i] != null )
+ p.Players[i].Mobile.SolidHueOverride = hueOverride;
+ }
+ }
+
+ public void DelayBounce( TimeSpan ts, Mobile mob, Container corpse )
+ {
+ Timer.DelayCall( ts, new TimerStateCallback( DelayBounce_Callback ), new object[] { mob, corpse } );
+ }
+
+ private void DelayBounce_Callback( object state )
+ {
+ object[] states = (object[]) state;
+ Mobile mob = (Mobile) states[0];
+ Container corpse = (Container) states[1];
+
+ DuelPlayer dp = null;
+
+ if ( mob is PlayerMobile )
+ dp = ( mob as PlayerMobile ).DuelPlayer;
+
+ m_Context.RemoveAggressions( mob );
+
+ if ( dp != null && !dp.Eliminated )
+ mob.MoveToWorld( m_Context.Arena.GetBaseStartPoint( GetTeamID( mob ) ), Facet );
+ else
+ m_Context.SendOutside( mob );
+
+ m_Context.Refresh( mob, corpse );
+ DuelContext.Debuff( mob );
+ DuelContext.CancelSpell( mob );
+ mob.Frozen = false;
+ }
+
+ public override bool OnDeath( Mobile mob, Container corpse )
+ {
+ Mobile killer = mob.FindMostRecentDamager( false );
+
+ if ( killer != null && killer.Player )
+ {
+ DDTeamInfo teamInfo = GetTeamInfo( killer );
+ DDTeamInfo victInfo = GetTeamInfo( mob );
+
+ if ( teamInfo != null && teamInfo != victInfo )
+ {
+ DDPlayerInfo playerInfo = teamInfo[killer];
+
+ if ( playerInfo != null )
+ {
+ playerInfo.Kills += 1;
+ playerInfo.Score += 1; // base frag
+
+ // extra points for killing someone on the waypoint
+ if ( this.Controller.PointA != null )
+ {
+ if ( mob.InRange( this.Controller.PointA, 2 ) )
+ playerInfo.Score += 1;
+ }
+
+ if ( this.Controller.PointB != null )
+ {
+ if ( mob.InRange( this.Controller.PointB, 2 ) )
+ playerInfo.Score += 1;
+ }
+ }
+
+ playerInfo = victInfo[mob];
+ if ( playerInfo != null )
+ playerInfo.Score -= 1;
+ }
+ }
+
+ mob.CloseGump( typeof( DDBoardGump ) );
+ mob.SendGump( new DDBoardGump( mob, this ) );
+
+ m_Context.Requip( mob, corpse );
+ DelayBounce( TimeSpan.FromSeconds( 30.0 ), mob, corpse );
+
+ return false;
+ }
+
+ private Timer m_FinishTimer;
+
+ public override void OnStart()
+ {
+ m_Capturable = true;
+
+ if ( m_CaptureTimer != null )
+ {
+ m_CaptureTimer.Stop();
+ m_CaptureTimer = null;
+ }
+
+ if ( m_UncaptureTimer != null )
+ {
+ m_UncaptureTimer.Stop();
+ m_UncaptureTimer = null;
+ }
+
+ for ( int i = 0; i < m_Controller.TeamInfo.Length; ++i )
+ {
+ DDTeamInfo teamInfo = m_Controller.TeamInfo[i];
+
+ teamInfo.Game = this;
+ teamInfo.Reset();
+ }
+
+ if ( m_Controller.PointA != null )
+ m_Controller.PointA.Game = this;
+
+ if ( m_Controller.PointB != null )
+ m_Controller.PointB.Game = this;
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ ApplyHues( m_Context.Participants[i] as Participant, m_Controller.TeamInfo[i % m_Controller.TeamInfo.Length].Color );
+
+ if ( m_FinishTimer != null )
+ m_FinishTimer.Stop();
+
+ m_FinishTimer = Timer.DelayCall( m_Controller.Duration, new TimerCallback( Finish_Callback ) );
+ }
+
+ private void Finish_Callback()
+ {
+ List teams = new List();
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ {
+ DDTeamInfo teamInfo = m_Controller.TeamInfo[i % m_Controller.TeamInfo.Length];
+
+ if ( teamInfo != null )
+ teams.Add( teamInfo );
+ }
+
+ teams.Sort( delegate( DDTeamInfo a, DDTeamInfo b )
+ {
+ return b.Score - a.Score;
+ } );
+
+ Tournament tourny = m_Context.m_Tournament;
+
+ StringBuilder sb = new StringBuilder();
+
+ if ( tourny != null && tourny.TournyType == TournyType.FreeForAll )
+ {
+ sb.Append( m_Context.Participants.Count * tourny.PlayersPerParticipant );
+ sb.Append( "-man FFA" );
+ }
+ else if ( tourny != null && tourny.TournyType == TournyType.RandomTeam )
+ {
+ sb.Append( tourny.ParticipantsPerMatch );
+ sb.Append( "-team" );
+ }
+ else if ( tourny != null && tourny.TournyType == TournyType.RedVsBlue )
+ {
+ sb.Append( "Red v Blue" );
+ }
+ else if ( tourny != null && tourny.TournyType == TournyType.Faction )
+ {
+ sb.Append( tourny.ParticipantsPerMatch );
+ sb.Append( "-team Faction" );
+ }
+ else if ( tourny != null )
+ {
+ for ( int i = 0; i < tourny.ParticipantsPerMatch; ++i )
+ {
+ if ( sb.Length > 0 )
+ sb.Append( 'v' );
+
+ sb.Append( tourny.PlayersPerParticipant );
+ }
+ }
+
+ if ( m_Controller != null )
+ sb.Append( ' ' ).Append( m_Controller.Title );
+
+ string title = sb.ToString();
+
+ DDTeamInfo winner = (DDTeamInfo)( teams.Count > 0 ? teams[0] : null );
+
+ for ( int i = 0; i < teams.Count; ++i )
+ {
+ TrophyRank rank = TrophyRank.Bronze;
+
+ if ( i == 0 )
+ rank = TrophyRank.Gold;
+ else if ( i == 1 )
+ rank = TrophyRank.Silver;
+
+ DDPlayerInfo leader = ((DDTeamInfo)teams[i]).Leader;
+
+ foreach ( DDPlayerInfo pl in ((DDTeamInfo)teams[i]).Players.Values )
+ {
+ Mobile mob = pl.Player;
+
+ if ( mob == null )
+ continue;
+
+ //"Red v Blue DD Champion"
+
+ sb = new StringBuilder();
+
+ sb.Append( title );
+
+ if ( pl == leader )
+ sb.Append( " Leader" );
+
+ if ( pl.Score > 0 )
+ {
+ sb.Append( ": " );
+
+ sb.Append( pl.Score.ToString( "N0" ) );
+ sb.Append( pl.Score == 1 ? " point" : " points" );
+
+ if ( pl.Kills > 0 )
+ {
+ sb.Append( ", " );
+ sb.Append( pl.Kills.ToString( "N0" ) );
+ sb.Append( pl.Kills == 1 ? " kill" : " kills" );
+ }
+
+ if ( pl.Captures > 0 )
+ {
+ sb.Append( ", " );
+ sb.Append( pl.Captures.ToString( "N0" ) );
+ sb.Append( pl.Captures == 1 ? " capture" : " captures" );
+ }
+ }
+
+ Item item = new Trophy( sb.ToString(), rank );
+
+ if ( pl == leader )
+ item.ItemID = 4810;
+
+ item.Name = String.Format( "{0}, {1} team", item.Name, ((DDTeamInfo)teams[i]).Name.ToLower() );
+
+ if ( !mob.PlaceInBackpack( item ) )
+ mob.BankBox.DropItem( item );
+
+ int cash = pl.Score * 250;
+
+ 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() );
+ }
+ }
+ }
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ {
+ Participant p = m_Context.Participants[i] as Participant;
+
+ for ( int j = 0; j < p.Players.Length; ++j )
+ {
+ DuelPlayer dp = p.Players[j];
+
+ if ( dp != null && dp.Mobile != null )
+ {
+ dp.Mobile.CloseGump( typeof( DDBoardGump ) );
+ dp.Mobile.SendGump( new DDBoardGump( dp.Mobile, this ) );
+ }
+ }
+
+ if ( i == winner.TeamID )
+ continue;
+
+ for ( int j = 0; j < p.Players.Length; ++j )
+ {
+ if ( p.Players[j] != null )
+ p.Players[j].Eliminated = true;
+ }
+ }
+
+ m_Context.Finish( m_Context.Participants[winner.TeamID] as Participant );
+ }
+
+ public override void OnStop()
+ {
+ for ( int i = 0; i < m_Controller.TeamInfo.Length; ++i )
+ {
+ DDTeamInfo teamInfo = m_Controller.TeamInfo[i];
+
+ if ( teamInfo.Board != null )
+ teamInfo.Board.m_TeamInfo = null;
+
+ teamInfo.Game = null;
+ }
+
+ if ( m_Controller.PointA != null )
+ m_Controller.PointA.Game = null;
+
+ if ( m_Controller.PointB != null )
+ m_Controller.PointB.Game = null;
+
+ m_Capturable = false;
+
+ if ( m_CaptureTimer != null )
+ {
+ m_CaptureTimer.Stop();
+ m_CaptureTimer = null;
+ }
+
+ if ( m_UncaptureTimer != null )
+ {
+ m_UncaptureTimer.Stop();
+ m_UncaptureTimer = null;
+ }
+
+ for ( int i = 0; i < m_Context.Participants.Count; ++i )
+ ApplyHues( m_Context.Participants[i] as Participant, -1 );
+
+ if ( m_FinishTimer != null )
+ m_FinishTimer.Stop();
+
+ m_FinishTimer = null;
+ }
+
+ private bool m_Capturable = true;
+ private Timer m_CaptureTimer = null;
+ private Timer m_UncaptureTimer = null;
+ private int m_CapStage = 0;
+
+ public void Dominate( DDWayPoint point, Mobile from, DDTeamInfo team )
+ {
+ if ( point == null || from == null || team == null || !m_Capturable )
+ return;
+
+ bool wasDom = ( m_Controller.PointA != null && m_Controller.PointB != null &&
+ m_Controller.PointA.TeamOwner == m_Controller.PointB.TeamOwner && m_Controller.PointA.TeamOwner != null );
+
+ point.TeamOwner = team;
+ Alert( "{0} has captured {1}!", team.Name, point.Name );
+
+ bool isDom = ( m_Controller.PointA != null && m_Controller.PointB != null &&
+ m_Controller.PointA.TeamOwner == m_Controller.PointB.TeamOwner && m_Controller.PointA.TeamOwner != null );
+
+ if ( wasDom && !isDom )
+ {
+ Alert( "Domination averted!" );
+
+ if ( m_Controller.PointA != null )
+ m_Controller.PointA.SetNonCaptureHue();
+
+ if ( m_Controller.PointB != null )
+ m_Controller.PointB.SetNonCaptureHue();
+
+ if ( m_CaptureTimer != null )
+ m_CaptureTimer.Stop();
+ m_CaptureTimer = null;
+ }
+
+ if ( !wasDom && isDom )
+ {
+ m_CapStage = 0;
+ m_CaptureTimer = Timer.DelayCall( TimeSpan.Zero, TimeSpan.FromSeconds( 1.0 ), new TimerCallback( CaptureTick ) );
+ m_CaptureTimer.Start();
+ }
+ }
+
+ private void CaptureTick()
+ {
+ DDTeamInfo team = null;
+
+ if ( m_Controller.PointA != null && m_Controller.PointA.TeamOwner != null )
+ team = m_Controller.PointA.TeamOwner;
+ else if ( m_Controller.PointB != null && m_Controller.PointB.TeamOwner != null )
+ team = m_Controller.PointB.TeamOwner;
+
+ if ( team == null )
+ {
+ m_Capturable = true;
+ if ( m_CaptureTimer != null )
+ m_CaptureTimer.Stop();
+ m_CaptureTimer = null;
+ return;
+ }
+
+ if ( ++m_CapStage < 10 )
+ {
+ Alert( "{0} is dominating... {1}", team.Name, 10 - m_CapStage );
+
+ if ( m_Controller.PointA != null )
+ m_Controller.PointA.SetCaptureHue( m_CapStage );
+
+ if ( m_Controller.PointB != null )
+ m_Controller.PointB.SetCaptureHue( m_CapStage );
+ }
+ else
+ {
+ Alert( "{0} has scored!", team.Name );
+
+ team.Score += 100;
+ team.Captures += 1;
+
+ m_Capturable = false;
+ m_CapStage = 0;
+ m_CaptureTimer.Stop();
+ m_CaptureTimer = null;
+
+ if ( m_Controller.PointA != null )
+ {
+ m_Controller.PointA.TeamOwner = null;
+ m_Controller.PointA.SetUncapturableHue();
+ }
+
+ if ( m_Controller.PointB != null )
+ {
+ m_Controller.PointB.TeamOwner = null;
+ m_Controller.PointB.SetUncapturableHue();
+ }
+
+ m_UncaptureTimer = Timer.DelayCall( TimeSpan.FromSeconds( 30.0 ), new TimerCallback( UncaptureTick ) );
+ m_UncaptureTimer.Start();
+ }
+ }
+
+ private void UncaptureTick()
+ {
+ m_Capturable = true;
+
+ if ( m_CaptureTimer != null )
+ {
+ m_CaptureTimer.Stop();
+ m_CaptureTimer = null;
+ }
+
+ if ( m_UncaptureTimer != null )
+ {
+ m_UncaptureTimer.Stop();
+ m_UncaptureTimer = null;
+ }
+
+ if ( m_Controller.PointA != null )
+ {
+ m_Controller.PointA.TeamOwner = null;
+ m_Controller.PointA.SetNonCaptureHue();
+ }
+
+ if ( m_Controller.PointB != null )
+ {
+ m_Controller.PointB.TeamOwner = null;
+ m_Controller.PointB.SetNonCaptureHue();
+ }
+ }
+ }
+
+ public class DDWayPoint : BaseAddon
+ {
+ private DDTeamInfo m_TeamOwner;
+ private DDGame m_Game;
+
+ [Constructable]
+ public DDWayPoint()
+ {
+ this.ItemID = 0x519;
+ this.Visible = true;
+ this.Name = "SET MY NAME";
+
+ AddComponent( new DDStep( 0x7A8 ), -1, -1, -5 );
+ AddComponent( new DDStep( 0x7A6 ), 0, -1, -5 );
+ AddComponent( new DDStep( 0x7AA ), 1, -1, -5 );
+
+ AddComponent( new DDStep( 0x7A5 ), 1, 0, -5 );
+
+ AddComponent( new DDStep( 0x7A9 ), 1, 1, -5 );
+ AddComponent( new DDStep( 0x7A4 ), 0, 1, -5 );
+ AddComponent( new DDStep( 0x7AB ), -1, 1, -5 );
+
+ AddComponent( new DDStep( 0x7A7 ), -1, 0, -5 );
+
+ SetUncapturableHue();
+ }
+
+ public DDWayPoint( Serial serial ) : base(serial)
+ {
+ }
+
+ public override void Serialize( GenericWriter writer )
+ {
+ base.Serialize( writer );
+
+ writer.Write( (int)0 );
+ }
+
+ public override void Deserialize( GenericReader reader )
+ {
+ base.Deserialize(reader);
+
+ int version = reader.ReadInt();
+ }
+
+ public override bool ShareHue{ get{ return false; } }
+
+ public DDGame Game
+ {
+ get{ return m_Game; }
+ set
+ {
+ m_Game = value;
+ m_TeamOwner = null;
+
+ if ( m_Game != null )
+ SetNonCaptureHue();
+ else
+ SetUncapturableHue();
+ }
+ }
+
+ public DDTeamInfo TeamOwner
+ {
+ get{ return m_TeamOwner; }
+ set
+ {
+ m_TeamOwner = value;
+
+ SetNonCaptureHue();
+ }
+ }
+
+ public const int UncapturableHue = 0x497;
+ public const int NonCapturedHue = 0x38A;
+
+ public void SetUncapturableHue()
+ {
+ for (int i=0;i= m.StamMax)
+ m.Stam -= 5;
+ }
+
+ return false;
+ }
+
+ public override bool OnMoveOff(Mobile m)
+ {
+ if (base.OnMoveOff(m))
+ {
+ if (m_King == m)
+ DeKingify();
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public virtual void OnKingDied(Mobile king, KHTeamInfo kingTeam, Mobile killer, KHTeamInfo killerTeam)
+ {
+ if (m_Game != null && CapturesSoFar > 0 && killer != null && king != null && kingTeam != null && killerTeam != null)
+ {
+ string kingName = king.Name;
+ if (kingName == null)
+ kingName = "";
+ string killerName = killer.Name;
+ if (killerName == null)
+ killerName = "";
+
+ m_Game.Alert("{0} ({1}) was dethroned by {2} ({3})!", kingName, kingTeam.Name, killerName, killerTeam.Name);
+ }
+
+ DeKingify();
+ }
+
+ private void DeKingify()
+ {
+ PublicOverheadMessage(MessageType.Regular, 0x0481, false, "Free!");
+
+ if (m_KingTimer != null)
+ m_KingTimer.Stop();
+
+ m_King = null;
+ }
+
+ private void ReKingify(Mobile m)
+ {
+ KHTeamInfo ti = null;
+ if (m_Game == null || m == null)
+ return;
+
+ ti = m_Game.GetTeamInfo(m);
+ if (ti == null)
+ return;
+
+ m_King = m;
+
+ if (m_KingTimer == null)
+ m_KingTimer = new KingTimer(this);
+ m_KingTimer.Stop();
+ m_KingTimer.StartHillTicker();
+
+ if (m_King.Name != null)
+ PublicOverheadMessage(MessageType.Regular, 0x0481, false, String.Format("Taken by {0}!", m_King.Name));
+ }
+
+ private class KingTimer : Timer
+ {
+ private HillOfTheKing m_Hill;
+ private int m_Total;
+ private int m_Counter;
+
+ public int Captures { get { return m_Total; } }
+
+ public KingTimer(HillOfTheKing hill)
+ : base(TimeSpan.FromSeconds(1.0), TimeSpan.FromSeconds(1.0))
+ {
+ m_Hill = hill;
+ m_Total = 0;
+ m_Counter = 0;
+
+ Priority = TimerPriority.FiftyMS;
+ }
+
+ public void StartHillTicker()
+ {
+ m_Total = 0;
+ m_Counter = 0;
+
+ Start();
+ }
+
+ protected override void OnTick()
+ {
+ KHTeamInfo ti = null;
+ KHPlayerInfo pi = null;
+
+ if (m_Hill == null || m_Hill.Deleted || m_Hill.Game == null)
+ {
+ Stop();
+ return;
+ }
+
+ if (m_Hill.King == null || m_Hill.King.Deleted || !m_Hill.King.Alive)
+ {
+ m_Hill.DeKingify();
+ Stop();
+ return;
+ }
+
+ ti = m_Hill.Game.GetTeamInfo(m_Hill.King);
+ if (ti != null)
+ pi = ti[m_Hill.King];
+
+ if (ti == null || pi == null)
+ {
+ // error, bail
+ m_Hill.DeKingify();
+ Stop();
+ return;
+ }
+
+ m_Counter++;
+
+ m_Hill.King.RevealingAction();
+
+ if (m_Counter >= m_Hill.ScoreInterval)
+ {
+ string hill = m_Hill.Name;
+ string king = m_Hill.King.Name;
+ if (king == null)
+ king = "";
+
+ if (hill == null || hill == "")
+ hill = "the hill";
+
+ m_Hill.Game.Alert("{0} ({1}) is king of {2}!", king, ti.Name, hill);
+
+ m_Hill.PublicOverheadMessage(MessageType.Regular, 0x0481, false, "Capture!");
+
+ pi.Captures++;
+ m_Total++;
+
+ pi.Score += m_Counter;
+
+ m_Counter = 0;
+ }
+ else
+ {
+ m_Hill.PublicOverheadMessage(MessageType.Regular, 0x0481, false, (m_Hill.ScoreInterval - m_Counter).ToString());
+ }
+ }
+ }
+ }
+
+ public class KHBoard : Item
+ {
+ public KHGame m_Game;
+ private KHController m_Controller;
+
+ [Constructable]
+ public KHBoard()
+ : base(7774)
+ {
+ Name = "King of the Hill Scoreboard";
+ Movable = false;
+ }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public KHController Controller
+ {
+ get { return m_Controller; }
+ set
+ {
+ if (m_Controller != value)
+ {
+ if (m_Controller != null)
+ m_Controller.RemoveBoard(this);
+ m_Controller = value;
+ if (m_Controller != null)
+ m_Controller.AddBoard(this);
+ }
+ }
+ }
+
+ public override void OnDoubleClick(Mobile from)
+ {
+ if (m_Game != null)
+ {
+ from.CloseGump(typeof(KHBoardGump));
+ from.SendGump(new KHBoardGump(from, m_Game));
+ }
+ else
+ {
+ from.SendMessage("There is no King of the Hill game in progress.");
+ }
+ }
+
+ public KHBoard(Serial serial)
+ : base(serial)
+ {
+ }
+
+ public override void Serialize(GenericWriter writer)
+ {
+ base.Serialize(writer);
+
+ writer.Write((int)0);
+
+ writer.Write(m_Controller);
+ }
+
+ public override void Deserialize(GenericReader reader)
+ {
+ base.Deserialize(reader);
+
+ int version = reader.ReadInt();
+
+ switch (version)
+ {
+ case 0:
+ {
+ m_Controller = reader.ReadItem() as KHController;
+ break;
+ }
+ }
+ }
+ }
+
+ public sealed class KHBoardGump : Gump
+ {
+ 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);
+ }
+
+ private const int LabelColor32 = 0xFFFFFF;
+ private const int BlackColor32 = 0x000000;
+
+ private KHGame m_Game;
+
+ public KHBoardGump(Mobile mob, KHGame game)
+ : base(60, 60)
+ {
+ m_Game = game;
+
+ KHTeamInfo ourTeam = game.GetTeamInfo(mob);
+
+ ArrayList entries = new ArrayList();
+
+ for (int i = 0; i < game.Context.Participants.Count; ++i)
+ {
+ KHTeamInfo teamInfo = game.Controller.TeamInfo[i % game.Controller.TeamInfo.Length];
+
+ if (teamInfo == null)
+ continue;
+
+ entries.Add(teamInfo);
+ }
+
+ entries.Sort();
+ /*
+ delegate( IRankedCTF a, IRankedCTF b )
+ {
+ return b.Score - a.Score;
+ } );*/
+
+ int height = 73 + (entries.Count * 75) + 28;
+
+ Closable = false;
+
+ AddPage(0);
+
+ AddBackground(1, 1, 398, height, 3600);
+
+ AddImageTiled(16, 15, 369, height - 29, 3604);
+
+ for (int i = 0; i < entries.Count; i += 1)
+ AddImageTiled(22, 58 + (i * 75), 357, 70, 0x2430);
+
+ AddAlphaRegion(16, 15, 369, height - 29);
+
+ AddImage(215, -45, 0xEE40);
+ //AddImage( 330, 141, 0x8BA );
+
+ AddBorderedText(22, 22, 294, 20, Center("King of the Hill Scoreboard"), LabelColor32, BlackColor32);
+
+ AddImageTiled(32, 50, 264, 1, 9107);
+ AddImageTiled(42, 52, 264, 1, 9157);
+
+ for (int i = 0; i < entries.Count; ++i)
+ {
+ KHTeamInfo teamInfo = entries[i] as KHTeamInfo;
+
+ AddImage(30, 70 + (i * 75), 10152);
+ AddImage(30, 85 + (i * 75), 10151);
+ AddImage(30, 100 + (i * 75), 10151);
+ AddImage(30, 106 + (i * 75), 10154);
+
+ AddImage(24, 60 + (i * 75), teamInfo == ourTeam ? 9730 : 9727, teamInfo.Color - 1);
+
+ int nameColor = LabelColor32;
+ int borderColor = BlackColor32;
+
+ switch (teamInfo.Color)
+ {
+ case 0x47E:
+ nameColor = 0xFFFFFF;
+ break;
+
+ case 0x4F2:
+ nameColor = 0x3399FF;
+ break;
+
+ case 0x4F7:
+ nameColor = 0x33FF33;
+ break;
+
+ case 0x4FC:
+ nameColor = 0xFF00FF;
+ break;
+
+ case 0x021:
+ nameColor = 0xFF3333;
+ break;
+
+ case 0x01A:
+ nameColor = 0xFF66FF;
+ break;
+
+ case 0x455:
+ nameColor = 0x333333;
+ borderColor = 0xFFFFFF;
+ break;
+ }
+
+ AddBorderedText(60, 65 + (i * 75), 250, 20, String.Format("{0}: {1}", LadderGump.Rank(1 + i), teamInfo.Name), nameColor, borderColor);
+
+ AddBorderedText(50 + 10, 85 + (i * 75), 100, 20, "Score:", 0xFFC000, BlackColor32);
+ AddBorderedText(50 + 15, 105 + (i * 75), 100, 20, teamInfo.Score.ToString("N0"), 0xFFC000, BlackColor32);
+
+ AddBorderedText(110 + 10, 85 + (i * 75), 100, 20, "Kills:", 0xFFC000, BlackColor32);
+ AddBorderedText(110 + 15, 105 + (i * 75), 100, 20, teamInfo.Kills.ToString("N0"), 0xFFC000, BlackColor32);
+
+ AddBorderedText(160 + 10, 85 + (i * 75), 100, 20, "Captures:", 0xFFC000, BlackColor32);
+ AddBorderedText(160 + 15, 105 + (i * 75), 100, 20, teamInfo.Captures.ToString("N0"), 0xFFC000, BlackColor32);
+
+ string leader = null;
+ if (teamInfo.Leader != null)
+ leader = teamInfo.Leader.Name;
+ if (leader == null)
+ leader = "(none)";
+
+ AddBorderedText(235 + 10, 85 + (i * 75), 250, 20, "Leader:", 0xFFC000, BlackColor32);
+ AddBorderedText(235 + 15, 105 + (i * 75), 250, 20, leader, 0xFFC000, BlackColor32);
+ }
+
+ AddButton(314, height - 42, 247, 248, 1, GumpButtonType.Reply, 0);
+ }
+ }
+
+ public sealed class KHPlayerInfo : IRankedCTF, IComparable
+ {
+ private KHTeamInfo m_TeamInfo;
+
+ private Mobile m_Player;
+
+ private int m_Kills;
+ private int m_Captures;
+ private int m_Score;
+
+ public KHPlayerInfo(KHTeamInfo teamInfo, Mobile player)
+ {
+ m_TeamInfo = teamInfo;
+ m_Player = player;
+ }
+
+ public Mobile Player { get { return m_Player; } }
+
+ public int CompareTo(object obj)
+ {
+ KHPlayerInfo pi = (KHPlayerInfo)obj;
+ int res = pi.Score.CompareTo(this.Score);
+ if (res == 0)
+ {
+ res = pi.Captures.CompareTo(this.Captures);
+
+ if (res == 0)
+ res = pi.Kills.CompareTo(this.Kills);
+ }
+ return res;
+ }
+
+ public string Name
+ {
+ get
+ {
+ if (m_Player == null || m_Player.Name == null)
+ return "";
+ return m_Player.Name;
+ }
+ }
+
+ public int Kills
+ {
+ get
+ {
+ return m_Kills;
+ }
+ set
+ {
+ m_TeamInfo.Kills += (value - m_Kills);
+ m_Kills = value;
+ }
+ }
+
+ public int Captures
+ {
+ get
+ {
+ return m_Captures;
+ }
+ set
+ {
+ m_TeamInfo.Captures += (value - m_Captures);
+ m_Captures = value;
+ }
+ }
+
+ public int Score
+ {
+ get
+ {
+ return m_Score;
+ }
+ set
+ {
+ m_TeamInfo.Score += (value - m_Score);
+ m_Score = value;
+
+ if (m_TeamInfo.Leader == null || m_Score > m_TeamInfo.Leader.Score)
+ m_TeamInfo.Leader = this;
+ }
+ }
+ }
+
+ [PropertyObject]
+ public sealed class KHTeamInfo : IRankedCTF, IComparable
+ {
+ private KHGame m_Game;
+ private int m_TeamID;
+
+ private int m_Color;
+ private string m_Name;
+
+ private int m_Kills;
+ private int m_Captures;
+
+ private int m_Score;
+
+ private Hashtable m_Players;
+
+ public int CompareTo(object obj)
+ {
+ KHTeamInfo ti = (KHTeamInfo)obj;
+ int res = ti.Score.CompareTo(this.Score);
+ if (res == 0)
+ {
+ res = ti.Captures.CompareTo(this.Captures);
+
+ if (res == 0)
+ res = ti.Kills.CompareTo(this.Kills);
+ }
+ return res;
+ }
+
+ public string Name
+ {
+ get
+ {
+ if (m_Name == null)
+ return "(null) Team";
+ return String.Format("{0} Team", m_Name);
+ }
+ }
+
+ public KHGame Game { get { return m_Game; } set { m_Game = value; } }
+ public int TeamID { get { return m_TeamID; } }
+
+ public int Kills { get { return m_Kills; } set { m_Kills = value; } }
+ public int Captures { get { return m_Captures; } set { m_Captures = value; } }
+ public int Score { get { return m_Score; } set { m_Score = value; } }
+
+ private KHPlayerInfo m_Leader;
+
+ public KHPlayerInfo Leader
+ {
+ get { return m_Leader; }
+ set { m_Leader = value; }
+ }
+
+ public Hashtable Players
+ {
+ get { return m_Players; }
+ }
+
+ public KHPlayerInfo this[Mobile mob]
+ {
+ get
+ {
+ if (mob == null)
+ return null;
+
+ KHPlayerInfo val = m_Players[mob] as KHPlayerInfo;
+
+ if (val == null)
+ m_Players[mob] = val = new KHPlayerInfo(this, mob);
+
+ return val;
+ }
+ }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public int Color
+ {
+ get { return m_Color; }
+ set { m_Color = value; }
+ }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public string TeamName
+ {
+ get { return m_Name; }
+ set { m_Name = value; }
+ }
+
+ public KHTeamInfo(int teamID)
+ {
+ m_TeamID = teamID;
+ m_Players = new Hashtable();
+ }
+
+ public void Reset()
+ {
+ m_Kills = 0;
+ m_Captures = 0;
+ m_Score = 0;
+
+ m_Leader = null;
+
+ m_Players.Clear();
+ }
+
+ public KHTeamInfo(int teamID, GenericReader ip)
+ {
+ m_TeamID = teamID;
+ m_Players = new Hashtable();
+
+ int version = ip.ReadEncodedInt();
+
+ switch (version)
+ {
+ case 0:
+ {
+ m_Name = ip.ReadString();
+ m_Color = ip.ReadEncodedInt();
+ break;
+ }
+ }
+ }
+
+ public void Serialize(GenericWriter op)
+ {
+ op.WriteEncodedInt(0); // version
+
+ op.Write(m_Name);
+ op.WriteEncodedInt(m_Color);
+ }
+
+ public override string ToString()
+ {
+ if (m_Name != null)
+ return String.Format("({0}) ...", this.Name);
+ else
+ return "...";
+ }
+ }
+
+ public sealed class KHController : EventController
+ {
+ private KHTeamInfo[] m_TeamInfo;
+ private HillOfTheKing[] m_Hills;
+ private ArrayList m_Boards;
+ private TimeSpan m_Duration;
+ private int m_ScoreInterval;
+
+ public KHTeamInfo[] TeamInfo { get { return m_TeamInfo; } }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public KHTeamInfo Team1_W { get { return m_TeamInfo[0]; } set { } }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public KHTeamInfo Team2_E { get { return m_TeamInfo[1]; } set { } }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public KHTeamInfo Team3_N { get { return m_TeamInfo[2]; } set { } }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public KHTeamInfo Team4_S { get { return m_TeamInfo[3]; } set { } }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public KHTeamInfo Team5_NW { get { return m_TeamInfo[4]; } set { } }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public KHTeamInfo Team6_SE { get { return m_TeamInfo[5]; } set { } }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public KHTeamInfo Team7_SW { get { return m_TeamInfo[6]; } set { } }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public KHTeamInfo Team8_NE { get { return m_TeamInfo[7]; } set { } }
+
+ public HillOfTheKing[] Hills { get { return m_Hills; } }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public HillOfTheKing Hill1 { get { return m_Hills[0]; } set { m_Hills[0] = value; } }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public HillOfTheKing Hill2 { get { return m_Hills[1]; } set { m_Hills[1] = value; } }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public HillOfTheKing Hill3 { get { return m_Hills[2]; } set { m_Hills[2] = value; } }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public HillOfTheKing Hill4 { get { return m_Hills[3]; } set { m_Hills[3] = value; } }
+
+ public ArrayList Boards { get { return m_Boards; } }
+
+ [CommandProperty(AccessLevel.GameMaster)]
+ public TimeSpan Duration
+ {
+ get { return m_Duration; }
+ set { m_Duration = value; }
+ }
+
+ public override string Title
+ {
+ get { return "King of the Hill"; }
+ }
+
+ public override string GetTeamName(int teamID)
+ {
+ return m_TeamInfo[teamID % m_TeamInfo.Length].Name;
+ }
+
+ public override EventGame Construct(DuelContext context)
+ {
+ return new KHGame(this, context);
+ }
+
+ public void RemoveBoard(KHBoard b)
+ {
+ if (b != null)
+ {
+ m_Boards.Remove(b);
+ b.m_Game = null;
+ }
+ }
+
+ public void AddBoard(KHBoard b)
+ {
+ if (b != null)
+ m_Boards.Add(b);
+ }
+
+ [Constructable]
+ public KHController()
+ {
+ Visible = false;
+ Movable = false;
+
+ Name = "King of the Hill Controller";
+
+ m_Duration = TimeSpan.FromMinutes(30.0);
+ m_Boards = new ArrayList();
+ m_Hills = new HillOfTheKing[4];
+ m_TeamInfo = new KHTeamInfo[8];
+
+ for (int i = 0; i < m_TeamInfo.Length; ++i)
+ m_TeamInfo[i] = new KHTeamInfo(i);
+ }
+
+ public KHController(Serial serial)
+ : base(serial)
+ {
+ }
+
+ public override void Serialize(GenericWriter writer)
+ {
+ base.Serialize(writer);
+
+ writer.Write((int)0);
+
+ writer.WriteEncodedInt(m_ScoreInterval);
+ writer.Write(m_Duration);
+
+ writer.WriteItemList(m_Boards, true);
+
+ writer.WriteEncodedInt(m_Hills.Length);
+ for (int i = 0; i < m_Hills.Length; ++i)
+ writer.Write(m_Hills[i]);
+
+ writer.WriteEncodedInt(m_TeamInfo.Length);
+ for (int i = 0; i < m_TeamInfo.Length; ++i)
+ m_TeamInfo[i].Serialize(writer);
+ }
+
+ public override void Deserialize(GenericReader reader)
+ {
+ base.Deserialize(reader);
+
+ int version = reader.ReadInt();
+
+ switch (version)
+ {
+ case 0:
+ {
+ m_ScoreInterval = reader.ReadEncodedInt();
+
+ m_Duration = reader.ReadTimeSpan();
+
+ m_Boards = reader.ReadItemList();
+
+ m_Hills = new HillOfTheKing[reader.ReadEncodedInt()];
+ for (int i = 0; i < m_Hills.Length; ++i)
+ m_Hills[i] = reader.ReadItem() as HillOfTheKing;
+
+ m_TeamInfo = new KHTeamInfo[reader.ReadEncodedInt()];
+ for (int i = 0; i < m_TeamInfo.Length; ++i)
+ m_TeamInfo[i] = new KHTeamInfo(i, reader);
+
+ break;
+ }
+ }
+ }
+ }
+
+ public sealed class KHGame : EventGame
+ {
+ private KHController m_Controller;
+
+ public KHController Controller { get { return m_Controller; } }
+
+ public override bool CantDoAnything(Mobile mob)
+ {
+ if (mob != null && GetTeamInfo(mob) != null && m_Controller != null)
+ {
+ for (int i = 0; i < m_Controller.Hills.Length; i++)
+ {
+ if (m_Controller.Hills[i] != null && m_Controller.Hills[i].King == mob)
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public void Alert(string text)
+ {
+ if (m_Context.m_Tournament != null)
+ m_Context.m_Tournament.Alert(text);
+
+ for (int i = 0; i < m_Context.Participants.Count; ++i)
+ {
+ Participant p = m_Context.Participants[i] as Participant;
+
+ for (int j = 0; j < p.Players.Length; ++j)
+ {
+ if (p.Players[j] != null)
+ p.Players[j].Mobile.SendMessage(0x35, text);
+ }
+ }
+ }
+
+ public void Alert(string format, params object[] args)
+ {
+ Alert(String.Format(format, args));
+ }
+
+ public KHGame(KHController controller, DuelContext context)
+ : base(context)
+ {
+ m_Controller = controller;
+ }
+
+ public Map Facet
+ {
+ get
+ {
+ if (m_Context != null && m_Context.Arena != null)
+ return m_Context.Arena.Facet;
+
+ return m_Controller.Map;
+ }
+ }
+
+ public KHTeamInfo GetTeamInfo(Mobile mob)
+ {
+ int teamID = GetTeamID(mob);
+
+ if (teamID >= 0)
+ return m_Controller.TeamInfo[teamID % m_Controller.TeamInfo.Length];
+
+ return null;
+ }
+
+ public int GetTeamID(Mobile mob)
+ {
+ PlayerMobile pm = mob as PlayerMobile;
+
+ if (pm == null)
+ {
+ if (mob is BaseCreature)
+ return ((BaseCreature)mob).Team - 1;
+ else
+ return -1;
+ }
+
+ if (pm.DuelContext == null || pm.DuelContext != m_Context)
+ return -1;
+
+ if (pm.DuelPlayer == null || pm.DuelPlayer.Eliminated)
+ return -1;
+
+ return pm.DuelContext.Participants.IndexOf(pm.DuelPlayer.Participant);
+ }
+
+ public int GetColor(Mobile mob)
+ {
+ KHTeamInfo teamInfo = GetTeamInfo(mob);
+
+ if (teamInfo != null)
+ return teamInfo.Color;
+
+ return -1;
+ }
+
+ private void ApplyHues(Participant p, int hueOverride)
+ {
+ for (int i = 0; i < p.Players.Length; ++i)
+ {
+ if (p.Players[i] != null)
+ p.Players[i].Mobile.SolidHueOverride = hueOverride;
+ }
+ }
+
+ public void DelayBounce(TimeSpan ts, Mobile mob, Container corpse)
+ {
+ Timer.DelayCall(ts, new TimerStateCallback(DelayBounce_Callback), new object[] { mob, corpse });
+ }
+
+ private void DelayBounce_Callback(object state)
+ {
+ object[] states = (object[])state;
+ Mobile mob = (Mobile)states[0];
+ Container corpse = (Container)states[1];
+
+ DuelPlayer dp = null;
+
+ if (mob is PlayerMobile)
+ dp = (mob as PlayerMobile).DuelPlayer;
+
+ m_Context.RemoveAggressions(mob);
+
+ if (dp != null && !dp.Eliminated)
+ mob.MoveToWorld(m_Context.Arena.GetBaseStartPoint(GetTeamID(mob)), Facet);
+ else
+ m_Context.SendOutside(mob);
+
+ m_Context.Refresh(mob, corpse);
+ DuelContext.Debuff(mob);
+ DuelContext.CancelSpell(mob);
+ mob.Frozen = false;
+
+ if (corpse != null && !corpse.Deleted)
+ Timer.DelayCall(TimeSpan.FromSeconds(30), new TimerCallback(corpse.Delete));
+ }
+
+ public override bool OnDeath(Mobile mob, Container corpse)
+ {
+ Mobile killer = mob.FindMostRecentDamager(false);
+ KHTeamInfo teamInfo = null;
+ KHTeamInfo victInfo = GetTeamInfo(mob);
+ int bonus = 0;
+
+ if (killer != null && killer.Player)
+ teamInfo = GetTeamInfo(killer);
+
+ for (int i = 0; i < m_Controller.Hills.Length; i++)
+ {
+ if (m_Controller.Hills[i] == null)
+ continue;
+
+ if (m_Controller.Hills[i].King == mob)
+ {
+ bonus += m_Controller.Hills[i].CapturesSoFar;
+ m_Controller.Hills[i].OnKingDied(mob, victInfo, killer, teamInfo);
+ }
+
+ if (m_Controller.Hills[i].King == killer)
+ bonus += 2;
+ }
+
+ if (teamInfo != null && teamInfo != victInfo)
+ {
+ KHPlayerInfo playerInfo = teamInfo[killer];
+
+ if (playerInfo != null)
+ {
+ playerInfo.Kills += 1;
+ playerInfo.Score += 1 + bonus;
+ }
+ }
+
+ mob.CloseGump(typeof(KHBoardGump));
+ mob.SendGump(new KHBoardGump(mob, this));
+
+ m_Context.Requip(mob, corpse);
+ DelayBounce(TimeSpan.FromSeconds(30.0), mob, corpse);
+
+ return false;
+ }
+
+ private Timer m_FinishTimer;
+
+ public override void OnStart()
+ {
+ for (int i = 0; i < m_Controller.TeamInfo.Length; ++i)
+ {
+ KHTeamInfo teamInfo = m_Controller.TeamInfo[i];
+
+ teamInfo.Game = this;
+ teamInfo.Reset();
+ }
+
+ for (int i = 0; i < m_Context.Participants.Count; ++i)
+ ApplyHues(m_Context.Participants[i] as Participant, m_Controller.TeamInfo[i % m_Controller.TeamInfo.Length].Color);
+
+ if (m_FinishTimer != null)
+ m_FinishTimer.Stop();
+
+ for (int i = 0; i < m_Controller.Hills.Length; i++)
+ {
+ if (m_Controller.Hills[i] != null)
+ m_Controller.Hills[i].Game = this;
+ }
+
+ foreach (KHBoard board in m_Controller.Boards)
+ {
+ if (board != null && !board.Deleted)
+ board.m_Game = this;
+ }
+
+ m_FinishTimer = Timer.DelayCall(m_Controller.Duration, new TimerCallback(Finish_Callback));
+ }
+
+ private void Finish_Callback()
+ {
+ ArrayList teams = new ArrayList();
+
+ for (int i = 0; i < m_Context.Participants.Count; ++i)
+ {
+ KHTeamInfo teamInfo = m_Controller.TeamInfo[i % m_Controller.TeamInfo.Length];
+
+ if (teamInfo == null)
+ continue;
+
+ teams.Add(teamInfo);
+ }
+
+ teams.Sort();
+
+ Tournament tourny = m_Context.m_Tournament;
+
+ StringBuilder sb = new StringBuilder();
+
+ if (tourny != null && tourny.TournyType == TournyType.FreeForAll)
+ {
+ sb.Append(m_Context.Participants.Count * tourny.PlayersPerParticipant);
+ sb.Append("-man FFA");
+ }
+ else if (tourny != null && tourny.TournyType == TournyType.RandomTeam)
+ {
+ sb.Append(tourny.ParticipantsPerMatch);
+ sb.Append("-team");
+ }
+ else if (tourny != null && tourny.TournyType == TournyType.RedVsBlue)
+ {
+ sb.Append("Red v Blue");
+ }
+ else if (tourny != null)
+ {
+ for (int i = 0; i < tourny.ParticipantsPerMatch; ++i)
+ {
+ if (sb.Length > 0)
+ sb.Append('v');
+
+ sb.Append(tourny.PlayersPerParticipant);
+ }
+ }
+
+ if (m_Controller != null)
+ sb.Append(' ').Append(m_Controller.Title);
+
+ string title = sb.ToString();
+
+ KHTeamInfo winner = (KHTeamInfo)(teams.Count > 0 ? teams[0] : null);
+
+ for (int i = 0; i < teams.Count; ++i)
+ {
+ TrophyRank rank = TrophyRank.Bronze;
+
+ if (i == 0)
+ rank = TrophyRank.Gold;
+ else if (i == 1)
+ rank = TrophyRank.Silver;
+
+ KHPlayerInfo leader = ((KHTeamInfo)teams[i]).Leader;
+
+ foreach (KHPlayerInfo pl in ((KHTeamInfo)teams[i]).Players.Values)
+ {
+ Mobile mob = pl.Player;
+
+ if (mob == null)
+ continue;
+
+ sb = new StringBuilder();
+
+ sb.Append(title);
+
+ if (pl == leader)
+ sb.Append(" Leader");
+
+ if (pl.Score > 0)
+ {
+ sb.Append(": ");
+
+ sb.Append(pl.Score.ToString("N0"));
+ sb.Append(pl.Score == 1 ? " point" : " points");
+
+ sb.Append(", ");
+ sb.Append(pl.Kills.ToString("N0"));
+ sb.Append(pl.Kills == 1 ? " kill" : " kills");
+
+ if (pl.Captures > 0)
+ {
+ sb.Append(", ");
+ sb.Append(pl.Captures.ToString("N0"));
+ sb.Append(pl.Captures == 1 ? " capture" : " captures");
+ }
+ }
+
+ Item item = new Trophy(sb.ToString(), rank);
+
+ if (pl == leader)
+ item.ItemID = 4810;
+
+ item.Name = String.Format("{0}, {1}", item.Name, ((KHTeamInfo)teams[i]).Name.ToLower());
+
+ if (!mob.PlaceInBackpack(item))
+ mob.BankBox.DropItem(item);
+
+ int cash = pl.Score * 250;
+
+ 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 game.", rank.ToString().ToLower(), cash);
+ }
+ else
+ {
+ mob.SendMessage("You have been awarded a {0} trophy for your participation in this game.", rank.ToString().ToLower());
+ }
+ }
+ }
+
+ for (int i = 0; i < m_Context.Participants.Count; ++i)
+ {
+ Participant p = m_Context.Participants[i] as Participant;
+
+ if (p == null || p.Players == null)
+ continue;
+
+ for (int j = 0; j < p.Players.Length; ++j)
+ {
+ DuelPlayer dp = p.Players[j];
+
+ if (dp != null && dp.Mobile != null)
+ {
+ dp.Mobile.CloseGump(typeof(KHBoardGump));
+ dp.Mobile.SendGump(new KHBoardGump(dp.Mobile, this));
+ }
+ }
+
+ if (i == winner.TeamID)
+ continue;
+
+ if (p != null && p.Players != null)
+ {
+ for (int j = 0; j < p.Players.Length; ++j)
+ {
+ if (p.Players[j] != null)
+ p.Players[j].Eliminated = true;
+ }
+ }
+ }
+
+ m_Context.Finish(m_Context.Participants[winner.TeamID] as Participant);
+ }
+
+ public override void OnStop()
+ {
+ for (int i = 0; i < m_Controller.TeamInfo.Length; ++i)
+ m_Controller.TeamInfo[i].Game = null;
+
+ for (int i = 0; i < m_Controller.Hills.Length; ++i)
+ {
+ if (m_Controller.Hills[i] != null)
+ m_Controller.Hills[i].Game = null;
+ }
+
+ foreach (KHBoard board in m_Controller.Boards)
+ {
+ if (board != null)
+ board.m_Game = null;
+ }
+
+ for (int i = 0; i < m_Context.Participants.Count; ++i)
+ ApplyHues(m_Context.Participants[i] as Participant, -1);
+
+ if (m_FinishTimer != null)
+ m_FinishTimer.Stop();
+ m_FinishTimer = null;
+ }
+ }
+}
diff --git a/Scripts/Engines/ConPVP/Tournament.cs b/Scripts/Engines/ConPVP/Tournament.cs
index e173c3e5a..9f5ed19d8 100644
--- a/Scripts/Engines/ConPVP/Tournament.cs
+++ b/Scripts/Engines/ConPVP/Tournament.cs
@@ -9,6 +9,10 @@ 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
{
@@ -80,6 +84,11 @@ namespace Server.Engines.ConPVP
return;
}
+ if ( tourny.IsFactionRestricted && Faction.Find( m ) == null )
+ {
+ return;
+ }
+
if ( tourny.HasParticipant( m ) )
return;
@@ -211,6 +220,17 @@ namespace Server.Engines.ConPVP
}
}
+ 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 )
@@ -398,7 +418,13 @@ namespace Server.Engines.ConPVP
}
else if ( tourny.TournyType == TournyType.RandomTeam )
{
- sb.Append( "Team" );
+ 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 )
{
@@ -637,6 +663,17 @@ namespace Server.Engines.ConPVP
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 )
@@ -933,6 +970,11 @@ namespace Server.Engines.ConPVP
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" );
@@ -1326,7 +1368,8 @@ namespace Server.Engines.ConPVP
Standard,
FreeForAll,
RandomTeam,
- RedVsBlue
+ RedVsBlue,
+ Faction
}
[PropertyObject]
@@ -1335,6 +1378,9 @@ namespace Server.Engines.ConPVP
private int m_ParticipantsPerMatch;
private int m_PlayersPerParticipant;
private int m_LevelRequirement;
+
+ private bool m_FactionRestricted;
+
private TournyPyramid m_Pyramid;
private Ruleset m_Ruleset;
@@ -1428,6 +1474,13 @@ namespace Server.Engines.ConPVP
set{ m_LevelRequirement = value; }
}
+ [CommandProperty( AccessLevel.GameMaster )]
+ public bool FactionRestricted
+ {
+ get{ return m_FactionRestricted; }
+ set{ m_FactionRestricted = value; }
+ }
+
[CommandProperty( AccessLevel.GameMaster )]
public TimeSpan SignupPeriod
{
@@ -1478,6 +1531,12 @@ namespace Server.Engines.ConPVP
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 )
@@ -1493,7 +1552,9 @@ namespace Server.Engines.ConPVP
public void Serialize( GenericWriter writer )
{
- writer.WriteEncodedInt( (int) 4 ); // version
+ writer.WriteEncodedInt( (int) 5 ); // version
+
+ writer.Write( (bool) m_FactionRestricted );
writer.Write( (Item) m_EventController );
@@ -1516,6 +1577,11 @@ namespace Server.Engines.ConPVP
switch ( version )
{
+ case 5: {
+ m_FactionRestricted = reader.ReadBool();
+
+ goto case 4;
+ }
case 4:
{
m_EventController = reader.ReadItem() as EventController;
@@ -1884,7 +1950,12 @@ namespace Server.Engines.ConPVP
else if ( m_TournyType == TournyType.RandomTeam )
{
sb.Append( m_ParticipantsPerMatch );
- sb.Append( "-team" );
+ sb.Append( "-Team" );
+ }
+ else if ( m_TournyType == TournyType.Faction )
+ {
+ sb.Append( m_ParticipantsPerMatch );
+ sb.Append( "-Team Faction" );
}
else if ( m_TournyType == TournyType.RedVsBlue )
{
@@ -1994,8 +2065,11 @@ namespace Server.Engines.ConPVP
}
else
{
- Alert( "Is this all?", "Pitiful. Signup extended." );
- m_SignupStart = DateTime.UtcNow;
+ /*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) )
@@ -2019,6 +2093,42 @@ namespace Server.Engines.ConPVP
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
@@ -2097,6 +2207,42 @@ namespace Server.Engines.ConPVP
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
@@ -2197,6 +2343,56 @@ namespace Server.Engines.ConPVP
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];
@@ -2693,12 +2889,18 @@ namespace Server.Engines.ConPVP
}
else if ( tourny.TournyType == TournyType.RandomTeam )
{
- sb.Append( "Team" );
+ 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 )
@@ -3063,7 +3265,7 @@ namespace Server.Engines.ConPVP
sb.Append( txt );
}
}
- else if ( m_Tournament.EventController != null || m_Tournament.TournyType == TournyType.RandomTeam || m_Tournament.TournyType == TournyType.RedVsBlue )
+ 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 )
{
@@ -3077,6 +3279,42 @@ namespace Server.Engines.ConPVP
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 );
@@ -3131,7 +3369,7 @@ namespace Server.Engines.ConPVP
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 )
+ 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 )
{
@@ -3141,6 +3379,42 @@ namespace Server.Engines.ConPVP
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 ) );
}
diff --git a/Scripts/Scripts.csproj b/Scripts/Scripts.csproj
index 9148ed93b..1e53c61f5 100644
--- a/Scripts/Scripts.csproj
+++ b/Scripts/Scripts.csproj
@@ -181,7 +181,11 @@
+
+
+
+