Exemplo n.º 1
0
 private void RemoveUnit(Unit Unit, bool Animation)
 {
     Units.Remove(Unit);
 }
Exemplo n.º 2
0
 // checks if a unit can move to a target coord
 public bool UnitCanMoveToCoord(Unit Unit, Coord TargetCoord)
 {
     return TargetCoord.InList(Move.ConvertToCoordList(GetPossibleFieldsForUnit(Unit)));
 }
Exemplo n.º 3
0
        protected List<Move> GetPossibleFieldsForUnitHelper(
            Unit Unit,
            Coord Position,
            int RangeRemaining,
            bool AttackCalculation,
            Coord.Direction ComingFrom,
            List<Coord> Way)
        {
            List<Move> PossibleFields = new List<Move>();
            if (Map.CoordOnMap(Position) /*&& (GetUnitByCoord(Position) == null || GetUnitByCoord(Position).Fraction == Unit.Fraction)*/)
            {
                int Cost = (AttackCalculation) ? 1 : Unit.MovementCostOn(this.Map.GetSurfaceByCoord(Position).Type);
                if (Cost != -1 && RangeRemaining - Cost >= 0)
                {
                    if (AttackCalculation)
                    {
                        if (!UnitOnCoord(Position) || GetUnitByCoord(Position).Fraction != Unit.Fraction)
                            PossibleFields.Add(new Move(Position, RangeRemaining - Cost, null));

                        PossibleFields.AddRange(GetPossibleFieldsForUnit(Unit, new Coord(Position), RangeRemaining - Cost, AttackCalculation, ComingFrom, FirstCall: false));
                    }
                    else
                    {
                        Way.Add(Position);
                        if (!UnitOnCoord(Position)) // field is only available if there is no unit
                            PossibleFields.Add(new Move(Position, RangeRemaining - Cost, Way));
                        if (!UnitOnCoord(Position) || GetUnitByCoord(Position).Fraction == Unit.Fraction) // can move through own units
                            PossibleFields.AddRange(GetPossibleFieldsForUnit(Unit, new Coord(Position), RangeRemaining - Cost, AttackCalculation, ComingFrom, Way, FirstCall: false));
                    }
                }
            }
            return PossibleFields;
        }
Exemplo n.º 4
0
        // returns a list of attackable fields for a unit
        public List<Coord> GetPossibleFieldsToAttack(Unit Unit)
        {
            if (Unit.AttackedThisRound || (!Unit.GetMoveAndFightInOneRound() && Unit.Range < Unit.GetDefaultRange()) || Unit.Ammunition == 0)
                return new List<Coord>();

            return Move.ConvertToCoordList(GetPossibleFieldsForUnit(Unit, Unit.Position, Unit.GetFiringRange(), true));
        }
Exemplo n.º 5
0
        // returns the range a unit can move after moving to given coord
        public Move GetShortestMoveToCoord(Unit Unit, Coord Coord)
        {
            int MostRemaining = -1;
            Move ShortestMove = null;
            List<Move> PossibleFields = GetPossibleFieldsForUnit(Unit);
            foreach (Move Move in PossibleFields)
            {
                if (Move.Target.Equals(Coord))
                {
                    if (Move.RangeRemaining > MostRemaining)
                    {
                        MostRemaining = Move.RangeRemaining;
                        ShortestMove = Move;
                    }
                }
            }

            return ShortestMove;
        }
Exemplo n.º 6
0
        // fight procedure
        public void Fight(Unit Attacker, Unit Defender)
        {
            int Distance = Coord.DistanceBetweenCoord(Attacker.Position, Defender.Position);

            Attacker.AttackedThisRound = true;
            Attacker.Range = 0; // attacker can't move after attacking

            int AttackerHealthBeforeFight = Attacker.Health;
            int AttackerPower = Attacker.GetCombatSkills()[0][(int)Defender.GetClass()], DefenderPower = Defender.GetCombatSkills()[1][(int)Attacker.GetClass()];
            int AttackerBuildingBasedBonus = (Map.GetBuildingByCoord(Attacker.Position) != null) ? Map.GetBuildingByCoord(Attacker.Position).GetAttackBonus() : 0;
            int DefenderGroundBasedBonus = Map.GetSurfaceByCoord(Defender.Position).DefenseBonus;

            Attacker.DecrementAmmunition();
            Defender.DecrementAmmunition();

            if (!(Defender.GetFiringRange() < Distance))
                if (!Attacker.DecreaseHealth((int)Math.Round(2 * ((Defender.Health / (double)Defender.GetMaxHealth()) * (DefenderPower / ((AttackerPower == 0) ? 1 : AttackerPower))) + DefenderGroundBasedBonus + 0.5, 0)))
                    RemoveUnit(Attacker, true);

            if (!(Attacker.GetFiringRange() < Distance))
                if (!Defender.DecreaseHealth((int)Math.Round(2 * ((AttackerHealthBeforeFight / (double)Attacker.GetMaxHealth()) * (AttackerPower / ((DefenderPower == 0) ? 1 : DefenderPower))) + AttackerBuildingBasedBonus + 0.5, 0)))
                    RemoveUnit(Defender, true);
        }
