Skip to content
This repository has been archived by the owner on Apr 14, 2020. It is now read-only.

Commit

Permalink
Merge pull request #1012 from CombatExtendedRWMod/Fix-for-#460
Browse files Browse the repository at this point in the history
Fix for #460 (multi-selection of gun users allows ammo change for all)
  • Loading branch information
zozilin authored Feb 22, 2020
2 parents d90a068 + 2299b8f commit 2ff8c43
Showing 1 changed file with 125 additions and 43 deletions.
168 changes: 125 additions & 43 deletions Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,28 @@ namespace CombatExtended
{
public class Command_Reload : Command_Action
{
List<Command_Reload> 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<Command_Reload>();
others.Add(this);
}

others.Add(order);
}

public override void ProcessInput(Event ev)
{
if (compAmmo == null)
Expand Down Expand Up @@ -66,66 +86,128 @@ private FloatMenu MakeAmmoMenu()

private List<FloatMenuOption> BuildAmmoOptions()
{
List<ThingDef> ammoList = new List<ThingDef>(); // 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
{
// Iterate through all suitable ammo types and check if they're in our inventory
foreach (AmmoLink curLink in compAmmo.Props.ammoSet.ammoTypes)
{
if (compAmmo.CompInventory.ammoList.Any(x => x.def == curLink.ammo))
ammoList.Add(curLink.ammo);
}
}
//Prepare list of others in case only a single gizmo is selected
if (others == null)
others = new List<Command_Reload>();
if (!others.Contains(this))
others.Add(this);

// Append float menu options for every available ammo type
List<FloatMenuOption> floatOptionList = new List<FloatMenuOption>();
if (ammoList.NullOrEmpty())
{
floatOptionList.Add(new FloatMenuOption("CE_OutOfAmmo".Translate(), null));
}
else

#region Ammo type switching
if (Controller.settings.EnableAmmoSystem)
{
// Append all available ammo types
foreach (ThingDef curDef in ammoList)
//List of actions to be taken on choosing a new ammo type, listed by ammoCategoryDef (FMJ/AP/HP)
Dictionary<AmmoCategoryDef, Action> ammoClassActions = new Dictionary<AmmoCategoryDef, Action>();

//Index 0: amount which COULD have this ammoClass; Index 1: amount which CURRENTLY has this ammoClass
Dictionary<AmmoCategoryDef, int[]> ammoClassAmounts = new Dictionary<AmmoCategoryDef, int[]>();

//Whether ALL in OTHERS lack reloadable weapons
var flag = false;

foreach (var other in others)
{
AmmoDef ammoDef = (AmmoDef)curDef;
floatOptionList.Add(new FloatMenuOption(ammoDef.ammoClass.LabelCap, new Action(delegate
var user = other.compAmmo;

foreach (AmmoLink link in user.Props.ammoSet.ammoTypes)
{
bool shouldReload = Controller.settings.AutoReloadOnChangeAmmo && (compAmmo.SelectedAmmo != ammoDef || compAmmo.CurMagCount < compAmmo.Props.magazineSize) && compAmmo.turret?.MannableComp == null;
compAmmo.SelectedAmmo = ammoDef;
if (shouldReload)
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 (compAmmo.turret != null)
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)
{
compAmmo.turret.TryOrderReload();
if (Controller.settings.AutoReloadOnChangeAmmo && user.turret?.MannableComp == null && user.CurMagCount < user.Props.magazineSize)
del += other.action;
}
else
{
compAmmo.TryStartReload();
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;
}
})));
}
}

//At least one ammo type is available
if (flag)
{
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 //Display when ALL OTHERS have no ammo
floatOptionList.Add(new FloatMenuOption("CE_OutOfAmmo".Translate(), null));
}
// 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)
#endregion

#region Unloading and reloading
var unload = false;
Action unloadDel = null;

var reload = false;
Action reloadDel = null;

foreach (var other in others)
{
floatOptionList.Add(new FloatMenuOption("CE_ReloadLabel".Translate(), new Action(action)));
var user = other.compAmmo;
if (user.HasMagazine && user.Wielder != null || (user.turret?.MannableComp?.MannedNow ?? false))
{
reload = true;
reloadDel += other.action;

if (user.UseAmmo && user.CurMagCount > 0)
{
unload = true;
unloadDel += delegate { user.TryUnload(true); };
}
}
}

// 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));
#endregion

return floatOptionList;
}

Expand Down

0 comments on commit 2ff8c43

Please sign in to comment.