From 5688fa4b326ffe72a14fd41551345d2978b3edad Mon Sep 17 00:00:00 2001 From: Alicecomma Date: Thu, 20 Feb 2020 00:18:21 +0100 Subject: [PATCH 1/2] Rewrite of Command_Reload - GroupsWith & MergeWith allow combining reloading gizmos when multiple things with guns are selected. All are stored in list "others" - BuildAmmoOptions is refactored to allow taking into account multiple selected gun users: - - Switching ammo for multiple users shows "(1/2) AP", for example, indicating that 1 gun is loaded with AP rounds and that there is another gun which could be loaded with these rounds. - - Unloading multiple guns is possible - - Reloading multiple guns is possible Commit furthermore fixes #460 --- .../CombatExtended/Gizmos/Command_Reload.cs | 167 +++++++++++++----- 1 file changed, 121 insertions(+), 46 deletions(-) diff --git a/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs b/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs index ab4e0c621b..3bcbc54a81 100644 --- a/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs +++ b/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs @@ -11,8 +11,28 @@ namespace CombatExtended { public class Command_Reload : Command_Action { + List others; public CompAmmoUser compAmmo; + public override bool GroupsWith(Gizmo other) + { + var order = other as Command_Reload; + return order != null; + } + + public override void MergeWith(Gizmo other) + { + var order = other as Command_Reload; + + if (others == null) + { + others = new List(); + others.Add(this); + } + + others.Add(order); + } + public override void ProcessInput(Event ev) { if (compAmmo == null) @@ -66,66 +86,121 @@ private FloatMenu MakeAmmoMenu() private List BuildAmmoOptions() { - List ammoList = new List(); // List of all ammo types the gun can use and the pawn has in his inventory - if (compAmmo.turret != null) - { - // If we have no inventory available (e.g. manned turret), add all possible ammo types to the selection - foreach (AmmoLink link in compAmmo.Props.ammoSet.ammoTypes) - { - ammoList.Add(link.ammo); - } - } - else + //Prepare list of others in case only a single gizmo is selected + if (others == null) + others = new List(); + if (!others.Contains(this)) + others.Add(this); + + //List of actions to be taken on choosing a new ammo type, listed by ammoCategoryDef (FMJ/AP/HP) + Dictionary ammoClassActions = new Dictionary(); + + //Index 0: amount which COULD have this ammoClass; Index 1: amount which CURRENTLY has this ammoClass + Dictionary ammoClassAmounts = new Dictionary(); + + //Whether ALL in OTHERS lack reloadable weapons + var flag = false; + + foreach (var other in others) { - // Iterate through all suitable ammo types and check if they're in our inventory - foreach (AmmoLink curLink in compAmmo.Props.ammoSet.ammoTypes) + var user = other.compAmmo; + + foreach (AmmoLink link in user.Props.ammoSet.ammoTypes) { - if (compAmmo.CompInventory.ammoList.Any(x => x.def == curLink.ammo)) - ammoList.Add(curLink.ammo); + var ammoDef = link.ammo; + var ammoClass = ammoDef.ammoClass; + + // If we have no inventory available (e.g. manned turret), add all possible ammo types to the selection + // Otherwise, iterate through all suitable ammo types and check if they're in our inventory + if (user.CompInventory?.ammoList?.Any(x => x.def == ammoDef) ?? true) + { + if (!ammoClassAmounts.ContainsKey(ammoClass)) + ammoClassAmounts.Add(ammoClass, new int[2]); + + ammoClassAmounts[ammoClass][0]++; + + Action del = null; + + //Increase amount of current ammo of this type by 1 + if (user.CurrentAmmo == ammoDef) + ammoClassAmounts[ammoClass][1]++; + + if (user.SelectedAmmo == ammoDef) + { + if (Controller.settings.AutoReloadOnChangeAmmo && user.turret?.MannableComp == null && user.CurMagCount < user.Props.magazineSize) + del += other.action; + } + else + { + del += delegate { user.SelectedAmmo = ammoDef; }; + + if (Controller.settings.AutoReloadOnChangeAmmo && user.turret?.MannableComp == null) + del += other.action; + } + + //Add to delegate or create delegate at ammoClass key + if (ammoClassActions.ContainsKey(ammoClass)) + ammoClassActions[ammoClass] += del; + else + ammoClassActions.Add(ammoClass, del); + + flag = true; + } } } // Append float menu options for every available ammo type List floatOptionList = new List(); - if (ammoList.NullOrEmpty()) + + //At least one ammo type is available + if (flag) { - floatOptionList.Add(new FloatMenuOption("CE_OutOfAmmo".Translate(), null)); + foreach (var pair in ammoClassActions) + { + //Create entries of form "(a/b) c" + //a = number of guns currently using this ammo category + //b = number of guns that could use this ammo category + //c = name of category (FMJ/AP/HP/..) + floatOptionList.Add(new FloatMenuOption( + others.Except(this).Any() ? + "(" + ammoClassAmounts[pair.Key][1] + "/"+ammoClassAmounts[pair.Key][0]+") " + pair.Key.LabelCap + : pair.Key.LabelCap + , pair.Value)); + } } - else + else //Display when ALL OTHERS have no ammo + floatOptionList.Add(new FloatMenuOption("CE_OutOfAmmo".Translate(), null)); + + var unload = false; + Action unloadDel = null; + + var reload = false; + Action reloadDel = null; + + foreach (var other in others) { - // Append all available ammo types - foreach (ThingDef curDef in ammoList) + var user = other.compAmmo; + if (user.HasMagazine && user.Wielder != null || (user.turret?.MannableComp?.MannedNow ?? false)) { - AmmoDef ammoDef = (AmmoDef)curDef; - floatOptionList.Add(new FloatMenuOption(ammoDef.ammoClass.LabelCap, new Action(delegate + reload = true; + reloadDel += other.action; + + if (user.UseAmmo && user.CurMagCount > 0) { - bool shouldReload = Controller.settings.AutoReloadOnChangeAmmo && (compAmmo.SelectedAmmo != ammoDef || compAmmo.CurMagCount < compAmmo.Props.magazineSize) && compAmmo.turret?.MannableComp == null; - compAmmo.SelectedAmmo = ammoDef; - if (shouldReload) - { - if (compAmmo.turret != null) - { - compAmmo.turret.TryOrderReload(); - } - else - { - compAmmo.TryStartReload(); - } - } - }))); + unload = true; + unloadDel += delegate { user.TryUnload(true); }; + } } } - // Append unload command - var hasOperator = compAmmo.Wielder != null || (compAmmo.turret?.MannableComp?.MannedNow ?? false); - if (compAmmo.UseAmmo && hasOperator && compAmmo.HasMagazine && compAmmo.CurMagCount > 0) - { - floatOptionList.Add(new FloatMenuOption("CE_UnloadLabel".Translate(), new Action(delegate { compAmmo.TryUnload(true); }))); - } - // Append reload command - if (compAmmo.HasMagazine && hasOperator) - { - floatOptionList.Add(new FloatMenuOption("CE_ReloadLabel".Translate(), new Action(action))); - } + + // Append unload delegates + if (unload) + floatOptionList.Add(new FloatMenuOption("CE_UnloadLabel".Translate(), unloadDel)); + + // Append reload delegates + if (reload) + floatOptionList.Add(new FloatMenuOption("CE_ReloadLabel".Translate(), reloadDel)); + return floatOptionList; } From 2299b8f979820ff68f3956e0e57229f489b91a38 Mon Sep 17 00:00:00 2001 From: Alicecomma Date: Fri, 21 Feb 2020 22:27:09 +0100 Subject: [PATCH 2/2] Speed up gizmo with ammo disabled --- .../CombatExtended/Gizmos/Command_Reload.cs | 129 +++++++++--------- 1 file changed, 68 insertions(+), 61 deletions(-) diff --git a/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs b/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs index 3bcbc54a81..5af74ae8fc 100644 --- a/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs +++ b/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs @@ -92,85 +92,91 @@ private List BuildAmmoOptions() if (!others.Contains(this)) others.Add(this); - //List of actions to be taken on choosing a new ammo type, listed by ammoCategoryDef (FMJ/AP/HP) - Dictionary ammoClassActions = new Dictionary(); + // Append float menu options for every available ammo type + List floatOptionList = new List(); - //Index 0: amount which COULD have this ammoClass; Index 1: amount which CURRENTLY has this ammoClass - Dictionary ammoClassAmounts = new Dictionary(); + #region Ammo type switching + if (Controller.settings.EnableAmmoSystem) + { + //List of actions to be taken on choosing a new ammo type, listed by ammoCategoryDef (FMJ/AP/HP) + Dictionary ammoClassActions = new Dictionary(); - //Whether ALL in OTHERS lack reloadable weapons - var flag = false; + //Index 0: amount which COULD have this ammoClass; Index 1: amount which CURRENTLY has this ammoClass + Dictionary ammoClassAmounts = new Dictionary(); - foreach (var other in others) - { - var user = other.compAmmo; - - foreach (AmmoLink link in user.Props.ammoSet.ammoTypes) + //Whether ALL in OTHERS lack reloadable weapons + var flag = false; + + foreach (var other in others) { - var ammoDef = link.ammo; - var ammoClass = ammoDef.ammoClass; - - // If we have no inventory available (e.g. manned turret), add all possible ammo types to the selection - // Otherwise, iterate through all suitable ammo types and check if they're in our inventory - if (user.CompInventory?.ammoList?.Any(x => x.def == ammoDef) ?? true) + var user = other.compAmmo; + + foreach (AmmoLink link in user.Props.ammoSet.ammoTypes) { - if (!ammoClassAmounts.ContainsKey(ammoClass)) - ammoClassAmounts.Add(ammoClass, new int[2]); - - ammoClassAmounts[ammoClass][0]++; + var ammoDef = link.ammo; + var ammoClass = ammoDef.ammoClass; - Action del = null; + // If we have no inventory available (e.g. manned turret), add all possible ammo types to the selection + // Otherwise, iterate through all suitable ammo types and check if they're in our inventory + if (user.CompInventory?.ammoList?.Any(x => x.def == ammoDef) ?? true) + { + if (!ammoClassAmounts.ContainsKey(ammoClass)) + ammoClassAmounts.Add(ammoClass, new int[2]); - //Increase amount of current ammo of this type by 1 - if (user.CurrentAmmo == ammoDef) - ammoClassAmounts[ammoClass][1]++; + ammoClassAmounts[ammoClass][0]++; - if (user.SelectedAmmo == ammoDef) - { - if (Controller.settings.AutoReloadOnChangeAmmo && user.turret?.MannableComp == null && user.CurMagCount < user.Props.magazineSize) - del += other.action; - } - else - { - del += delegate { user.SelectedAmmo = ammoDef; }; + Action del = null; - if (Controller.settings.AutoReloadOnChangeAmmo && user.turret?.MannableComp == null) - del += other.action; - } + //Increase amount of current ammo of this type by 1 + if (user.CurrentAmmo == ammoDef) + ammoClassAmounts[ammoClass][1]++; - //Add to delegate or create delegate at ammoClass key - if (ammoClassActions.ContainsKey(ammoClass)) - ammoClassActions[ammoClass] += del; - else - ammoClassActions.Add(ammoClass, del); + if (user.SelectedAmmo == ammoDef) + { + if (Controller.settings.AutoReloadOnChangeAmmo && user.turret?.MannableComp == null && user.CurMagCount < user.Props.magazineSize) + del += other.action; + } + else + { + del += delegate { user.SelectedAmmo = ammoDef; }; - flag = true; - } - } - } + if (Controller.settings.AutoReloadOnChangeAmmo && user.turret?.MannableComp == null) + del += other.action; + } - // Append float menu options for every available ammo type - List floatOptionList = new List(); + //Add to delegate or create delegate at ammoClass key + if (ammoClassActions.ContainsKey(ammoClass)) + ammoClassActions[ammoClass] += del; + else + ammoClassActions.Add(ammoClass, del); - //At least one ammo type is available - if (flag) - { - foreach (var pair in ammoClassActions) + flag = true; + } + } + } + + //At least one ammo type is available + if (flag) { - //Create entries of form "(a/b) c" + foreach (var pair in ammoClassActions) + { + //Create entries of form "(a/b) c" //a = number of guns currently using this ammo category //b = number of guns that could use this ammo category //c = name of category (FMJ/AP/HP/..) - floatOptionList.Add(new FloatMenuOption( - others.Except(this).Any() ? - "(" + ammoClassAmounts[pair.Key][1] + "/"+ammoClassAmounts[pair.Key][0]+") " + pair.Key.LabelCap - : pair.Key.LabelCap - , pair.Value)); + floatOptionList.Add(new FloatMenuOption( + others.Except(this).Any() ? + "(" + ammoClassAmounts[pair.Key][1] + "/" + ammoClassAmounts[pair.Key][0] + ") " + pair.Key.LabelCap + : pair.Key.LabelCap + , pair.Value)); + } } + else //Display when ALL OTHERS have no ammo + floatOptionList.Add(new FloatMenuOption("CE_OutOfAmmo".Translate(), null)); } - else //Display when ALL OTHERS have no ammo - floatOptionList.Add(new FloatMenuOption("CE_OutOfAmmo".Translate(), null)); - + #endregion + + #region Unloading and reloading var unload = false; Action unloadDel = null; @@ -200,7 +206,8 @@ private List BuildAmmoOptions() // Append reload delegates if (reload) floatOptionList.Add(new FloatMenuOption("CE_ReloadLabel".Translate(), reloadDel)); - + #endregion + return floatOptionList; }