Exemplo n.º 7
0
        public List<Move> GetPossibleFieldsForUnit(
            Unit Unit,
            Coord Position = null,
            int RangeRemaining = -1,
            bool AttackCalculation = false,
            Coord.Direction? ComingFrom = null,
            List<Coord> Way = null, 
            bool FirstCall = true)
        {
            List<Move> PossibleFields = new List<Move>();
            // first call parameter not set
            if (RangeRemaining == -1) RangeRemaining = Unit.Range;
            if (Position == null) Position = Unit.Position;
            if (Way == null)
            {
                Way = new List<Coord>();
                Way.Add(new Coord(Unit.Position));
            }
            if (FirstCall) ShortestMovesFoundYet = new List<Move>();

            Move MoveToCoord = GetMoveToCoord(Position);
            if (MoveToCoord == null || (MoveToCoord.RangeRemaining < RangeRemaining))
            {
                if (MoveToCoord != null && MoveToCoord.RangeRemaining > RangeRemaining)
                    ShortestMovesFoundYet.Remove(MoveToCoord);

                ShortestMovesFoundYet.Add(new Move(Position, RangeRemaining, Way));

                Coord Up = new Coord(Position.X, Position.Y - 1), Right = new Coord(Position.X + 1, Position.Y), Down = new Coord(Position.X, Position.Y + 1), Left = new Coord(Position.X - 1, Position.Y);
                if (ComingFrom != Coord.Direction.Down)
                    PossibleFields.AddRange(GetPossibleFieldsForUnitHelper(Unit, Up, RangeRemaining, AttackCalculation, Coord.Direction.Up, ObjectTools.DeepCopy<List<Coord>>(Way))); // upward
                if (ComingFrom != Coord.Direction.Left)
                    PossibleFields.AddRange(GetPossibleFieldsForUnitHelper(Unit, Right, RangeRemaining, AttackCalculation, Coord.Direction.Right, ObjectTools.DeepCopy<List<Coord>>(Way))); // right
                if (ComingFrom != Coord.Direction.Up)
                    PossibleFields.AddRange(GetPossibleFieldsForUnitHelper(Unit, Down, RangeRemaining, AttackCalculation, Coord.Direction.Down, ObjectTools.DeepCopy<List<Coord>>(Way))); // bottom
                if (ComingFrom != Coord.Direction.Right)
                    PossibleFields.AddRange(GetPossibleFieldsForUnitHelper(Unit, Left, RangeRemaining, AttackCalculation, Coord.Direction.Left, ObjectTools.DeepCopy<List<Coord>>(Way))); // left
            }

            if (FirstCall)
            {
                if (Unit.Food == 0)
                {
                    for (int i = 0; i < PossibleFields.Count; i++)
                    {
                        if (PossibleFields[i].Way != null && PossibleFields[i].Way.Count > 2)
                        {
                            PossibleFields.RemoveAt(i);
                            i--;
                        }
                    }
                }
            }

            return PossibleFields;
        }
Exemplo n.º 8
0
        public void ShowUnitTypeInformationPopup(Unit Unit)
        {
            Label_UnitInfoInfantryAttack.Content = Unit.GetCombatSkills()[0][0].ToString();
            Label_UnitInfoInfantryDefend.Content = Unit.GetCombatSkills()[1][0].ToString();
            Label_UnitInfoCavalryAttack.Content = Unit.GetCombatSkills()[0][1].ToString();
            Label_UnitInfoCavalryDefend.Content = Unit.GetCombatSkills()[1][1].ToString();
            Label_UnitInfoArtilleryAttack.Content = Unit.GetCombatSkills()[0][2].ToString();
            Label_UnitInfoArtilleryDefend.Content = Unit.GetCombatSkills()[1][2].ToString();
            Label_UnitInfoAirForceAttack.Content = Unit.GetCombatSkills()[0][3].ToString();
            Label_UnitInfoAirForceDefend.Content = Unit.GetCombatSkills()[1][3].ToString();
            Label_UnitInfoNavyAttack.Content = Unit.GetCombatSkills()[0][4].ToString();
            Label_UnitInfoNavyDefend.Content = Unit.GetCombatSkills()[1][4].ToString();

            Grid_UnitTypeInformationPopup.Visibility = Visibility.Visible;
        }
