Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic ammo user for auto loader (very experimental) #2923

Draft
wants to merge 6 commits into
base: Development
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 89 additions & 123 deletions Defs/ThingDefs_Buildings/AutoLoaderExample.xml
Original file line number Diff line number Diff line change
@@ -1,144 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<Defs>
<!--

===Auto loader example def

<ThingDef ParentName="BuildingBase">
<defName>BDsAutoLoaderTest</defName>
<label>auto loader test</label>
<description>An ammo crate with magical autoloaders.</description>
<ThingDef ParentName="BuildingBase">
<defName>BDsAutoLoaderTest</defName>
<label>auto loader test</label>
<description>An ammo crate with magical autoloaders.</description>

===Thing class, ticker type and drawer type are mandatory===
<thingClass>CombatExtended.Building_AutoLoaderCE</thingClass>
<tickerType>Normal</tickerType>
<drawerType>MapMeshAndRealTime</drawerType>

<thingClass>CombatExtended.Building_AutoLoaderCE</thingClass>
<tickerType>Normal</tickerType>
<drawerType>MapMeshAndRealTime</drawerType>
<comps>
<li Class="CombatExtended.CompProperties_AmmoUser">
<compClass>CombatExtended.CompAmmoUserGeneric</compClass>
<magazineSize>400</magazineSize>
<reloadTime>7.8</reloadTime>
<ammoSet>AmmoSet_762x51mmNATO</ammoSet>
</li>

===This Ammo user is the autoloader's ammo capacity and reload time===
<li Class="CompProperties_Mannable">
<manWorkType>Hauling</manWorkType>
</li>
<li Class="CompProperties_Power">
<compClass>CompPowerTrader</compClass>
<basePowerConsumption>300</basePowerConsumption>
</li>
</comps>

<comps>
<li Class="CombatExtended.CompProperties_AmmoUser">
<magazineSize>400</magazineSize>
<reloadTime>7.8</reloadTime>
<ammoSet>AmmoSet_145x114mm</ammoSet>
</li>

===If CompMannable and CompPowerTrader are present, they'll be taken into account too, same goes for CompInitiatable and CompCanBeDormant===

<li Class="CompProperties_Mannable">
<manWorkType>Hauling</manWorkType>
</li>
<li Class="CompProperties_Power">
<compClass>CompPowerTrader</compClass>
<basePowerConsumption>300</basePowerConsumption>
</li>
</comps>

===Different graphics can be applied at empty, half full (above 0) and full (above 75%) if this mod extension exists===

<modExtensions>
<li Class="CombatExtended.ModExtension_AutoLoaderGraphics">
<fullGraphic>
<texPath>Things/Building/Misc/ToolCabinet</texPath>
<graphicClass>Graphic_Multi</graphicClass>
<drawSize>(2,1)</drawSize>
<color>(0,0,0)</color>
<damageData>
<cornerTL>Damage/Corner</cornerTL>
<cornerTR>Damage/Corner</cornerTR>
<cornerBL>Damage/Corner</cornerBL>
<cornerBR>Damage/Corner</cornerBR>
</damageData>
</fullGraphic>

<halfFullGraphic>
<li Class="CombatExtended.ModExtension_AutoLoaderGraphics">
<fullGraphic>
<texPath>Things/Building/Misc/ToolCabinet</texPath>
<graphicClass>Graphic_Multi</graphicClass>
<drawSize>(2,1)</drawSize>
<color>(0,0,0)</color>
<damageData>
<cornerTL>Damage/Corner</cornerTL>
<cornerTR>Damage/Corner</cornerTR>
<cornerBL>Damage/Corner</cornerBL>
<cornerBR>Damage/Corner</cornerBR>
</damageData>
</fullGraphic>

===This is left deliberately empty, The code should fall back to default graphic if the current situation's graphics is left blank===
<halfFullGraphic>

</halfFullGraphic>

<emptyGraphic>
<texPath>Things/Building/Misc/ToolCabinet</texPath>
<graphicClass>Graphic_Multi</graphicClass>
<drawSize>(2,1)</drawSize>
<color>(0,0,114)</color>
<damageData>
<cornerTL>Damage/Corner</cornerTL>
<cornerTR>Damage/Corner</cornerTR>
<cornerBL>Damage/Corner</cornerBL>
<cornerBR>Damage/Corner</cornerBR>
</damageData>
</emptyGraphic>

===Only turrets in this list will be reloaded, if it's not empty===

<allowedTurrets>
<li>Turret_Heavy</li>
</allowedTurrets>

==The tag here is buildingTags under building node, Not weapon tag. See the def of KPV for example

<allowedTurretTags>
<li>CE_TurretHeavy</li>
</allowedTurretTags>

===if left empty, a default machine cranking sound will play===
<emptyGraphic>
<texPath>Things/Building/Misc/ToolCabinet</texPath>
<graphicClass>Graphic_Multi</graphicClass>
<drawSize>(2,1)</drawSize>
<color>(0,0,114)</color>
<damageData>
<cornerTL>Damage/Corner</cornerTL>
<cornerTR>Damage/Corner</cornerTR>
<cornerBL>Damage/Corner</cornerBL>
<cornerBR>Damage/Corner</cornerBR>
</damageData>
</emptyGraphic>

