예제 #1
0
 private void ResetRound()
 {
     _voteOptions.Clear();
     _lastRoundSeed       = _roundSeed;
     _roundSeed           = 0;
     _roundPriority       = 0;
     _roundStartTimestamp = 0;
     _localPlayerIndex    = -1;
     _matchBuffer         = null;
 }
예제 #2
0
        private void UpdateRound(Terminal terminal)
        {
            var roundDuration = Stopwatch.GetTimestamp() - _roundStartTimestamp;

            if (roundDuration < Timestamps.VoteStart)
            {
                TournamentPhase        = TournamentPhase.VoteCountdown;
                NextPhaseTimestamp     = _roundStartTimestamp + Timestamps.VoteStart;
                LocalPlayer.VoteOption = 0;
            }
            else
            {
                if (roundDuration < Timestamps.MatchTransitionStart)
                {
                    LocalPlayer.IsReady = false;

                    if (_voteOptions.Count == 0)
                    {
                        LocalPlayer.TournamentScore = (int)(LocalPlayer.TournamentScore * _scoreDecay);

                        _roundRandom = new Random(_roundSeed);
                        _voteOptions = _roundRandom.Shuffle(DisciplineDirectory.Disciplines).Take(3).ToList();
                        _voteOptions.Insert(0, null);
                    }

                    TournamentPhase    = TournamentPhase.Vote;
                    NextPhaseTimestamp = _roundStartTimestamp + Timestamps.MatchTransitionStart;
                }
                else
                {
                    if (LocalPlayer.VoteOption == 0)
                    {
                        /* Local player opted out of the match. */
                        ResetRound();
                        return;
                    }

                    if (roundDuration < Timestamps.MatchCountdownStart)
                    {
                        TournamentPhase    = TournamentPhase.MatchTransition;
                        NextPhaseTimestamp = _roundStartTimestamp + Timestamps.MatchCountdownStart;
                    }
                    else
                    {
                        if (_matchBuffer == null)
                        {
                            var activePlayers = _roundRandom.Shuffle(_players.Values.Where(p => p.VoteOption != 0).OrderBy(p => p.Id));
                            if (activePlayers.Count < 2)
                            {
                                ResetRound();
                                return;
                            }

                            _localPlayerIndex = activePlayers.IndexOf(LocalPlayer);

                            var winningDiscipline = _voteOptions[activePlayers[_roundRandom.Next(activePlayers.Count)].VoteOption];
                            _voteOptions.Clear();

                            DiscipleName = winningDiscipline.Name;

                            var newOutput = new Output();

                            var playerDescriptions = activePlayers.Select(
                                p => new PlayerDescription
                            {
                                Color  = p.PlayerColor,
                                Name   = p.Name,
                                Output = p == LocalPlayer ? newOutput : NullOutput.Instance,
                            }).ToList();

                            var matchDescription = new MatchDescription
                            {
                                Players          = playerDescriptions,
                                Random           = _roundRandom,
                                Output           = newOutput,
                                LocalPlayerIndex = _localPlayerIndex,
                            };

                            var match = winningDiscipline.CreateMatch(matchDescription);
                            _matchBuffer      = new MatchBuffer(match);
                            _lastUpdatedFrame = 0;
                        }

                        int currentFrame;
                        if (roundDuration < Timestamps.MatchStart)
                        {
                            TournamentPhase    = TournamentPhase.MatchCountdown;
                            NextPhaseTimestamp = _roundStartTimestamp + Timestamps.MatchStart;
                            currentFrame       = 0;
                        }
                        else
                        {
                            TournamentPhase    = TournamentPhase.Match;
                            NextPhaseTimestamp = 0;
                            currentFrame       = (int)((roundDuration - Timestamps.MatchStart) / GameSpeed.FrameDuration);

                            var input = terminal.Input;
                            while (currentFrame > _lastUpdatedFrame)
                            {
                                ++_lastUpdatedFrame;
                                _matchBuffer.SetInput(_lastUpdatedFrame, _localPlayerIndex, input);
                                _inputEntries.Add(new InputEntry(_lastUpdatedFrame, input));
                            }
                        }

                        /* Render a 50ms old frame to hide a certain amount of lag. */
                        _matchBuffer.UpdateToFrame(currentFrame - _latencyFrames);

                        var output = _matchBuffer.PredictedMatch.Output as Output;
                        if (output != null)
                        {
                            double frame = (roundDuration - Timestamps.MatchStart) / (double)GameSpeed.FrameDuration - _latencyFrames;
                            output.Render(frame, terminal);
                        }

                        if (_matchBuffer.IsCompleted)
                        {
                            var scores           = _matchBuffer.KnownMatch.Players.Select(p => p.Score).ToList();
                            var localPlayerScore = scores[_localPlayerIndex];
                            int roundScore       = scores.Sum(s => s < localPlayerScore ? _winScore : (s == localPlayerScore ? _tieScore : 0));
                            LocalPlayer.TournamentScore += roundScore;
                            ResetRound();
                        }
                    }
                }
            }
        }