Exemplo n.º 9
0
 // returns whether a unit can attack a given field
 public bool FieldAttackable(Unit Unit, Coord Field)
 {
     return Field.InList(GetPossibleFieldsToAttack(Unit));
 }
Exemplo n.º 10
0
        public void GetUnitCanvasContent(Unit Unit, out Label HealthPoints, out Label RangeLeft, out Label RangeUsed, out Image UnitIcon)
        {
            HealthPoints = new Label();
            HealthPoints.Name = "Label_HealthPoints";
            HealthPoints.Content = Unit.Health.ToString();
            HealthPoints.Margin = new Thickness(FieldSize - 17, FieldSize - 17, 1, 1);
            HealthPoints.Padding = new Thickness(0);
            HealthPoints.FontSize = 12;
            HealthPoints.FontWeight = FontWeights.Bold;
            HealthPoints.Width = 16;
            HealthPoints.Height = 16;
            HealthPoints.Foreground = new SolidColorBrush(Colors.White);
            HealthPoints.Background = new SolidColorBrush(Colors.Black);
            HealthPoints.HorizontalContentAlignment = HorizontalAlignment.Center;
            HealthPoints.VerticalContentAlignment = VerticalAlignment.Center;

            // range left
            double RangeLeftPercentage = (double)Unit.Range / Unit.GetDefaultRange();
            int MaxWidth = FieldSize - 16 - 2;
            RangeLeft = new Label();
            RangeLeft.Margin = new Thickness(MaxWidth - RangeLeftPercentage * MaxWidth + 1, FieldSize - 4 - 1, 17, 1);
            RangeLeft.Height = 4;
            RangeLeft.Width = RangeLeftPercentage * MaxWidth;
            RangeLeft.Background = new SolidColorBrush((Unit.Fraction == GameControl.Game.Turn) ? Colors.DarkGreen : Colors.DarkRed);

            RangeUsed = new Label();
            RangeUsed.Margin = new Thickness(1, FieldSize - 4 - 1, MaxWidth - RangeLeftPercentage * MaxWidth + 1 + 16, 1);
            RangeUsed.Height = 4;
            RangeUsed.Width = MaxWidth - RangeLeftPercentage * MaxWidth;
            RangeUsed.Background = new SolidColorBrush(Colors.Gray);

            // image
            UnitIcon = new Image();
            UnitIcon.Name = "Image_UnitIcon";
            UnitIcon.Width = FieldSize;
            UnitIcon.Height = FieldSize;

            UnitIcon.Source = new BitmapImage(new Uri("Resources/Units58/" + ((Unit.Fraction == Fraction.Saracens) ? "S" : "C") + "_" + Unit.GetName() + ".png", UriKind.Relative));
            UnitIcon.Stretch = Stretch.Uniform;
        }
Exemplo n.º 11
0
        // hide info
        public void HideClickedFieldInfo()
        {
            this.ShownUnit = null;
            this.ShownBuilding = null;

            Label_Info_Name.Content = null;
            Label_Info_Type.Content = null;

            Label_TaxesPerRound.Visibility = Visibility.Hidden;
            Image_TaxesPerRoundMoney.Visibility = Visibility.Hidden;

            Image_Info_Unit.Source = null;
            Image_Info_Building.Source = null;
            Image_Info_BuildingBasement.Visibility = Visibility.Hidden;

            ListBox_Info_GeneralInformation_Description.Visibility = Visibility.Hidden;
            StackPanel_UnitInfoIcons.Visibility = Visibility.Hidden;
            ListBox_Info_GeneralInformation_Value.Items.Clear();
            HideUnitTypeInformationPopup();
        }
