} //end PaintTopInGame public void AfterCollect() { if (!Hud.Game.IsInGame) { return; } var toRemove = Snapshots.Where(pair => !Hud.Game.Players.Any(p => p.HeroId == pair.Key)).Select(pair => pair.Key).ToList(); foreach (var key in toRemove) { Snapshots.Remove(key); } foreach (IPlayer player in Hud.Game.Players.Where(p => p.HasValidActor && p.SnoArea == Hud.Game.Me.SnoArea && p.CoordinateKnown)) { ProcRuleCalculator.CalculatePaintInfo(player); //check for procs if (ProcRuleCalculator.PaintInfoList.Count > 0) //proc detected { BuffPaintInfo info = ProcRuleCalculator.PaintInfoList[0]; int finishtick = Hud.Game.CurrentGameTick + (int)(info.TimeLeft * 60d); int starttick = Hud.Game.CurrentGameTick - (int)(info.Elapsed * 60d); double duration = info.TimeLeft + info.Elapsed; bool play = false; ProcInfo snapshot; if (!Snapshots.TryGetValue(player.HeroId, out snapshot)) { play = true; snapshot = new ProcInfo() { PlayerName = player.BattleTagAbovePortrait, HeroId = player.HeroId, PlayerClass = player.HeroClassDefinition.HeroClass, StartTick = starttick, FinishTick = finishtick, //Hud.Game.CurrentRealTimeMilliseconds + (long)(info.TimeLeft*1000), //long endtime Duration = duration, Texture = info.Texture, SoundPlayedTick = Hud.Game.CurrentGameTick }; Snapshots.Add(player.HeroId, snapshot); } else if (Math.Abs(finishtick - snapshot.FinishTick) > 2) //different end time //is the old record expired? //if (snapshot.FinishTick < Hud.Game.CurrentGameTick) { { if (starttick > snapshot.SoundPlayedTick) { play = true; snapshot.SoundPlayedTick = Hud.Game.CurrentGameTick; } snapshot.StartTick = starttick; snapshot.FinishTick = finishtick; snapshot.Duration = duration; snapshot.Count += 1; snapshot.Texture = info.Texture; //if (snapshot.PlayerName != player.BattleTagAbovePortrait) { //that is a desync, need to resync...would this ever happen? //} Snapshots[player.HeroId] = snapshot; } if (play && PlaySounds) { ThreadPool.QueueUserWorkItem(state => { try { if (player.IsMe) { if (SoundYou != null) { SoundYou.Play(); } else { Hud.Sound.Speak(SayYouHaveProcced); } } else { Hud.Sound.Speak(player.BattleTagAbovePortrait + SayHasProcced); } } catch (Exception) {} }); } } else { //no proc detected, but double check that the proc is not supposed to still be running (there may be an issue with proc buffs in that they momentarily register as inactive) ProcInfo snapshot; if (Snapshots.TryGetValue(player.HeroId, out snapshot)) { double timeLeft = (double)(snapshot.FinishTick - Hud.Game.CurrentGameTick) / 60d; IQuest riftQuest = Hud.Game.Quests.FirstOrDefault(q => q.SnoQuest.Sno == Hud.Sno.SnoQuests.GreaterNephalemRift_382695.Sno); if (timeLeft < 0 || //expired snapshot timeLeft > snapshot.Duration || //this happens when data lingers between games (riftQuest != null && (snapshot.FinishTick - (int)(snapshot.Duration * 60)) < riftQuest.CreatedOn) || //if the proc started before the GR was opened player.IsDeadSafeCheck) //player.HeadStone != null { Snapshots[player.HeroId].FinishTick = 0; } } } } }
public void PaintTopInGame(ClipState clipState) //public void PaintWorld(WorldLayer layer) { if (!ShowTracker) { return; } var h = Hud.Window.Size.Height * 0.001667f * BarHeight; //8 var w = Hud.Window.Size.Width * 0.00155f * BarWidth; //55 if (PositionX == -1 || PositionY == -1) { var objectivesPosition = Hud.Render.GetUiElement("Root.NormalLayer.eventtext_bkgrnd.eventtext_region.title").Rectangle; PositionX = objectivesPosition.X - ProcRuleCalculator.StandardIconSize - Gap; // Hud.Render.MinimapUiElement.Rectangle.X - Gap*2 - w - Gap - ProcRuleCalculator.StandardIconSize; //left of the minimap PositionY = objectivesPosition.Y; //Hud.Window.Size.Height * 0.015f; //0.14f; } var x = PositionX; var y = PositionY; IEnumerable <KeyValuePair <uint, ProcInfo> > ActiveSnapshots = Snapshots.Where(kvp => kvp.Value.FinishTick > Hud.Game.CurrentGameTick); //draw background int active = ActiveSnapshots.Count(); if (active > 0) { ShadowBrush.Opacity = 0.25f; ShadowBrush.DrawRectangle(x + ProcRuleCalculator.StandardIconSize, y, w + Gap * 2 + BorderBrush.StrokeWidth, active * (ProcRuleCalculator.StandardIconSize + Gap) - Gap); } //draw countdowns foreach (KeyValuePair <uint, ProcInfo> entry in ActiveSnapshots) { //render the proc snapshot if it is not expired ProcInfo snapshot = entry.Value; float timeLeft = (float)(snapshot.FinishTick - Hud.Game.CurrentGameTick) / 60f; //seconds float w2 = (float)(timeLeft * w / snapshot.Duration); float opacity = (timeLeft >= 1 || (timeLeft < 1 && (Hud.Game.CurrentRealTimeMilliseconds / 200) % 2 == 0) ? 0.9f : 0.2f); snapshot.Texture.Draw(x, y, ProcRuleCalculator.StandardIconSize, ProcRuleCalculator.StandardIconSize, opacity); //draw custom icon BorderBrush.DrawRectangle(x + 1, y + 1, ProcRuleCalculator.StandardIconSize - 2, ProcRuleCalculator.StandardIconSize - 2); //draw custom border float x2 = x + ProcRuleCalculator.StandardIconSize + Gap + BorderBrush.StrokeWidth; float y2 = y + ProcRuleCalculator.StandardIconSize * 0.5f - h * 0.5f; ShadowBrush.Opacity = 0.25f; ShadowBrush.DrawRectangle(x2 - 4, y2 - 4, w + 8, h + 8); IBrush brush; if (!ProcBrush.TryGetValue(snapshot.PlayerClass, out brush)) { brush = ProcBrushDefault; } brush.DrawRectangle(x2, y2, w2, h); BorderBrush.DrawRectangle(x2 - 2, y2 - 2, w + 4, h + 4); //draw countdown text TextLayout layout = TimeLeftFont.GetTextLayout(timeLeft.ToString(timeLeft > 1 ? "F0" : "F1")); TimeLeftFont.DrawText(layout, x2 + w * 0.5f - layout.Metrics.Width * 0.5f, y2 + h * 0.5f - layout.Metrics.Height * 0.5f); //draw player name layout = PlayerFont.GetTextLayout(snapshot.PlayerName); PlayerFont.DrawText(layout, x - layout.Metrics.Width - Gap, y + ProcRuleCalculator.StandardIconSize * 0.5f - layout.Metrics.Height * 0.5f); y += ProcRuleCalculator.StandardIconSize + Gap; } //end foreach } //end PaintTopInGame