<reloadingSustainer>Ingest_Drink</reloadingSustainer>

===if left empty, the intereact sound of the turret gun will play===

<reloadCompleteSound>Pawn_Chicken_Call</reloadCompleteSound>
</li>
</modExtensions>

===Generic stuffs here===
</modExtensions>

<graphicData>
<texPath>Things/Building/Misc/ToolCabinet</texPath>
<graphicClass>Graphic_Multi</graphicClass>
<drawSize>(2,1)</drawSize>
<color>(96,114,95)</color>
<damageData>
<cornerTL>Damage/Corner</cornerTL>
<cornerTR>Damage/Corner</cornerTR>
<cornerBL>Damage/Corner</cornerBL>
<cornerBR>Damage/Corner</cornerBR>
</damageData>
</graphicData>
<altitudeLayer>Building</altitudeLayer>
<passability>PassThroughOnly</passability>
<castEdgeShadows>true</castEdgeShadows>
<staticSunShadowHeight>0.35</staticSunShadowHeight>
<graphicData>
<texPath>Things/Building/Misc/ToolCabinet</texPath>
<graphicClass>Graphic_Multi</graphicClass>
<drawSize>(2,1)</drawSize>
<color>(96,114,95)</color>
<damageData>
<cornerTL>Damage/Corner</cornerTL>
<cornerTR>Damage/Corner</cornerTR>
<cornerBL>Damage/Corner</cornerBL>
<cornerBR>Damage/Corner</cornerBR>
</damageData>
</graphicData>
<altitudeLayer>Building</altitudeLayer>
<passability>PassThroughOnly</passability>
<castEdgeShadows>true</castEdgeShadows>
<staticSunShadowHeight>0.35</staticSunShadowHeight>
<hasInteractionCell>True</hasInteractionCell>
<interactionCellOffset>(0,0,-1)</interactionCellOffset>
<fillPercent>0.5</fillPercent>
<canOverlapZones>false</canOverlapZones>
<pathCost>42</pathCost>
<size>(2,1)</size>
<costList>
<Steel>200</Steel>
</costList>
<building>
<destroySound>BuildingDestroyed_Metal_Small</destroySound>
</building>
<statBases>
<MaxHitPoints>100</MaxHitPoints>
<WorkToBuild>1800</WorkToBuild>
<Mass>20</Mass>
<Flammability>0.5</Flammability>

===Look at this reload speed. this controls how fast/slow autoloader loads===

<ReloadSpeed>0.5</ReloadSpeed>
</statBases>
<designationCategory>Misc</designationCategory>
<minifiedDef>MinifiedThing</minifiedDef>
<thingCategories>
<li>BuildingsMisc</li>
</thingCategories>
</ThingDef>
-->
<fillPercent>0.5</fillPercent>
<canOverlapZones>false</canOverlapZones>
<pathCost>42</pathCost>
<size>(2,1)</size>
<costList>
<Steel>200</Steel>
</costList>
<building>
<destroySound>BuildingDestroyed_Metal_Small</destroySound>
</building>
<statBases>
<MaxHitPoints>100</MaxHitPoints>
<WorkToBuild>1800</WorkToBuild>
<Mass>20</Mass>
<Flammability>0.5</Flammability>

<ReloadSpeed>0.5</ReloadSpeed>
</statBases>
<designationCategory>Misc</designationCategory>
<minifiedDef>MinifiedThing</minifiedDef>
<thingCategories>
<li>BuildingsMisc</li>
</thingCategories>
</ThingDef>

</Defs>
Original file line number Diff line number Diff line change
Expand Up @@ -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<AutoLoaderTracker>().Register(this);
CompAmmoUser = GetComp<CompAmmoUser>();
CompAmmoUser = this.TryGetComp<CompAmmoUser>();

dormantComp = GetComp<CompCanBeDormant>();
initiatableComp = GetComp<CompInitiatable>();
Expand Down Expand Up @@ -228,7 +228,7 @@ public override IEnumerable<Gizmo> 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;
Expand Down Expand Up @@ -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;
}
}
}
}
Expand Down
28 changes: 15 additions & 13 deletions Source/CombatExtended/CombatExtended/Comps/CompAmmoUser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -267,7 +269,7 @@ private Map Map
}
public bool ShouldThrowMote => Props.throwMote && MagSize > 1;

public AmmoDef SelectedAmmo
public virtual AmmoDef SelectedAmmo
{
get
{
Expand Down Expand Up @@ -297,15 +299,15 @@ 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");
}
else
{
if (currentAmmoInt == null)
{
currentAmmoInt = (AmmoDef)Props.ammoSet.ammoTypes[0].ammo;
currentAmmoInt = (AmmoDef)CurAmmoSet.ammoTypes[0].ammo;
}
if (selectedAmmo == null)
{
Expand Down Expand Up @@ -671,7 +673,7 @@ public bool TryPickupAmmo()
{
return false;
}
IEnumerable<AmmoDef> supportedAmmo = Props.ammoSet.ammoTypes.Select(a => a.ammo);
IEnumerable<AmmoDef> 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)))))
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -927,7 +929,7 @@ public override IEnumerable<Gizmo> 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;
}

Expand Down
Loading
Loading