Exemplo n.º 12
0
        // display info of a unit
        public void DisplayClickedFieldInfo(Unit Unit)
        {
            HideClickedFieldInfo();

            if (Unit == null) return;
            this.ShownUnit = Unit;

            Label_Info_Name.Content = R.String(Unit.GetName());
            Label_Info_Type.Visibility = Visibility.Visible;
            Label_Info_Type.Content = Unit.UnitClassToString(Unit.GetClass());

            Image_Info_Unit.Source = new BitmapImage(new Uri("Resources/Units/" + ((Unit.Fraction == Fraction.Saracens) ? "S" : "C") + "_" + Unit.GetName() + ".png", UriKind.Relative)); ;

            ListBox_Info_GeneralInformation_Description.Visibility = Visibility.Visible;
            StackPanel_UnitInfoIcons.Visibility = Visibility.Visible;

            ListBox_Info_GeneralInformation_Value.Items.Add(Unit.Health.ToString() + " / " + Unit.GetMaxHealth().ToString());
            ListBox_Info_GeneralInformation_Value.Items.Add(Unit.Ammunition.ToString().Replace("-1", "++") + " / " + Unit.GetMaxAmmunition().ToString().Replace("-1", "++"));
            ListBox_Info_GeneralInformation_Value.Items.Add(Unit.Food.ToString().Replace("-1", "++") + " / " + Unit.GetMaxFood().ToString().Replace("-1", "++"));
            ListBox_Info_GeneralInformation_Value.Items.Add(Unit.Range.ToString() + " / " + Unit.GetDefaultRange().ToString());
            ListBox_Info_GeneralInformation_Value.Items.Add(Unit.GetInitiative().ToString());
            ListBox_Info_GeneralInformation_Value.Items.Add(Unit.GetFiringRange().ToString());
            ListBox_Info_GeneralInformation_Value.Items.Add(Unit.GetPrice().ToString());

            ShowUnitTypeInformationPopup(Unit);
        }
Exemplo n.º 13
0
        private void HandleUnitAnimation(Unit Unit)
        {
            if (Unit.AnimatedMovesRemaining.Count == 0 || Unit.ManagedByAnimationThread) // nothing to animate
            {
                return;
            }
            Unit.ManagedByAnimationThread = true;

            new Thread(() =>
            {
                Thread.CurrentThread.IsBackground = true;
                Thread.CurrentThread.Priority = ThreadPriority.Normal;

                while (Unit.AnimatedMovesRemaining.Count > 0)
                {
                    if (Unit.AnimatedMovesRemaining.Count == 0)
                    {
                        break;
                    }

                    for (int i = 1; i < Unit.AnimatedMovesRemaining[0].Way.Count; i++)
                    {
                        Coord Start = Unit.AnimatedMovesRemaining[0].Way[i - 1],
                            Destination = Unit.AnimatedMovesRemaining[0].Way[i];

                        bool AnimationVertical = (Start.X == Destination.X);

                        int AnimationDuration =
                            (AnimationVertical) ?
                                Math.Abs(GameScreen.MillisecondsPerSegment * (Start.Y - Destination.Y)) :
                                Math.Abs(GameScreen.MillisecondsPerSegment * (Start.X - Destination.X));

                        Canvas AnimationControlReference = null;

                        GameScreen.Dispatcher.BeginInvoke(
                            (Action)(() =>
                            {
                                Canvas Container = new Canvas();
                                AnimationControlReference = Container;
                                Canvas.SetLeft(Container, GameScreen.FieldSize * Start.X);
                                Canvas.SetTop(Container, GameScreen.FieldSize * Start.Y);

                                Label HealthPoints, RangeLeft, RangeUsed;
                                Image UnitIcon;

                                GameScreen.GetUnitCanvasContent(Unit, out HealthPoints, out RangeLeft, out RangeUsed, out UnitIcon);
                                Container.Children.Add(HealthPoints);
                                Container.Children.Add(RangeLeft);
                                Container.Children.Add(RangeUsed);
                                Container.Children.Add(UnitIcon);

                                GameScreen.Canvas_Inner.Children.Add(Container);

                                DoubleAnimation MoveAnimation = new DoubleAnimation();
                                MoveAnimation.From = (AnimationVertical) ?
                                    GameScreen.FieldSize * Start.Y :
                                    GameScreen.FieldSize * Start.X;
                                MoveAnimation.To = (AnimationVertical) ?
                                     GameScreen.FieldSize * Destination.Y :
                                     GameScreen.FieldSize * Destination.X;

                                MoveAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(AnimationDuration));

                                Storyboard storyboard = new Storyboard();

                                storyboard.Children.Add(MoveAnimation);
                                Storyboard.SetTarget(MoveAnimation, Container);
                                Storyboard.SetTargetProperty(
                                    MoveAnimation,
                                    new PropertyPath((AnimationVertical) ?
                                        "(Canvas.Top)" :
                                        "(Canvas.Left)")); // Attached dependency property
                                storyboard.Begin();
                            }));

                        Thread.Sleep(AnimationDuration);

                        GameScreen.Dispatcher.BeginInvoke(
                            (Action)(() =>
                            {
                                GameScreen.Canvas_Inner.Children.Remove(AnimationControlReference);
                            }));
                    }
                    Unit.AnimatedMovesRemaining.RemoveAt(0);

                    GameScreen.Dispatcher.BeginInvoke(
                        (Action)(() =>
                        {
                            GameScreen.RefreshMap(Game.Map); // refresh main window

                            if (SelectedSegment == Unit.Position) // check if the user has selected another unit or clicked into the map
                            {
                                SegmentClicked(Unit.Position); // simulate a click on the unit which has just been moved to mark the attackable fields
                            }
                            else if (SelectedSegment != null)
                            {
                                SegmentClicked(SelectedSegment);
                            }
                        }));
                }
                Unit.ManagedByAnimationThread = false; // klar ist das nötig, bin ich dumm....

            }).Start(); // start thread
        }
