private void ParseSpecialKeys(OverwatchDataModel gameDataModel, CharacterColor? characterMatch, Color[,] colors) { if ((characterMatch == null) || (characterMatch.Value.Character == OverwatchCharacter.None)) return; // Ultimate is ready when Q is blinking var charCol = characterMatch.Value.Color; var backlidColor = Color.FromRgb((byte) (charCol.R*0.25), (byte) (charCol.G*0.25), (byte) (charCol.B*0.25)); var ultReady = !backlidColor.Equals(colors[2, 2]); if (_ultimateUsed.AddSeconds(15) <= DateTime.Now) { // Player can change hero if H is blinking gameDataModel.CanChangeHero = !colors[3, 7].Equals(backlidColor); if (!_stickyUltimateReady.Value && ultReady && ControlsShown(colors)) { _ultimateReady = DateTime.Now; _stickyUltimateReady.Value = true; } } // If ult no longer ready but it was ready before, it was used. if (_stickyUltimateReady.Value && !ultReady) { _stickyUltimateReady.Value = false; if (_ultimateUsed.AddSeconds(15) <= DateTime.Now) _ultimateUsed = DateTime.Now; } // UltimateUsed is true for 10 seconds after ultimate went on cooldown if (_ultimateUsed != DateTime.MinValue) _stickyUltimateUsed.Value = _ultimateUsed.AddSeconds(10) >= DateTime.Now; }