protected override void OnPaint(PaintEventArgs e) { if (Demos.Count < 1) { return; } g = e.Graphics; // update Zoom double width = FirstDemo.MaxX - FirstDemo.MinX + 40; double height = FirstDemo.MaxY - FirstDemo.MinY + 40; double xratio = ClientRectangle.Width / width; double yratio = ClientRectangle.Height / height; Zoom = xratio < yratio ? xratio : yratio; // draw bsp! if (Bsp != null) { foreach (var ed in Bsp.Edges) { var va = Bsp.Vertices[ed.A]; var vb = Bsp.Vertices[ed.B]; Point pa = Convert(va.X, va.Y); Point pb = Convert(vb.X, vb.Y); e.Graphics.DrawLine(Pens.Gray, pa, pb); } } int keyY = 10; foreach (ParsedDemo Demo in Demos) { // find closest state GameState state = Demo.States[0]; foreach (var pair in Demo.States) { if (pair.Key > Time) { break; } state = pair.Value; } // draw player key StatIndex hpstat = StatIndex.Player1HP; StatIndex wpstat = StatIndex.Player1Weapon; StatIndex amstat = StatIndex.Player1Ammo; int x = 10; foreach (Player pl in Demo.Players.Values) { if (pl.Netname == null) { break; } int windex = state.Stat(wpstat); string hptext = state.Stats.ContainsKey(hpstat) ? state.Stat(hpstat).ToString() : "?"; string wptext = Info.WeaponNames.ContainsKey(windex) ? Info.WeaponNames[windex] : "?"; string amtext = state.Stats.ContainsKey(amstat) ? state.Stat(amstat).ToString() : "?"; Entity ent = state.Entities[pl.Entity]; DrawPlayer(e.Graphics, ent, pl, new Rectangle(x, keyY, 10, 10)); e.Graphics.DrawString(pl.Netname, Font, Brushes.White, x + 12, keyY); e.Graphics.DrawString(hptext, Font, Brushes.White, x + 82, keyY); e.Graphics.DrawString(wptext, Font, Brushes.White, x + 102, keyY); e.Graphics.DrawString(amtext, Font, Brushes.White, x + 122, keyY); hpstat++; wpstat++; amstat++; keyY += 14; } // draw messages int y = ClientRectangle.Height - 10; y -= state.Messages.Count * 14; foreach (string msg in state.Messages) { e.Graphics.DrawString(msg, Font, Brushes.White, x, y); y += 14; } // draw counts x = ClientRectangle.Width - 100; y = ClientRectangle.Height - 24; e.Graphics.DrawString($"Kills: {state.Stat(StatIndex.KilledMonsters)} / {state.Stat(StatIndex.NumMonsters)}", Font, Brushes.White, x, y - 14); e.Graphics.DrawString($"Secrets: {state.Stat(StatIndex.FoundSecrets)} / {state.Stat(StatIndex.NumSecrets)}", Font, Brushes.White, x, y); // draw temps foreach (Temp t in state.Temps) { t.Draw(this); } // draw entities foreach (Entity ent in state.Entities.Values.Reverse()) { if (ent.Number == 0) { continue; } if (ent.Model[0] == '*') { continue; } if (ent.Model == "?") { continue; } ModelInfo minf = Info.GetModelInfo(ent.Model, ent.Skin); if (minf.Type == ModelType.Player) { Player pl = Demo.GetPlayer((byte)(ent.Number - 1)); DrawPlayer(e.Graphics, ent, pl); DrawAngle(e.Graphics, ent); continue; } if (minf.DeadFrames.Contains(ent.Frame)) { Cross(ent.Origin, Color.DarkRed, minf.Size / 2); continue; } Rectangle rect = GetDrawRect(ent, minf.Size); e.Graphics.FillRectangle(minf.Background, rect); if (minf.Type == ModelType.Enemy) { DrawAngle(e.Graphics, ent); } if (minf.Label != null) { SizeF size = e.Graphics.MeasureString(minf.Label, Font); float lx = rect.Left + rect.Width / 2 - size.Width / 2; float ly = rect.Top + rect.Height / 2 - size.Height / 2; e.Graphics.DrawString(minf.Label, Font, minf.Foreground, lx, ly); } } } }
private static void LoadModelInfo(string fileName) { using (StreamReader reader = File.OpenText(fileName)) { ModelInfo inf = null; while (!reader.EndOfStream) { string line = reader.ReadLine().Trim(); if (line.Length == 0) { continue; } if (line[0] == '*') { if (inf != null) { ModelInfos[inf.Model] = inf; } inf = new ModelInfo(line.Substring(1)); } else if (line.StartsWith("Name: ")) { inf.Name = line.Substring(6); } else if (line.StartsWith("Label: ")) { inf.Label = line.Substring(7); } else if (line.StartsWith("Type: ")) { string typeName = line.Substring(6); ModelType type = (ModelType)Enum.Parse(typeof(ModelType), typeName, true); inf.Type = type; if (ModelInfo.DefaultBackground.ContainsKey(type)) { inf.Background = ModelInfo.DefaultBackground[type]; } if (ModelInfo.DefaultSize.ContainsKey(type)) { inf.Size = ModelInfo.DefaultSize[type]; } } else if (line.StartsWith("Source: ")) { string sourceName = line.Substring(8); inf.Source = (GameSource)Enum.Parse(typeof(GameSource), sourceName, true); } else if (line.StartsWith("Background: ")) { string bgName = line.Substring(12); inf.Background = new SolidBrush(Color.FromName(bgName)); } else if (line.StartsWith("Foreground: ")) { string fgName = line.Substring(12); inf.Foreground = new SolidBrush(Color.FromName(fgName)); } else if (line.StartsWith("Size: ")) { inf.Size = int.Parse(line.Substring(6)); } else if (line.StartsWith("Dead: ")) { string[] frames = line.Substring(6).Replace(" ", "").Split(','); foreach (string frame in frames) { int fval = int.Parse(frame); inf.DeadFrames.Add(fval); } } else { Console.WriteLine($"Unknown instruction in models.txt: {line}"); } } if (inf != null) { ModelInfos[inf.Model] = inf; } } }