diff --git a/Defs/TempTestDef.xml b/Defs/TempTestDef.xml new file mode 100644 index 0000000000..9e7ac47f58 --- /dev/null +++ b/Defs/TempTestDef.xml @@ -0,0 +1,177 @@ + + + + Turret_GenericAmmoUserTest + + 6 + + Things/Building/Turrets/MachineGunBase + + (0.27,0.25,0.27) + (0,0,0) + + + UI/Icons/Turrets/MediumAutoTurret_uiIcon + + 20000 + 200 + 0.6 + 30 + 40 + 0.5 + 0.75 + + Automatic turret equiped with a full powered cartridge machine gun. Fairly resistant to damage. + + 150 + 8 + + + true + Gun_GenericAmmoUserTest + + +
  • PlaceWorker_TurretTop
  • +
  • PlaceWorker_ShowTurretRadius
  • +
    + +
  • + CompPowerTrader + 150 +
  • +
    + MinifiedThing + +
  • GunTurrets
  • +
  • PrecisionRifling
  • +
    +
    + + + Gun_GenericAmmoUserTest + + + Things/Building/Turrets/MediumTurret_Top + Graphic_Single + + Full powered cartridge gun on a turret mount. + + 1 + 0.05 + 0.84 + 0.36 + 10 + + +
  • + 0.95 + CombatExtended.Verb_ShootCE + true + Bullet_762x51mmNATO_FMJ + 1.3 + 55 + 6 + 10 + MediumMG + GunTail_Medium + 11 + Mounted +
  • +
    + +
  • + CombatExtended.CompAmmoUserGeneric + 80 + 7.8 + AmmoSet_762x51mmNATO +
  • +
    +
    + + + Turret_GenericAmmoUserTestII + + 6 + + Things/Building/Turrets/MachineGunBase + + (0.27,0.25,0.27) + (0,0,0) + + + UI/Icons/Turrets/MediumAutoTurret_uiIcon + + 20000 + 200 + 0.6 + 30 + 40 + 0.5 + 0.75 + + Automatic turret equiped with a full powered cartridge machine gun. Fairly resistant to damage. + + 150 + 8 + + + true + Gun_GenericAmmoUserTestII + + +
  • PlaceWorker_TurretTop
  • +
  • PlaceWorker_ShowTurretRadius
  • +
    + +
  • + CompPowerTrader + 150 +
  • +
    + MinifiedThing + +
  • GunTurrets
  • +
  • PrecisionRifling
  • +
    +
    + + + Gun_GenericAmmoUserTestII + + + Things/Building/Turrets/MediumTurret_Top + Graphic_Single + + Full powered cartridge gun on a turret mount. + + 1 + 0.05 + 0.84 + 0.36 + 10 + + +
  • + 0.95 + CombatExtended.Verb_ShootCE + true + Bullet_762x51mmNATO_FMJ + 1.3 + 55 + 6 + 10 + MediumMG + GunTail_Medium + 11 + Mounted +
  • +
    + +
  • + 80 + 7.8 + AmmoSet_303British +
  • +
    +
    +
    \ No newline at end of file diff --git a/Defs/ThingDefs_Buildings/AutoLoaderExample.xml b/Defs/ThingDefs_Buildings/AutoLoaderExample.xml index a8bcec7417..3484c6b900 100644 --- a/Defs/ThingDefs_Buildings/AutoLoaderExample.xml +++ b/Defs/ThingDefs_Buildings/AutoLoaderExample.xml @@ -1,144 +1,119 @@ - + 0.5 + false + 42 + (2,1) + + 200 + + + BuildingDestroyed_Metal_Small + + + 100 + 1800 + 20 + 0.5 + + 0.5 + + Misc + MinifiedThing + +
  • BuildingsMisc
  • +
    +
    \ No newline at end of file diff --git a/Source/CombatExtended/CombatExtended/Building_AmmoContainerCE/Building_AutoloaderCE.cs b/Source/CombatExtended/CombatExtended/Building_AmmoContainerCE/Building_AutoloaderCE.cs index d4c594649d..da4468f889 100644 --- a/Source/CombatExtended/CombatExtended/Building_AmmoContainerCE/Building_AutoloaderCE.cs +++ b/Source/CombatExtended/CombatExtended/Building_AmmoContainerCE/Building_AutoloaderCE.cs @@ -88,14 +88,14 @@ public override Graphic Graphic public bool CanReplaceAmmo(CompAmmoUser ammoUser) { - return shouldReplaceAmmo && ammoUser.Props.ammoSet == CompAmmoUser.Props.ammoSet && ammoUser.CurrentAmmo != CompAmmoUser.CurrentAmmo; + return shouldReplaceAmmo && ammoUser.CurAmmoSet == CompAmmoUser.CurAmmoSet && ammoUser.CurrentAmmo != CompAmmoUser.CurrentAmmo; } public override void SpawnSetup(Map map, bool respawningAfterLoad) { base.SpawnSetup(map, respawningAfterLoad); Map.GetComponent().Register(this); - CompAmmoUser = GetComp(); + CompAmmoUser = this.TryGetComp(); dormantComp = GetComp(); initiatableComp = GetComp(); @@ -228,7 +228,7 @@ public override IEnumerable GetGizmos() } if (!success) { - Messages.Message(string.Format("CE_AutoLoader_NoTurretToReload".Translate(), Label, CompAmmoUser.Props.ammoSet.label), this, MessageTypeDefOf.RejectInput, historical: false); + Messages.Message(string.Format("CE_AutoLoader_NoTurretToReload".Translate(), Label, CompAmmoUser.CurAmmoSet.label), this, MessageTypeDefOf.RejectInput, historical: false); } }; yield return reload; @@ -349,18 +349,24 @@ public bool StartReload(CompAmmoUser TurretMagazine, bool continued = false) //if this is the right turret to reload if (graphicsExt != null) { - //if def exists and match - bool tagMatch = graphicsExt.allowedTurrets.Any() && graphicsExt.allowedTurrets.Contains(turret.def.defName); + //if turret type restriction is in place, if both are null, tag chech automatically pass + bool tagMatch = graphicsExt.allowedTurrets.NullOrEmpty() && graphicsExt.allowedTurretTags.NullOrEmpty(); - //if tag exists and match - if (!tagMatch && graphicsExt.allowedTurretTags.Any()) + if (!tagMatch) { - foreach (string loadertag in graphicsExt.allowedTurretTags) + //if def dont exist or match + tagMatch = graphicsExt.allowedTurrets.NullOrEmpty() || graphicsExt.allowedTurrets.Contains(turret.def.defName); + + //if tag exists and match + if (!tagMatch && graphicsExt.allowedTurretTags.Any()) { - if (turret.def.building.buildingTags.NotNullAndContains(loadertag)) + foreach (string loadertag in graphicsExt.allowedTurretTags) { - tagMatch = true; - break; + if (turret.def.building.buildingTags.NotNullAndContains(loadertag)) + { + tagMatch = true; + break; + } } } } diff --git a/Source/CombatExtended/CombatExtended/Comps/CompAmmoUser.cs b/Source/CombatExtended/CombatExtended/Comps/CompAmmoUser.cs index e1aa4617b6..91c3ae0e4f 100644 --- a/Source/CombatExtended/CombatExtended/Comps/CompAmmoUser.cs +++ b/Source/CombatExtended/CombatExtended/Comps/CompAmmoUser.cs @@ -17,9 +17,9 @@ public class CompAmmoUser : CompRangedGizmoGiver { #region Fields - private int curMagCountInt = 0; - private AmmoDef currentAmmoInt = null; - private AmmoDef selectedAmmo; + protected int curMagCountInt = 0; + protected AmmoDef currentAmmoInt = null; + protected AmmoDef selectedAmmo; private Thing ammoToBeDeleted; @@ -46,7 +46,7 @@ public int MagsLeft { CompInventory.UpdateInventory(); int count = 0; - foreach (AmmoLink link in Props.ammoSet.ammoTypes) + foreach (AmmoLink link in CurAmmoSet.ammoTypes) { count += CompInventory.AmmoCountOfDef(link.ammo); } @@ -137,7 +137,7 @@ public bool UseAmmo { get { - return Props.ammoSet != null && AmmoUtility.IsAmmoSystemActive(Props.ammoSet); + return CurAmmoSet != null && AmmoUtility.IsAmmoSystemActive(CurAmmoSet); } } public bool IsAOEWeapon @@ -172,7 +172,7 @@ public bool HasAmmo { get { - return CompInventory != null && CompInventory.ammoList.Any(x => Props.ammoSet.ammoTypes.Any(a => a.ammo == x.def)); + return CompInventory != null && CompInventory.ammoList.Any(x => CurAmmoSet.ammoTypes.Any(a => a.ammo == x.def)); } } public bool HasMagazine => MagSize > 0; @@ -217,7 +217,9 @@ public bool FullMagazine } } - public ThingDef CurAmmoProjectile => Props.ammoSet?.ammoTypes?.FirstOrDefault(x => x.ammo == CurrentAmmo)?.projectile ?? parent.def.Verbs.FirstOrDefault().defaultProjectile; + public virtual AmmoSetDef CurAmmoSet => Props.ammoSet; + + public virtual ThingDef CurAmmoProjectile => CurAmmoSet?.ammoTypes?.FirstOrDefault(x => x.ammo == CurrentAmmo)?.projectile ?? parent.def.Verbs.FirstOrDefault().defaultProjectile; public CompInventory CompInventory { get @@ -267,7 +269,7 @@ private Map Map } public bool ShouldThrowMote => Props.throwMote && MagSize > 1; - public AmmoDef SelectedAmmo + public virtual AmmoDef SelectedAmmo { get { @@ -297,7 +299,7 @@ public override void Initialize(CompProperties vprops) // Initialize ammo with default if none is set if (UseAmmo) { - if (Props.ammoSet.ammoTypes.NullOrEmpty()) + if (CurAmmoSet.ammoTypes.NullOrEmpty()) { Log.Error(parent.Label + " has no available ammo types"); } @@ -305,7 +307,7 @@ public override void Initialize(CompProperties vprops) { if (currentAmmoInt == null) { - currentAmmoInt = (AmmoDef)Props.ammoSet.ammoTypes[0].ammo; + currentAmmoInt = (AmmoDef)CurAmmoSet.ammoTypes[0].ammo; } if (selectedAmmo == null) { @@ -671,7 +673,7 @@ public bool TryPickupAmmo() { return false; } - IEnumerable supportedAmmo = Props.ammoSet.ammoTypes.Select(a => a.ammo); + IEnumerable supportedAmmo = CurAmmoSet.ammoTypes.Select(a => a.ammo); foreach (Thing thing in Holder.Position.AmmoInRange(Holder.Map, 6).Where(t => t is AmmoThing ammo && supportedAmmo.Contains(ammo.AmmoDef) && (!Holder.IsColonist || (!ammo.IsForbidden(Holder) && ammo.Position.AdjacentTo8WayOrInside(Holder))))) @@ -831,7 +833,7 @@ public bool TryFindAmmoInInventory(out Thing ammoThing) } // Try finding ammo from different type - foreach (AmmoLink link in Props.ammoSet.ammoTypes) + foreach (AmmoLink link in CurAmmoSet.ammoTypes) { ammoThing = CompInventory.ammoList.Find(thing => thing.def == link.ammo); if (ammoThing != null) @@ -927,7 +929,7 @@ public override IEnumerable CompGetGizmosExtra() public override string TransformLabel(string label) { - string ammoSet = UseAmmo && Controller.settings.ShowCaliberOnGuns ? " (" + (string)Props.ammoSet.LabelCap + ") " : ""; + string ammoSet = UseAmmo && Controller.settings.ShowCaliberOnGuns ? " (" + (string)CurAmmoSet.LabelCap + ") " : ""; return label + ammoSet; } diff --git a/Source/CombatExtended/CombatExtended/Comps/CompAmmoUserGeneric.cs b/Source/CombatExtended/CombatExtended/Comps/CompAmmoUserGeneric.cs new file mode 100644 index 0000000000..e792a46783 --- /dev/null +++ b/Source/CombatExtended/CombatExtended/Comps/CompAmmoUserGeneric.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using Verse; + +namespace CombatExtended +{ + public class CompAmmoUserGeneric : CompAmmoUser + { + protected List usableAmmoSets = new List(); + + public AmmoSetDef SelectedAmmoSet; + + public AmmoSetDef UsedGenericAmmoSet => Props.ammoSet.similarTo ?? Props.ammoSet; + + const float margin = 4f; + + public virtual List UsableAmmoSets + { + get + { + if (usableAmmoSets.NullOrEmpty()) + { + foreach (var def in DefDatabase.AllDefs) + { + if (def.similarTo == null) + { + continue; + } + if (def.similarTo == UsedGenericAmmoSet && !def.ammoTypes.First().ammo.menuHidden && !IsIdenticalToAny(def)) + { + usableAmmoSets.Add(def); + } + } + } + return usableAmmoSets; + } + } + + //Merge ammosets with identical ammo usage. I'm worried about its performance and I might want to caculate this during game start up. + protected bool IsIdenticalToAny(AmmoSetDef def) + { + if (usableAmmoSets.NullOrEmpty()) + { + return false; + } + foreach (var v in usableAmmoSets) + { + if (IsIdenticalTo(v, def)) + { + return true; + } + } + return false; + } + + protected bool IsIdenticalTo(AmmoSetDef a, AmmoSetDef b) + { + if (a.ammoTypes.Count != b.ammoTypes.Count) + { + return false; + } + HashSet list = new HashSet(); + foreach (var v in a.ammoTypes) + { + list.Add(v.ammo); + } + foreach (var n in b.ammoTypes) + { + if (!list.Contains(n.ammo)) + { + return false; + } + } + return true; + } + + + public override AmmoSetDef CurAmmoSet => SelectedAmmoSet; + + public override void PostExposeData() + { + base.PostExposeData(); + Scribe_Defs.Look(ref SelectedAmmoSet, "SelectedAmmoSet"); + } + + public override void Initialize(CompProperties vprops) + { + base.Initialize(vprops); + SelectedAmmoSet = Props.ammoSet; + RegenSelectedAmmo(); + } + public void RegenSelectedAmmo() + { + if (currentAmmoInt == null) + { + currentAmmoInt = (AmmoDef)CurAmmoSet.ammoTypes[0].ammo; + } + if (selectedAmmo == null) + { + selectedAmmo = currentAmmoInt; + } + else + { + //turned out it was bold to assume similar ammosets always have same ammo types + var tempAmmoLink = CurAmmoSet.ammoTypes.Where(l => l.ammo.ammoClass == currentAmmoInt.ammoClass); + if (tempAmmoLink.Any()) + { + selectedAmmo = tempAmmoLink.First().ammo; + } + else + { + selectedAmmo = CurAmmoSet.ammoTypes.First().ammo; + } + } + } + + [Compatibility.Multiplayer.SyncMethod] + private void SyncedSelectAmmoSet(AmmoSetDef caliber) + { + SelectedAmmoSet = caliber; + RegenSelectedAmmo(); + } + + public override IEnumerable CompGetGizmosExtra() + { + foreach (var gizmo in base.CompGetGizmosExtra()) + { + yield return gizmo; + } + if (!Controller.settings.GenericAmmo) + { + Command_Action command_Action = new Command_Action(); + command_Action.defaultLabel = "CE_SelectAmmoSet".Translate(); + command_Action.defaultDesc = "CommandSelectMineralToScanForDesc".Translate(); + command_Action.icon = ContentFinder.Get("UI/Buttons/Reload", reportFailure: false); + command_Action.action = delegate + { + List list = new List(); + foreach (AmmoSetDef caliber in UsableAmmoSets) + { + FloatMenuOption item = new FloatMenuOption(caliber.LabelCap, delegate + { + SyncedSelectAmmoSet(caliber); + }, MenuOptionPriority.Default, + delegate (Rect rect) + { + ContainedAmmoPopOut(rect, caliber); + } + , null); + list.Add(item); + } + Find.WindowStack.Add(new FloatMenu(list)); + }; + yield return command_Action; + } + } + + AmmoSetDef currentlyHoveredOverAmmoSet = null; + + string ammoSetContentDescCache; + + public void ContainedAmmoPopOut(Rect rect, AmmoSetDef ammoSet) + { + if (ammoSet != currentlyHoveredOverAmmoSet) + { + BuildAmmosetString(ammoSet); + } + TooltipHandler.TipRegion(rect, ammoSetContentDescCache); + + } + + public void BuildAmmosetString(AmmoSetDef ammoSetDef) + { + StringBuilder stringBuilder = new StringBuilder(); + foreach (var v in ammoSetDef.ammoTypes) + { + stringBuilder.AppendLine(v.ammo.label); + } + ammoSetContentDescCache = stringBuilder.ToString(); + } + } +} diff --git a/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs b/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs index d8a83d5f0f..d93368b433 100644 --- a/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs +++ b/Source/CombatExtended/CombatExtended/Gizmos/Command_Reload.cs @@ -119,7 +119,7 @@ private List BuildAmmoOptions() { var user = other.compAmmo; - foreach (AmmoLink link in user.Props.ammoSet.ammoTypes) + foreach (AmmoLink link in user.CurAmmoSet.ammoTypes) { var ammoDef = link.ammo; var ammoClass = ammoDef.ammoClass; diff --git a/Source/CombatExtended/CombatExtended/Jobs/JobGiver_CheckReload.cs b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_CheckReload.cs index 57c4446115..0a5af7ae86 100644 --- a/Source/CombatExtended/CombatExtended/Jobs/JobGiver_CheckReload.cs +++ b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_CheckReload.cs @@ -132,7 +132,7 @@ private bool DoReloadCheck(Pawn pawn, out ThingWithComps reloadWeapon, out AmmoD { // Get key stats of the weapon. tmpComp = gun.TryGetComp(); - AmmoDef ammoType = tmpComp.CurrentAmmo; + AmmoDef ammoType = tmpComp.SelectedAmmo; int ammoAmount = tmpComp.CurMagCount; int magazineSize = tmpComp.MagSize; @@ -140,7 +140,7 @@ private bool DoReloadCheck(Pawn pawn, out ThingWithComps reloadWeapon, out AmmoD if (tmpComp.UseAmmo && pawnHasLoadout && !TrackingSatisfied(pawn, ammoType, magazineSize)) { // Do we have ammo in the inventory that the gun uses which satisfies requirements? (expensive) - AmmoDef matchAmmo = tmpComp.Props.ammoSet.ammoTypes + AmmoDef matchAmmo = tmpComp.CurAmmoSet.ammoTypes .Where(al => al.ammo != ammoType) .Select(al => al.ammo) .FirstOrDefault(ad => TrackingSatisfied(pawn, ad, magazineSize) diff --git a/Source/CombatExtended/CombatExtended/Jobs/JobGiver_ManTurretsNearPointCE.cs b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_ManTurretsNearPointCE.cs index c9448e901a..228f64d9f0 100644 --- a/Source/CombatExtended/CombatExtended/Jobs/JobGiver_ManTurretsNearPointCE.cs +++ b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_ManTurretsNearPointCE.cs @@ -54,7 +54,7 @@ private static Thing FindAmmoForTurret(Pawn pawn, Thing turret) 40f, t => !t.IsForbidden(pawn) && pawn.CanReserve(t, 10, 1) && - compAmmo.Props.ammoSet.ammoTypes.Any(l => l.ammo == t.def)); + compAmmo.CurAmmoSet.ammoTypes.Any(l => l.ammo == t.def)); } } } diff --git a/Source/CombatExtended/CombatExtended/Jobs/JobGiver_ManTurretsNearSelfCE.cs b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_ManTurretsNearSelfCE.cs index b02bca7243..1129cfa3d5 100644 --- a/Source/CombatExtended/CombatExtended/Jobs/JobGiver_ManTurretsNearSelfCE.cs +++ b/Source/CombatExtended/CombatExtended/Jobs/JobGiver_ManTurretsNearSelfCE.cs @@ -54,7 +54,7 @@ private static Thing FindAmmoForTurret(Pawn pawn, Thing turret) 40f, t => !t.IsForbidden(pawn) && pawn.CanReserve(t, 10, 1) && - compAmmo.Props.ammoSet.ammoTypes.Any(l => l.ammo == t.def)); + compAmmo.CurAmmoSet.ammoTypes.Any(l => l.ammo == t.def)); } } }