Exemplo n.º 14
0
        private void BackgroundWorkerDownloadLatestGameStateWork(object sender, DoWorkEventArgs e)
        {
            int? AvailableGameState = Server.GetGameState(MatchId); // get the match version

            if (AvailableGameState == null) // server response?
            {
                return;
            }

            if ((int)AvailableGameState > GameState) // newer version available
            {
                // download new game version
                if (Server.DownloadLatestGameState(MatchId, (int)AvailableGameState, GameState, ref DownloadTraffic))
                {
                    // update variable storing the local version
                    GameState = (int)AvailableGameState;

                    Control.MainWindow.Dispatcher.BeginInvoke(
                        (Action)(() =>
                        {
                            // refresh traffic label
                            GameScreen.Label_Multiplayer_TrafficDownload.Content = DownloadTraffic.ToString();

                            GameScreen.UpdateMatchState(GameState); // update label content showing the match state

                            // read downloaded file storing the new game state
                            MultiplayerGameState State = Data.GetMultiplayerGameState(MatchId + "_" + GameState);

                            if (this.Game.Turn != State.Turn && (State.Over == null || !(bool)State.Over)) // other player finished the round?
                            {
                                // TODO: add taskbar alert and sound
                                Control.ShowLoadingScreen(R.String("ItsYourTurn"));
                                this.YourTurnNotificationScreenShown = true;
                                GameScreen.Button_EndTurn.IsEnabled = true;
                            }

                            // new round began?
                            bool NewRoundBegan = (State.Rounds != null && State.Rounds > Game.Rounds);

                            // refresh local game object
                            Game.Map.MergeBuildingOwnersToBildingsList(State.BuildingOwners);
                            List<Unit> GameUnitsBeforeDownload = ObjectTools.DeepCopy<List<Unit>>(Game.Units);
                            Game.Units = State.Units ?? Game.Units;
                            Game.Turn = State.Turn ?? Game.Turn;
                            Game.Crusaders = State.Crusaders ?? Game.Crusaders;
                            Game.Saracens = State.Saracens ?? Game.Saracens;
                            Game.Over = State.Over ?? Game.Over;
                            Game.Rounds = State.Rounds ?? Game.Rounds;

                            foreach (Unit Unit in Game.Units)
                            {
                                Unit.ManagedByAnimationThread = false;
                                HandleUnitAnimation(Unit);
                            }

                            // if a new round just began refresh stats and add statistic stamp to list
                            // else refresh but don't save stamp
                            RefreshStatistic(NewRoundBegan);

                            if (Game.Over) // game over boolean set?
                            {
                                Control.ShowGameOverScreen(StatisticHistory, Game.Turn);
                            }

                            SelectedUnit = null;

                            // refresh main window
                            GameScreen.RefreshMap(Game.Map);
                            GameScreen.RefreshMoneyAndFractionOnTheMove();
                        }));
                }
            }
        }
