/// <summary> /// Create a new node for a HCUnit. /// </summary> /// <param name="hcunit"></param> public OrbatNode(HCUnit hcunit) : base(hcunit.Title) { this.hcunit = hcunit; this.Update(); }
/// <summary> /// Displays a series of dummy events for alert testing. /// </summary> public void TestAlert() { this.currentEvents.Clear(); this.currentIndex = 0; DateTime time = DateTime.Now.AddMinutes(-10); Country newOwner = new Country(1, "UK", Language.Country_Name_England, Language.Country_Demonym_England, Side.Allied); Country prevOwner = new Country(4, "DE", Language.Country_Name_Germany, Language.Country_Demonym_Germany, Side.Axis); ChokePoint testCP = new ChokePoint(0, "Berlin", ChokePointType.Generic, prevOwner, new Point(), null); MilitaryFacility testFacility = new MilitaryFacility(0, "Berlin Central Armybase", testCP, FacilityType.Armybase, new Point()); Facility testFacility2 = new Facility(0, "Bilton's House", testCP, FacilityType.City, new Point()); HCUnit testHCUnit = new HCUnit(0, HCUnitLevel.Brigade, "27idkg1", "1.Kampfgruppe", "27.Infanterie 1.Kampfgruppe", null, prevOwner, Branch.Army, MoveType.Land, null, null); this.currentEvents.Add(new FacilityCapturedGameEvent(time, testFacility, newOwner, prevOwner, "xiper")); this.currentEvents.Add(new HCUnitRoutedGameEvent(time, testHCUnit, testCP)); this.currentEvents.Add(new ChokePointCapturedGameEvent(time, testCP, newOwner, prevOwner, DateTime.Now.AddMinutes(-171))); testCP.SetInitState(prevOwner, newOwner, testHCUnit); testCP.Activity = ActivityLevel.Heavy; testFacility.Owner = newOwner; if (tmrAutoNext.Enabled) { tmrAutoNext.Stop(); } if (this.Visible) { this.Visible = false; } DisplayAlerts(); }
// text colour private void tvwOrbat_DrawText(object sender, DrawEventArgs e) { e.TextBrush = new SolidBrush(Color.FromArgb(224, 224, 224)); // default forecolor HCUnit hcunit = ((OrbatNode)e.Node.Tag).hcunit; if (hcunit == null) { return; } if (hcunit.IsDeployable && !hcunit.IsDeployed) { e.TextBrush = Brushes.Gray; // is an undeployed division or brigade } else if (sender == tvwOrbatTxtChokePoint) { // color of chokepoint column depends on how recently the unit has // been moved, within the past 24 hours if (hcunit.LastMovedPlayer == null) { return; // not moved recently } e.TextBrush = new SolidBrush(Misc.GetFadedYellow(hcunit.LastMovedTime, 12 * 60, 224)); } }
// don't show right-click menu on non-brigade/divisions private void cmsOrbat_Opening(object sender, System.ComponentModel.CancelEventArgs e) { HCUnit hcunit = this.SelectedBrigade; if (hcunit == null) { e.Cancel = true; } }
/// <summary> /// Adds any child HCUnits to the given node. /// </summary> /// <param name="parentNode">The node under which to add items.</param> /// <param name="parentUnit">The HCUnit containing child units.</param> private void PopulateNode(Node parentNode, HCUnit parentUnit) { foreach (HCUnit childUnit in parentUnit.ChildUnits) { Node childNode = new OrbatNode(childUnit); parentNode.Nodes.Add(childNode); PopulateNode(childNode, childUnit); } }
private void miEquipment_Click(object sender, EventArgs e) { HCUnit hcunit = this.SelectedBrigade; if (hcunit == null) { return; } GameStatus_RevealWidget(WidgetType.Equipment, hcunit.Toe); }
/// <summary> /// A recursive method to find the tree node that is associated with the given HCUnit. /// </summary> /// <param name="root">The root node to start searching.</param> /// <param name="hcunit">The HCUnit to look for.</param> /// <returns>The node if found, otherwise null.</returns> private TreeNodeAdv FindOrbatNode(TreeNodeAdv root, HCUnit hcunit) { foreach (TreeNodeAdv node in root.Nodes) { if (((OrbatNode)node.Tag).hcunit == hcunit) { return(node); } TreeNodeAdv res = FindOrbatNode(node, hcunit); if (res != null) { return(res); } } return(null); }
/// <summary> /// Populates the tree with the given countries and hcunit hierarchy. /// </summary> /// <param name="countrys">An array of Country's.</param> /// <param name="topHCUnit">The top-level HCUnit that contains all other hcunits.</param> private void PopulateTree(IEnumerable <Country> countrys, HCUnit topHCUnit) { tvwOrbat.BeginUpdate(); ((TreeModel)tvwOrbat.Model).Nodes.Clear(); foreach (Country country in countrys) { if (!country.IsActive) { continue; } Node countryNode = new OrbatNode(country.Name); ((TreeModel)tvwOrbat.Model).Nodes.Add(countryNode); foreach (int branch in Enum.GetValues(typeof(Branch))) { if (branch == (int)Branch.None) { continue; } Node branchNode = new OrbatNode(Misc.EnumString((Branch)branch)); countryNode.Nodes.Add(branchNode); if (topHCUnit != null) { foreach (HCUnit hcunit in topHCUnit.ChildUnits) // top levels { if (hcunit.Country != country || hcunit.Branch != (Branch)branch) { continue; } Node hcunitNode = new OrbatNode(hcunit); branchNode.Nodes.Add(hcunitNode); PopulateNode(hcunitNode, hcunit); } } } } RestoreTree(); tvwOrbat.EndUpdate(); ResizeWidget(); }
/// <summary> /// Gets a tooltip for the orbat entries. /// </summary> /// <returns>The tooltip string, or null if no tooltip.</returns> public string GetToolTip(TreeNodeAdv node, NodeControl nodeControl) { HCUnit hcunit = ((OrbatNode)node.Tag).hcunit; if (hcunit == null) { return(null); } if (nodeControl.ParentColumn.Index == 2) { return(hcunit.TooltipRedeploy); } else { return(hcunit.Tooltip); } }
/// <summary> /// Recurses down the hcunit tree and generates a pair of parallel lists containing /// supply info for the currently selected vehicle. /// </summary> /// <param name="parent">The parent hcunit to process.</param> /// <param name="hcunits">A list containing the units that have the selected vehicle.</param> /// <param name="count">A list containing the number of vehicles the unit has.</param> private void GetSupply(HCUnit parent, ref List <HCUnit> hcunits, ref List <int> count) { int cycle = (int)numSupplyCycle.Value; // add unit if it's toe contains the vehicle and has supply if (parent.Toe != null && parent.Toe.Vehicles.Contains(this.selectedVehicle) && cycle < parent.Toe[this.selectedVehicle].Cycle.Length && parent.Toe[this.selectedVehicle].Cycle[cycle] > 0) { hcunits.Add(parent); count.Add(parent.Toe[this.selectedVehicle].Cycle[cycle]); } // recurse child units foreach (HCUnit child in parent.ChildUnits) { GetSupply(child, ref hcunits, ref count); } }
/// <summary> /// Makes the Order of Battle widget visible by making sure it's expanded, scrolling it into /// view, and expanding the relevant tree nodes to select the given hcunit. /// </summary> /// <seealso cref="tmrReveal_Tick"/> /// <param name="arg">The HCUnit to select.</param> public void Reveal(object arg) { HCUnit hcunit = arg as HCUnit; if (hcunit == null) { return; } if (tmrReveal.Enabled) { return; // another Reveal() in progress } TreeNodeAdv node = FindOrbatNode(tvwOrbat.Root, hcunit); if (node == null) { return; // not found; } tvwOrbat.EnsureVisible(node); node.IsExpanded = true; tvwOrbat.SelectedNode = node; Expando expOrderOfBattle = (Expando)this.Parent; if (expOrderOfBattle.Collapsed) { expOrderOfBattle.Collapsed = false; // animate tmrReveal.Start(); // scroll into view after animation } else { if (expOrderOfBattle.TaskPane != null) { expOrderOfBattle.TaskPane.ScrollControlIntoView(expOrderOfBattle); } } }
/// <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 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); }