/// <summary> /// Generates an image of all hcunits that have supply of the currently selected vehicle. /// </summary> /// <param name="hcunits">A list of hcunits.</param> /// <param name="count">A list of the hcunits' supply numbers.</param> /// <param name="imgmap">An ImageMap on which to add tooltips & clickable regions.</param> /// <returns>The supply image to display.</returns> private Image GenerateSupplyImage(IList <HCUnit> hcunits, IList <int> count, ImageMap.ImageMap imgmap) { // calculate required dimensions const int lineHeight = 14; int linesRequired = 0; HCUnit prevDivision = null; foreach (HCUnit hcunit in hcunits) { linesRequired++; HCUnit division = hcunit.Level == HCUnitLevel.Division ? hcunit : hcunit.ParentUnit; if (division != prevDivision) { linesRequired++; prevDivision = division; } } if (linesRequired == 0) { linesRequired = 4; // for "not available" message } int height = (linesRequired * lineHeight) + 2; int width = imgmap.Width; // create bitmap, graphics objects Bitmap bitmap = new Bitmap(width, height); Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; // remove previous tooltips imgmap.RemoveAll(); // create graphics resources Brush brushMain = new SolidBrush(Color.FromArgb(192, 192, 192)); Brush brushHCUnitAllied = new SolidBrush(Color.FromArgb(128, 204, 255)); // light blue Brush brushHCUnitAxis = new SolidBrush(Color.FromArgb(255, 178, 102)); // orange Font fontMain = new Font("Tahoma", 8.25F); StringFormat alignRight = new StringFormat { Alignment = StringAlignment.Far }; StringFormat alignCenter = new StringFormat { Alignment = StringAlignment.Center }; // hcunit loop int y = 0; prevDivision = null; for (int i = 0; i < hcunits.Count; i++) { HCUnit hcunit = hcunits[i]; HCUnit division = hcunit.Level == HCUnitLevel.Division ? hcunit : hcunit.ParentUnit; HCUnit brigade = hcunit.Level == HCUnitLevel.Brigade ? hcunit : hcunit.GetDummyDivHQBrigade(); // draw division heading if (division != prevDivision) { g.DrawImage(division.Country.BrigadeFlag, 0, y + 2.5F, 17.57F, 9); // 41x21 g.DrawString(division.Title, fontMain, brushMain, 17, y); y += lineHeight; prevDivision = division; } // draw unit title g.FillEllipse(hcunit.Country.Side == Side.Allied ? brushHCUnitAllied : brushHCUnitAxis, 21, y + 4, 5, 5); g.DrawString(brigade.Title, fontMain, brushMain, 29, y); int stringWidth = (int)g.MeasureString(brigade.Title, fontMain, width - 29).Width - 4; imgmap.AddRectangle(Language.Common_Tooltip_GoToBrigade, new Rectangle(30, y + 2, stringWidth, 10), true, hcunit); // draw count g.DrawString(count[i].ToString(), fontMain, brushMain, 250, y, alignRight); y += lineHeight; } // end hcunit loop // if none available, show message if (hcunits.Count == 0) { g.DrawString(String.Format(Language.Equipment_NotAvailable, numSupplyCycle.Value), fontMain, brushMain, pnlSupply.Width / 2, lineHeight * 2.5F, alignCenter); } // note: int division intentional // all done g.Dispose(); return(bitmap); }
/// <summary> /// Generate a stats image for the given Country, showing production /// output percentages and damage/output graphs. /// </summary> /// <param name="imgmap">An ImageMap on which to add tooltips.</param> /// <param name="country">The reference Country.</param> /// <returns>The image to display.</returns> private Image GenerateImage(ImageMap.ImageMap imgmap, Country country) { // get sorted list of factories to display List <Factory> countryFactorys = new List <Factory>(); foreach (Factory factory in game.Factories.Values) { if (factory.Country == country) { countryFactorys.Add(factory); } } countryFactorys.Sort(); // determine wether to show RDP info bool showRDP = true; if (country.RDPGoal <= 0) { showRDP = false; } else { foreach (Factory factory in countryFactorys) { if (factory.TotalProduced == 0 || factory.Ticks.Count == 0) { showRDP = false; } } } // create bitmap, graphics objects const int width = 334; int height = 25 * countryFactorys.Count; if (showRDP) { height += 20; } Bitmap bitmap = new Bitmap(width, height); Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; int y = -22; imgmap.RemoveAll(); // remove previous tooltips // create graphics resources Brush brushHead = new SolidBrush(Color.FromArgb(224, 224, 224)); Brush brushMain = new SolidBrush(Color.FromArgb(192, 192, 192)); Brush brushPieLight = Brushes.CornflowerBlue; Brush brushPieDark = Brushes.MediumBlue; Font fontMain = new Font("Tahoma", 8.25F); Font fontHead = new Font("Tahoma", 8.25F, FontStyle.Bold); Font fontRDP = new Font("Tahoma", 7.5F); Pen penLine = new Pen(Color.FromArgb(75, 75, 75)); StringFormat alignCenter = new StringFormat { Alignment = StringAlignment.Center }; // rdp summary if (showRDP) { y += 20; // calc percent complete int totalPointsCampaign = 0; foreach (Factory factory in countryFactorys) { totalPointsCampaign += factory.TotalProduced; } int totalPointsThisCycle = totalPointsCampaign - country.RDPPrevCyclePoints; if (totalPointsThisCycle > country.RDPGoal) { totalPointsThisCycle = country.RDPGoal; // cycle finished } float percentComplete = ((float)totalPointsThisCycle / (float)country.RDPGoal) * 100; // calc eta int totalPointsRemaining = country.RDPGoal - totalPointsThisCycle; DateTime cycleCompleted = CalcRdpEstimatedCompletion(countryFactorys, totalPointsRemaining); // draw stuff, add tooltips g.DrawLine(penLine, 0, 20, 334, 20); if (cycleCompleted == DateTime.MaxValue) // never { g.DrawString(String.Format(Language.FactoryStatus_RDPCycleNoEta, country.NextRDPCycle, percentComplete.ToString("0.00")), fontHead, brushMain, 167, 3, alignCenter); imgmap.AddRectangle(Language.FactoryStatus_Tooltip_AllFactoriesCaptured, new Rectangle(230, 5, 90, 10)); } else { g.DrawString(String.Format(Language.FactoryStatus_RDPCycle, country.NextRDPCycle, percentComplete.ToString("0.00"), Misc.MinsUntilShort(cycleCompleted)), fontHead, brushMain, 167, 3, alignCenter); imgmap.AddRectangle(String.Format(Language.FactoryStatus_Tooltip_EstimatedCompletion, cycleCompleted.ToString("ddd, d MMM, h:mm tt")), new Rectangle(230, 5, 90, 10)); } imgmap.AddRectangle(String.Format(Language.FactoryStatus_Tooltip_RdpPoints, totalPointsThisCycle, country.RDPGoal), new Rectangle(110, 5, 100, 10)); } // factory loop foreach (Factory factory in countryFactorys) { y += 25; // draw heading/parent chokepoint int x_indent = 0; if (factory.Owner.Side != country.Side) // not original side, indent and draw flag { x_indent = 15; g.DrawImage(factory.Owner.CountryFlag, 2F, y + 3.5F, 12, 7.125F); } string factoryName = Regex.Replace(factory.Name, @"^\S+\s", ""); // remove eg, "British " g.DrawString(factoryName, fontHead, brushHead, x_indent, y); g.DrawString(factory.ChokePoint.Name, fontMain, brushMain, x_indent + 10, y + 11); if (factory.Ticks.Count == 0) { continue; // skip if no data } // draw rdp output percent pie & bar graph g.FillRectangle(brushPieDark, 137, y + 1, 6, 20); float rdpBarHeight = (factory.OutputPercentPastDay * 20F) / 100F; g.FillRectangle(brushPieLight, 137, y + 1 + 20 - rdpBarHeight, 6, rdpBarHeight); imgmap.AddRectangle(String.Format(Language.FactoryStatus_Tooltip_OutputDay, factory.OutputPercentPastDay), new Rectangle(137, y + 1, 6, 20)); g.FillEllipse(brushPieDark, 147, y + 1, 20, 20); int angle = (int)((factory.OutputPercentCampaign * 360F) / 100F); g.FillPie(brushPieLight, 147, y + 1, 20, 20, -90, angle); imgmap.AddElipse(String.Format(Language.FactoryStatus_Tooltip_OutputCampaign, factory.OutputPercentCampaign), 157, y + 11, 10); // draw rdp output percentages g.DrawString(factory.OutputPercentPastDay + "%", fontMain, brushMain, 185, y, alignCenter); g.DrawString(factory.OutputPercentCampaign + "%", fontMain, brushPieLight, 185, y + 11, alignCenter); imgmap.AddRectangle(String.Format(Language.FactoryStatus_Tooltip_OutputDay, factory.OutputPercentPastDay), new Rectangle(171, y + 2, 29, 10)); imgmap.AddRectangle(String.Format(Language.FactoryStatus_Tooltip_OutputCampaign, factory.OutputPercentCampaign), new Rectangle(171, y + 13, 29, 10)); // draw damage & rdp 24-hour graph int rdpHeight = -1; // 0-5, rdp=1 => ++, rdp=0 => -- for (int i = 0; i < factory.Ticks.Count; i++) // should be <= 96 { // damage graph float damagePercent = factory.Ticks[i].Damage / 100F; float barHeight = 10F - (10F * damagePercent); Pen penDamage = new Pen(Misc.BlendColour(Color.FromArgb(0, 150, 0), Color.Red, damagePercent)); g.DrawLine(penDamage, 204 + i, y + 12, 204 + i, y + 12 - barHeight); // rdp graph if (rdpHeight == -1) // first tick { rdpHeight = factory.Ticks[i].RDP == 0 ? 0 : 5; } else if (factory.Ticks[i].RDP == 0 && rdpHeight > 0) { rdpHeight--; } else if (factory.Ticks[i].RDP == 1 && rdpHeight < 5) { rdpHeight++; } g.DrawLine(Pens.Gray, 204 + i, y + 21, 204 + i, y + 21 - rdpHeight); g.DrawLine(Pens.White, 204 + i, y + 21 - rdpHeight, 204 + i, y + 21 - rdpHeight - 1); } imgmap.AddRectangle(Language.FactoryStatus_Tooltip_GraphDamage, new Rectangle(204, y + 2, 96, 11)); imgmap.AddRectangle(Language.FactoryStatus_Tooltip_GraphOutput, new Rectangle(204, y + 15, 96, 7)); // draw damage percent, rdp flag g.DrawString(factory.CurrentHealth + "%", fontMain, brushMain, 317, y, alignCenter); imgmap.AddRectangle(String.Format(Language.FactoryStatus_Tooltip_CurrentHealth, factory.CurrentHealth), new Rectangle(303, y + 2, 29, 10)); Brush brushRDP = new SolidBrush(factory.CurrentRDP ? Color.FromArgb(0, 150, 0) : Color.Red); g.DrawString("RDP", fontRDP, brushRDP, 317, y + 12, alignCenter); imgmap.AddRectangle((factory.CurrentRDP ? Language.FactoryStatus_Tooltip_RdpOn : Language.FactoryStatus_Tooltip_RdpOff), new Rectangle(307, y + 14, 20, 10)); } // end factory loop g.Dispose(); return(bitmap); }
/// <summary> /// Generate an info image for the given ChokePoint, showing facility status, /// deployed hcunits, and linked cps. /// </summary> /// <param name="cp">The reference ChokePoint.</param> /// <param name="imgmap">An ImageMap on which to add tooltips & clickable regions.</param> /// <returns>The info image.</returns> private Image GenerateInfoImage(ChokePoint cp, ImageMap.ImageMap imgmap) { #region Init // get data ReadOnlyCollection <Bridge> nearbyBridges = cp.GetNearbyBridges(game.Bridges); SortedList <float, ChokePoint> attackFrom = cp.AttackFrom; // calculate required dimensions const int lineHeight = 14; int linesRequired = 5; if (attackFrom.Count == 1) { linesRequired += 1; } else if (attackFrom.Count > 1) { linesRequired += 1 + attackFrom.Count; } if (cp.IsContested) { linesRequired += 2; // capbar } linesRequired += 1 + cp.Facilities.Count; if (cp.LinkedChokePoints.Count > 0) { linesRequired += 1 + cp.LinkedChokePoints.Count; } if (cp.DeployedHCUnits.Count > 0) { linesRequired++; HCUnit prevDivision = null; foreach (HCUnit hcunit in cp.DeployedHCUnits) { linesRequired++; HCUnit division = hcunit.Level == HCUnitLevel.Division ? hcunit : hcunit.ParentUnit; if (division != prevDivision) { linesRequired++; prevDivision = division; } } } if (nearbyBridges.Count > 0) { linesRequired += 1 + nearbyBridges.Count; } int height = (linesRequired * lineHeight) + 2; const int width = 334; // create bitmap, graphics resources Bitmap bitmap = new Bitmap(width, height); Graphics g = Graphics.FromImage(bitmap); g.SmoothingMode = SmoothingMode.HighQuality; g.InterpolationMode = InterpolationMode.High; Brush brushMain = new SolidBrush(Color.FromArgb(192, 192, 192)); Brush brushHead = new SolidBrush(Color.FromArgb(224, 224, 224)); Brush brushHCUnitAllied = new SolidBrush(Color.FromArgb(128, 204, 255)); // light blue Brush brushHCUnitAxis = new SolidBrush(Color.FromArgb(255, 178, 102)); // orange Pen penDark = new Pen(Color.FromArgb(80, 80, 80)); Font fontMain = new Font("Tahoma", 8.25F); Font fontHead = new Font("Tahoma", 8.25F, FontStyle.Bold); StringFormat alignRight = new StringFormat { Alignment = StringAlignment.Far }; StringFormat formatNoWrap = new StringFormat { FormatFlags = StringFormatFlags.NoWrap }; // prevents odd spacing when line is clipped DateTime oneHourAgo = DateTime.Now.AddHours(-1); DateTime twelveHoursAgo = DateTime.Now.AddHours(-12); imgmap.RemoveAll(); // remove previous tooltips int y = 0; int[] xTab = new[] { 2, 15, 32, 44 }; int stringWidth; #endregion #region General info // get x position for owner/controller values float xFlagPos = 80; // min stringWidth = (int)g.MeasureString(Language.Misc_OwnedBy, fontHead).Width; if (xTab[0] + stringWidth + 2 > xFlagPos) { xFlagPos = xTab[0] + stringWidth + 2; } stringWidth = (int)g.MeasureString(Language.Misc_ControlledBy, fontHead).Width; if (xTab[0] + stringWidth + 2 > xFlagPos) { xFlagPos = xTab[0] + stringWidth + 2; } xFlagPos = (float)Math.Round(xFlagPos); // owner g.DrawString(Language.Misc_OwnedBy, fontHead, brushHead, xTab[0], y); g.DrawImage(cp.Owner.CountryFlag, xFlagPos, y + 3.5F, 12, 7.125F); string captured = null; if (cp.LastOwnerChanged > twelveHoursAgo) // within past 12 hours { captured = " (" + String.Format(Language.Time_CapturedMinsAgo, Misc.MinsAgoLong(cp.LastOwnerChanged)) + ")"; } g.DrawString(String.Format("{0}{1}", cp.Owner, captured), fontMain, brushMain, xFlagPos + 15, y); y += lineHeight; // controller g.DrawString(Language.Misc_ControlledBy, fontHead, brushHead, xTab[0], y); g.DrawImage(cp.Controller.CountryFlag, xFlagPos, y + 3.5F, 12, 7.125F); string gained = null; if (cp.LastControllerChanged > twelveHoursAgo) // within past 12 hours { gained = " (" + String.Format(cp.Controller.Side == cp.Owner.Side ? Language.Time_RegainedMinsAgo : Language.Time_GainedMinsAgo, Misc.MinsAgoLong(cp.LastControllerChanged)) + ")"; } g.DrawString(String.Format("{0}{1}", cp.Controller, gained), fontMain, brushMain, xFlagPos + 15, y); y += lineHeight; // contested if (cp.IsContested) { g.DrawImage(Resources.contested, xTab[1], y + 2, 13, 10.52F); // 21x17 string since = null; if (cp.LastContestedChanged > twelveHoursAgo) // within past 12 hours { since = " (" + String.Format(Language.Time_ForMins, Misc.MinsAgoLong(cp.LastContestedChanged)) + ")"; } g.DrawString(Language.Misc_Contested + since, fontMain, brushMain, xTab[2], y); } else { g.DrawImage(Resources.uncontested, xTab[1], y + 2, 13, 10.52F); // 21x17 string since = null; if (cp.LastContestedChanged > twelveHoursAgo) // within past 12 hours { since = " (" + String.Format(Language.Time_ForMins, Misc.MinsAgoLong(cp.LastContestedChanged)) + ")"; } g.DrawString(Language.Misc_Uncontested + since, fontMain, brushMain, xTab[2], y); } y += lineHeight; // attack objective if (cp.HasAO) { g.DrawImage(Resources.attack_objective, xTab[1], y + 2, 12, 10.29F); // 21x18 string placed = null; if (cp.LastAOChanged > twelveHoursAgo) // within past 12 hours { placed = " (" + String.Format(Language.Time_PlacedMinsAgo, Misc.MinsAgoLong(cp.LastAOChanged)) + ")"; } g.DrawString(Language.TownStatus_AttackObjective + placed, fontMain, brushMain, xTab[2], y); string attackUnit = cp.AttackingHCUnit.Title; if (cp.AttackingHCUnit.DeployedChokePoint != null) { attackUnit += " " + String.Format(Language.Misc_AtChokePoint, cp.AttackingHCUnit.DeployedChokePoint); } string aoTooltip = String.Format(Language.TownStatus_Tooltip_AOPlacedBy, attackUnit); imgmap.AddRectangle(aoTooltip, new Rectangle(xTab[1], y + 2, 100, 10)); y += lineHeight; } else { g.DrawImage(Resources.no_attack_objective, xTab[1], y + 2, 12, 10.29F); // 21x18 string removed = null; if (cp.LastAOChanged > twelveHoursAgo) // within past 12 hours { removed = " (" + String.Format(Language.Time_RemovedMinsAgo, Misc.MinsAgoLong(cp.LastAOChanged)) + ")"; } g.DrawString(Language.TownStatus_NoAttackObjective + removed, fontMain, brushMain, xTab[2], y); y += lineHeight; } // activity level g.DrawImage(cp.ActivityImage, xTab[1], y + 2, 12, 10.8F); // 20x18 g.DrawString(Language.TownStatus_Activity + " " + Misc.EnumString(cp.Activity), fontMain, brushMain, xTab[2], y); y += lineHeight; // attack from if (attackFrom.Count > 0) { if (attackFrom.Count == 1) { g.DrawString(Language.TownStatus_UnderAttackFrom + " " + attackFrom.Values[0].Name, fontMain, brushMain, xTab[2], y); y += lineHeight; } else { g.DrawString(Language.TownStatus_UnderAttackFrom, fontMain, brushMain, xTab[2], y); y += lineHeight; for (int i = attackFrom.Count - 1; i >= 0; i--) { g.DrawString(String.Format("{0} ({1:0}%)", attackFrom.Values[i], attackFrom.Keys[i]), fontMain, brushMain, xTab[3], y); y += lineHeight; } } } #endregion #region Base counts int countArmybase = 0, countAirbase = 0, countNavalbase = 0; foreach (Facility facility in cp.Facilities) { if (facility.Type == FacilityType.Armybase) { countArmybase++; } else if (facility.Type == FacilityType.Airbase) { countAirbase++; } else if (facility.Type == FacilityType.Navalbase) { countNavalbase++; } } int yOffset = 0; if (countArmybase > 0) { g.DrawImage(Resources.armybase, 300, yOffset, 18, 16); g.DrawString("x" + countArmybase, fontMain, brushMain, 334, yOffset + 1, alignRight); yOffset += 18; } if (countAirbase > 0) { g.DrawImage(Resources.airbase, 300, yOffset, 18, 16); g.DrawString("x" + countAirbase, fontMain, brushMain, 334, yOffset + 1, alignRight); yOffset += 20; } if (countNavalbase > 0) { g.DrawImage(Resources.navalbase, 300, yOffset, 18, 16); g.DrawString("x" + countNavalbase, fontMain, brushMain, 334, yOffset + 1, alignRight); } #endregion #region Capbar if (cp.IsContested) { const int left = 19; const int right = 319; int range = right - left; int mid = (int)((100 - cp.PercentOwnership) * range / 100) + left; g.DrawImage(cp.Owner.Side == Side.Allied ? Resources.capbar_red_left : Resources.capbar_blue_left, left - 4, y + 9, 4, 10); g.DrawImage(cp.Owner.Side == Side.Allied ? Resources.capbar_red : Resources.capbar_blue, new Rectangle(left, y + 9, mid - left, 10), new Rectangle(0, 0, 1, 10), GraphicsUnit.Pixel); g.DrawImage(cp.Owner.Side == Side.Allied ? Resources.capbar_blue : Resources.capbar_red, new Rectangle(mid, y + 9, right - mid, 10), new Rectangle(0, 0, 1, 10), GraphicsUnit.Pixel); g.DrawImage(cp.Owner.Side == Side.Allied ? Resources.capbar_blue_right : Resources.capbar_red_right, right, y + 9, 4, 10); g.DrawImage(Resources.capbar_pointer, mid - 13, y + 6, 27, 23); y += lineHeight + lineHeight; } #endregion #region Facility list int maxNameWidth = 255; // heading(s) g.DrawString(Language.TownStatus_Section_Facilities, fontHead, brushHead, xTab[0], y); if (cp.HasAO || cp.IsContested) { g.DrawString(Language.TownStatus_Tables, fontMain, brushHead, 252, y); maxNameWidth = 215; } if (cp.IsContested) { g.DrawString(Language.TownStatus_HeldFor, fontMain, brushHead, 250, y, alignRight); maxNameWidth = 160; } g.DrawString(Language.TownStatus_Spawn, fontMain, brushHead, 297, y); // facility loop foreach (Facility facility in cp.Facilities) { y += lineHeight; // owner flag & facility icon g.DrawImage(facility.Owner.CountryFlag, xTab[1], y + 3.5F, 12, 7.125F); g.DrawImage(facility.Icon, xTab[2], y + 2.5F, 11, 8.94F); // facility name g.DrawString(facility.Name, fontMain, brushMain, new RectangleF(xTab[3], y, maxNameWidth, lineHeight), formatNoWrap); // held for column if (cp.IsContested) { if (facility.LastOwnerChanged > twelveHoursAgo) // within past 12 hours { Brush brush; if (facility.LastOwnerChanged < oneHourAgo) { brush = new SolidBrush(Color.FromArgb(128, 128, 128)); } else { brush = new SolidBrush(Misc.GetFadedYellow(facility.LastOwnerChanged, 15, 192)); } g.DrawString(Misc.MinsAgoShort(facility.LastOwnerChanged), fontMain, brush, 250, y, alignRight); imgmap.AddRectangle(Misc.Timestamp(facility.LastOwnerChanged) + " " + String.Format(Language.TownStatus_Tooltip_CapturedBy, facility.LastCapper), new Rectangle(210, y + 2, 38, 10)); } else { g.DrawLine(penDark, 209, y + 6, 247.5F, y + 6); } } // table status column if (cp.HasAO || cp.IsContested) { if (facility.RadioTableUp) { g.DrawImage(Resources.table_up, 269, y + 2, 12, 10); } else { g.DrawImage(Resources.table_down, 269, y + 2, 12, 10); } } // spawnable column Image spawnImage; string spawnTooltip; if (!facility.SpawnableFacility) { spawnImage = Resources.spawn_nonspawnable; spawnTooltip = null; } else if (facility.Owner.Side == cp.Owner.Side) // friendly { if (facility.EnemySpawnable) { spawnImage = Resources.spawn_enemyspawnable; spawnTooltip = Language.TownStatus_Tooltip_SpawnSpawnable; } else if (facility.OwnerCanSpawn) { spawnImage = Resources.spawn_friendly; spawnTooltip = Language.TownStatus_Tooltip_SpawnFriendly; } else { spawnImage = Resources.spawn_closed; spawnTooltip = Language.TownStatus_Tooltip_SpawnClosed; } } else // enemy { if (facility.OwnerCanSpawn) { spawnImage = Resources.spawn_enemy; spawnTooltip = Language.TownStatus_Tooltip_SpawnEnemy; } else { spawnImage = Resources.spawn_closed; spawnTooltip = Language.TownStatus_Tooltip_SpawnClosed; } } g.DrawImage(spawnImage, 311, y + 2, 9, 9); if (spawnTooltip != null) { imgmap.AddRectangle(spawnTooltip, new Rectangle(311, y + 2, 9, 9)); } } // end facility loop #endregion #region Deployed hcunits if (cp.DeployedHCUnits.Count > 0) { int xTimeColumn = new BegmMisc.TextWidth(fontMain, 70, 230).MeasureAll(cp.DeployedHCUnits).MaxWidth + 100; y += lineHeight; g.DrawString(Language.TownStatus_Section_HCUnits, fontHead, brushHead, xTab[0], y); HCUnit prevDivision = null; foreach (HCUnit hcunit in cp.DeployedHCUnits) { y += lineHeight; HCUnit division = hcunit.Level == HCUnitLevel.Division ? hcunit : hcunit.ParentUnit; HCUnit brigade = hcunit.Level == HCUnitLevel.Brigade ? hcunit : hcunit.GetDummyDivHQBrigade(); if (division != prevDivision) // draw division heading w/ tooltip { prevDivision = division; g.DrawImage(division.Country.BrigadeFlag, xTab[1], y + 2.5F, 17.57F, 9); // 41x21 g.DrawString(division.Title, fontMain, brushMain, xTab[2], y); string divTooltip = null; if (division.IsDeployed) { if (division.DeployedChokePoint != cp) { divTooltip = String.Format(Language.Common_Tooltip_DivisionDeployed, division.DeployedChokePoint); } } else { divTooltip = Language.Common_Tooltip_DivisionNotDeployed; } if (divTooltip != null) { stringWidth = (int)g.MeasureString(division.Title, fontMain, width - 32).Width - 2; imgmap.AddRectangle(divTooltip, new Rectangle(xTab[2] + 1, y + 2, stringWidth, 10), true, division); } y += lineHeight; } // draw unit title, time w/ last moved tooltip g.FillEllipse(hcunit.Country.Side == Side.Allied ? brushHCUnitAllied : brushHCUnitAxis, xTab[2] + 4, y + 4, 5, 5); g.DrawString(brigade.Title, fontMain, brushMain, xTab[3], y); if (hcunit.HasLastMoved) { g.DrawString(Misc.MinsAgoShort(hcunit.LastMovedTime), fontMain, brushMain, xTimeColumn, y, alignRight); } string brigTooltip = hcunit.Tooltip; if (brigTooltip != null) { stringWidth = (int)g.MeasureString(brigade.Title, fontMain, width - xTab[3]).Width - 2; imgmap.AddRectangle(brigTooltip, new Rectangle(xTab[3] + 1, y + 2, stringWidth, 10), true, hcunit); } } } #endregion #region Linked cps/firebases if (cp.LinkedChokePoints.Count > 0) { // calc x position for kms column based on max town name length float xKmsColumn = 170; // min foreach (ChokePoint linkedChokePoint in cp.LinkedChokePoints) { stringWidth = (int)g.MeasureString(linkedChokePoint.Name, fontMain).Width; if (stringWidth + 100 > xKmsColumn) { xKmsColumn = stringWidth + 100; } } y += lineHeight; g.DrawString(Language.TownStatus_Section_LinkedTowns, fontHead, brushHead, xTab[0], y); foreach (ChokePoint linkedChokePoint in cp.LinkedChokePoints) { y += lineHeight; // owner flag g.DrawImage(linkedChokePoint.Owner.CountryFlag, xTab[1], y + 3.5F, 12, 7.125F); imgmap.AddRectangle(String.Format(Language.Common_Tooltip_GoToMap, linkedChokePoint.Name), new Rectangle(xTab[1], y + 3, 12, 8), true, linkedChokePoint.ID); // fb icon Firebase linkedFirebase = cp.GetFirebaseFrom(linkedChokePoint); string fbTooltip; if (linkedFirebase == null) { fbTooltip = String.Format(Language.TownStatus_Tooltip_FirebaseNone, cp, linkedChokePoint); } else // draw fb icon { Image fbImage; if (linkedFirebase.Link.State == FirebaseState.Inactive) { fbImage = Resources.facility_firebase; fbTooltip = String.Format(Language.TownStatus_Tooltip_FirebaseInactive, cp, linkedChokePoint); } else if (linkedFirebase.IsOpen) { fbImage = Resources.facility_firebase_open; fbTooltip = String.Format(Language.TownStatus_Tooltip_FirebaseUp, linkedChokePoint, cp, Misc.EnumString(linkedFirebase.Link.State).ToLower(), Misc.EnumString(linkedFirebase.Link.Side)); } else { fbImage = Resources.facility_firebase_closed; fbTooltip = String.Format(Language.TownStatus_Tooltip_FirebaseDown, linkedChokePoint, cp, Misc.EnumString(linkedFirebase.Link.State).ToLower(), Misc.EnumString(linkedFirebase.Link.Side)); } g.DrawImage(fbImage, xTab[2], y + 2.5F, 11, 8.94F); } imgmap.AddRectangle(fbTooltip, new Rectangle(xTab[2], y + 2, 11, 9)); // linked cp name g.DrawString(linkedChokePoint.Name, fontMain, brushMain, xTab[3], y); stringWidth = (int)g.MeasureString(linkedChokePoint.Name, fontMain, width - xTab[3]).Width - 2; imgmap.AddRectangle(String.Format(Language.Common_Tooltip_GoToStatus, linkedChokePoint.Name), new Rectangle(xTab[3] + 1, y + 2, stringWidth, 10), true, linkedChokePoint); // distance double distance = Misc.DistanceBetween(cp.LocationOctets, linkedChokePoint.LocationOctets) * 0.8; // x 800m / 1000m g.DrawString(distance.ToString("0.0 km"), fontMain, brushMain, (int)xKmsColumn, y, alignRight); } } #endregion #region Nearby bridges if (nearbyBridges.Count > 0) { y += lineHeight; g.DrawString(Language.TownStatus_Section_Bridges, fontHead, brushHead, xTab[0], y); foreach (Bridge bridge in nearbyBridges) { y += lineHeight; g.DrawImage(Resources.bridge, xTab[2], y + 3, 11, 9); g.DrawString(bridge.Name, fontMain, brushMain, xTab[3], y); } } #endregion g.Dispose(); return(bitmap); }