Exemplo n.º 15
0
        // user has clicked a segment on the map
        public void SegmentClicked(Coord Coord)
        {
            SelectedSegment = Coord; // selected segment

            if (SelectedUnit != null && AllowedToOperate())
            {
                // unit has been selected before

                // move unit
                Move Move = Game.GetShortestMoveToCoord(SelectedUnit, SelectedSegment);
                if (Move != null)
                {
                    if (SelectedUnit.Range == SelectedUnit.GetDefaultRange())
                    {
                        // food can only be decremented once per round
                        SelectedUnit.DecrementFood();
                    }
                    SelectedUnit.Range = (SelectedUnit.Food == 0) ? 0 : Move.RangeRemaining; // set remaining range to 0 when the unit has no more food
                    SelectedUnit.Position = new Coord(SelectedSegment);

                    SelectedUnit.AnimatedMovesRemaining.Add(Move);

                    UploadGameState();

                    HandleUnitAnimation(SelectedUnit);
                }

                // attack other unit
                if (Game.UnitOnCoord(Coord) && Game.GetUnitByCoord(Coord).Fraction != Game.Turn && Game.FieldAttackable(SelectedUnit, Coord))
                {
                    Game.Fight(SelectedUnit, Game.GetUnitByCoord(Coord));

                    UploadGameState();

                    // check if both units still exists, if not show animation
                }

                // deselect unit
                else // deselect only if user attacked; keep unit selected if unit has been moved
                {
                    SelectedUnit = null;
                }

                GameScreen.RefreshMap(Game.Map); // refresh main window
            }

            // user clicked on an unit
            if (Game.UnitOnCoord(Coord))
            {
                GameScreen.DisplayClickedFieldInfo(Game.GetUnitByCoord(Coord)); // update info field

                // unit on clicked coord and unit of fraction being on the move
                if (!MultiplayerMatch && Game.GetUnitByCoord(Coord).Fraction == Game.Turn ||
                    MultiplayerMatch && Game.GetUnitByCoord(Coord).Fraction == MultiplayerFraction && MultiplayerFraction == Game.Turn)
                {
                    SelectedUnit = Game.GetUnitByCoord(Coord); // set selected unit

                    List<Move> Moves = Game.GetPossibleFieldsForUnit(Game.GetUnitByCoord(Coord));
                    GameScreen.MarkFieldsAsAvailable(Move.ConvertToCoordList(Moves)); // mark moveable fields
                    GameScreen.MarkFieldsAsAttackable(Game.GetPossibleFieldsToAttack(Game.GetUnitByCoord(Coord))); // mark attackable fields
                }
            }
            else // no unit on coord
            {
                // building
                Building SelectedBuilding = Game.Map.GetBuildingByCoord(Coord);
                if (SelectedBuilding != null)
                {
                    GameScreen.DisplayClickedFieldInfo(SelectedBuilding);
                    if (Game.Turn == SelectedBuilding.Fraction) // building on clicked coord? and show menu only if building belongs to fraction which is on turn
                    {
                        GameScreen.ShowMenuOf(SelectedBuilding.GetBuildingType()); // show building menu (like barracks recruitable unit selection, ...)
                    }
                }
                else
                {
                    GameScreen.HideClickedFieldInfo();
                }
            }
        }
Exemplo n.º 16
0
        // ends turn
        public void EndTurn(bool Internal = false)
        {
            if (!AllowedToOperate()) return; // multiplayer: aborts current action if the user is not allowed to move

            if (MultiplayerMatch) // disable end turn button after clicking (will be reenabled when the other player ended his round)
                GameScreen.Button_EndTurn.IsEnabled = false;

            Fraction? Won = Game.EndTurn(); // call the actual end turn method

            //Control.SetTaskBarItemInfoOverlay(Game.Turn);

            UploadGameState(ForceUpload:true);

            if (Won != null)
            {
                (new Thread(() =>
                {
                    Thread.CurrentThread.Priority = ThreadPriority.Highest;
                    Thread.CurrentThread.IsBackground = false; // dont't cancel this thread when the window is being closed

                    // update database about the winner
                    Server.SetWinningFraction(MatchId, Player.FractionToStringKey((Fraction)Won));
                })).Start();

                Control.ShowGameOverScreen(StatisticHistory, (Fraction)Won);
                return;
            }

            RefreshStatistic(true);

            SelectedUnit = null;

            // refresh main window
            GameScreen.RefreshMap(Game.Map);
            GameScreen.RefreshMoneyAndFractionOnTheMove();
        }