Skip to content

Commit

Permalink
Initial cleanup of partial armor implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
AluminumAlman committed Jan 2, 2025
1 parent 64cd332 commit 763f487
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 100 deletions.
25 changes: 3 additions & 22 deletions Source/CombatExtended/CombatExtended/ArmorUtilityCE.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RimWorld;
using Verse;
using UnityEngine;
Expand Down Expand Up @@ -96,7 +95,7 @@ public static DamageInfo GetAfterArmorDamage(DamageInfo originalDinfo, Pawn pawn
}
else
{
var hasCoverage = shieldDef.PartIsCoveredByShield(hitPart, pawn);
var hasCoverage = shieldDef.PartIsCoveredByShield(hitPart, pawn.IsCrouching());
if (hasCoverage)
{
// Right arm is vulnerable during warmup/attack/cooldown
Expand Down Expand Up @@ -245,7 +244,7 @@ public static DamageInfo GetAfterArmorDamage(DamageInfo originalDinfo, Pawn pawn
{
var curPart = partsToHit[i];
var coveredByArmor = curPart.IsInGroup(CE_BodyPartGroupDefOf.CoveredByNaturalArmor);
var armorAmount = coveredByArmor ? pawn.PartialStat(dinfo.Def.armorCategory.armorRatingStat, curPart, dmgAmount, penAmount) : 0;
var armorAmount = coveredByArmor ? pawn.PartialStat(dinfo.Def.armorCategory.armorRatingStat, curPart) : 0;

// Only apply damage reduction when penetrating armored body parts
if (!TryPenetrateArmor(dinfo.Def, armorAmount, ref penAmount, ref dmgAmount, null, partDensity))
Expand Down Expand Up @@ -544,7 +543,7 @@ private static DamageInfo GetDeflectDamageInfo(DamageInfo dinfo, BodyPartRecord
localPenAmount,
dinfo.Angle,
dinfo.Instigator,
GetOuterMostParent(hitPart),
CE_Utility.GetOuterMostParent(hitPart),
partialPen ? null : dinfo.Weapon, //To not apply the secondary damage twice on partial penetrations.
instigatorGuilty: dinfo.InstigatorGuilty);
newDinfo.SetBodyRegion(dinfo.Height, dinfo.Depth);
Expand All @@ -560,24 +559,6 @@ private static DamageInfo GetDeflectDamageInfo(DamageInfo dinfo, BodyPartRecord
return newDinfo;
}

/// <summary>
/// Retrieves the first parent of a body part with depth Outside
/// </summary>
/// <param name="part">The part to get the parent of</param>
/// <returns>The first parent part with depth Outside, the original part if it already is Outside or doesn't have a parent, the root part if no parents are Outside</returns>
private static BodyPartRecord GetOuterMostParent(BodyPartRecord part)
{
var curPart = part;
if (curPart != null)
{
while (curPart.parent != null && curPart.depth != BodyPartDepth.Outside)
{
curPart = curPart.parent;
}
}
return curPart;
}

/// <summary>
/// Determines whether a dinfo is of an ambient (i.e. heat, electric) damage type and should apply percentage reduction, as opposed to deflection-based reduction
/// </summary>
Expand Down
152 changes: 87 additions & 65 deletions Source/CombatExtended/CombatExtended/CE_Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using RimWorld;
using Verse;
using Verse.AI;
using Verse.Sound;
using UnityEngine;
using System.Runtime.CompilerServices;
using RimWorld.Planet;

namespace CombatExtended
Expand Down Expand Up @@ -435,69 +432,99 @@ public static T GetLastModExtension<T>(this Def def) where T : DefModExtension
}

/// <summary>
/// Gets the true rating of armor with partial stats taken into account
/// Retrieves the first parent of a body part with depth Outside
/// </summary>
public static float PartialStat(this Apparel apparel, StatDef stat, BodyPartRecord part)
/// <param name="part">The part to get the parent of</param>
/// <returns>The first parent part with depth Outside, the original part if it already is Outside or doesn't have a parent, the root part if no parents are Outside</returns>
public static BodyPartRecord GetOuterMostParent(BodyPartRecord part)
{
if (!apparel.def.apparel.CoversBodyPart(part))
var curPart = part;
if (curPart != null)
{
return 0;
while (curPart.parent != null && curPart.depth != BodyPartDepth.Outside)
{
curPart = curPart.parent;
}
}
return curPart;
}

/// <summary>
/// Gets the true rating of armor with partial stats taken into account
/// </summary>
public static float PartialStat(this Apparel apparel, StatDef stat, BodyPartRecord part)
{
float result = apparel.GetStatValue(stat);
if (part == null)
{
return result;
}

if (Controller.settings.PartialStat)
if (!apparel.def.apparel.CoversBodyPart(part))
{
if (apparel.def.HasModExtension<PartialArmorExt>())
var shieldDef = apparel.def.GetModExtension<ShieldDefExtension>();
if (shieldDef == null || !shieldDef.PartIsCoveredByShield(part, true))
{
foreach (ApparelPartialStat partial in apparel.def.GetModExtension<PartialArmorExt>().stats)
{
if ((partial?.parts?.Contains(part.def) ?? false) | ((partial?.parts?.Contains(part?.parent?.def) ?? false) && part.depth == BodyPartDepth.Inside))
{
return 0f;
}
}

if (partial.staticValue > 0f)
{
return partial.staticValue;
}
result *= partial.mult;
break;
if (!Controller.settings.PartialStat)
{
return result;
}

}
}
PartialArmorExt partialArmorExt = apparel.def.GetModExtension<PartialArmorExt>();
if (partialArmorExt == null)
{
return result;
}

foreach (ApparelPartialStat partial in partialArmorExt.stats)
{
if (partial.stat != stat || !partial.parts.Contains(GetOuterMostParent(part).def))
{
continue;
}
result = partial.staticValue > 0f ? partial.staticValue : result * partial.mult;
}
return result;
}

/// <summary>
/// Gets the true rating of armor with partial stats taken into account
/// </summary>
public static float PartialStat(this Pawn pawn, StatDef stat, BodyPartRecord part, float damage = 0f, float AP = 0f)
public static float PartialStat(this Pawn pawn, StatDef stat, BodyPartRecord part)
{
float result = pawn.GetStatValue(stat);
if (part == null)
{
return result;
}

if (Controller.settings.PartialStat)
if (!part.IsInGroup(CE_BodyPartGroupDefOf.CoveredByNaturalArmor))
{
if (pawn.def.HasModExtension<PartialArmorExt>())
{
foreach (ApparelPartialStat partial in pawn.def.GetModExtension<PartialArmorExt>().stats)
{
if (partial.stat == stat)
{
if ((partial?.parts?.Contains(part.def) ?? false) | ((partial?.parts?.Contains(part?.parent?.def) ?? false) && part.depth == BodyPartDepth.Inside))
{
return 0f;
}

if (partial.staticValue > 0f)
{
return partial.staticValue;
}
result *= partial.mult;
break;
if (!Controller.settings.PartialStat)
{
return result;
}

}
}
}
PartialArmorExt partialArmorExt = pawn.def.GetModExtension<PartialArmorExt>();
if (partialArmorExt == null)
{
return result;
}

foreach (ApparelPartialStat partial in partialArmorExt.stats)
{
if (partial.stat != stat || !partial.parts.Contains(GetOuterMostParent(part).def))
{
continue;
}
result = partial.staticValue > 0f ? partial.staticValue : result * partial.mult;
}
return result;
}
Expand All @@ -508,22 +535,19 @@ public static float PartialStat(this Pawn pawn, StatDef stat, BodyPartRecord par
public static float PartialStat(this Apparel apparel, StatDef stat, BodyPartDef part)
{
float result = apparel.GetStatValue(stat);
if (apparel.def.HasModExtension<PartialArmorExt>())
PartialArmorExt partialArmorExt = apparel.def.GetModExtension<PartialArmorExt>();
if (partialArmorExt == null)
{
foreach (ApparelPartialStat partial in apparel.def.GetModExtension<PartialArmorExt>().stats)
{
if ((partial?.parts?.Contains(part) ?? false))
{

if (partial.staticValue > 0f)
{
return partial.staticValue;
}
result *= partial.mult;
break;
return result;
}

}
foreach (ApparelPartialStat partial in partialArmorExt.stats)
{
if (partial.stat != stat || !partial.parts.Contains(part))
{
continue;
}
result = partial.staticValue > 0f ? partial.staticValue : result * partial.mult;
}
return result;
}
Expand All @@ -534,21 +558,19 @@ public static float PartialStat(this Apparel apparel, StatDef stat, BodyPartDef
public static float PartialStat(this Pawn pawn, StatDef stat, BodyPartDef part)
{
float result = pawn.GetStatValue(stat);
if (pawn.def.HasModExtension<PartialArmorExt>())
PartialArmorExt partialArmorExt = pawn.def.GetModExtension<PartialArmorExt>();
if (partialArmorExt == null)
{
foreach (ApparelPartialStat partial in pawn.def.GetModExtension<PartialArmorExt>().stats)
{
if ((partial?.parts?.Contains(part) ?? false))
{
if (partial.staticValue > 0f)
{
return partial.staticValue;
}
result *= partial.mult;
break;
return result;
}

}
foreach (ApparelPartialStat partial in partialArmorExt.stats)
{
if (partial.stat != stat || !partial.parts.Contains(part))
{
continue;
}
result = partial.staticValue > 0f ? partial.staticValue : result * partial.mult;
}
return result;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,19 @@ public class ApparelPartialStat
{
public StatDef stat;

public float mult;
public float mult = 0f;

public List<BodyPartDef> parts;

public float staticValue = 0f;

public bool useStatic = false;

public void LoadDataFromXmlCustom(XmlNode xmlRoot)
{
bool useStatic = false;
int index = 1;
if (xmlRoot.FirstChild.Name.Contains("use"))
{
this.useStatic = ParseHelper.FromString<bool>(xmlRoot.FirstChild.InnerText);
useStatic = ParseHelper.FromString<bool>(xmlRoot.FirstChild.InnerText);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class ShieldDefExtension : DefModExtension
public List<BodyPartGroupDef> crouchCoverage = new List<BodyPartGroupDef>();
public bool drawAsTall = false;

public bool PartIsCoveredByShield(BodyPartRecord part, Pawn pawn)
public bool PartIsCoveredByShield(BodyPartRecord part, bool isPawnCrouching)
{
if (!shieldCoverage.NullOrEmpty())
{
Expand All @@ -26,7 +26,7 @@ public bool PartIsCoveredByShield(BodyPartRecord part, Pawn pawn)
}
}
}
if (!crouchCoverage.NullOrEmpty() && pawn.IsCrouching())
if (!crouchCoverage.NullOrEmpty() && isPawnCrouching)
{
foreach (BodyPartGroupDef group in crouchCoverage)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Text.RegularExpressions;
using RimWorld;
using RimWorld;
using RimWorld.Planet;
using System;
using System.Collections.Generic;
Expand All @@ -8,7 +7,6 @@
using Verse;
using Verse.AI;
using Verse.Sound;
using CombatExtended.HarmonyCE;

namespace CombatExtended
{
Expand Down Expand Up @@ -535,7 +533,7 @@ private void RebuildArmorCache(Dictionary<BodyPartRecord, float> armorCache, Sta
{
if (!shield.def.apparel.CoversBodyPart(part))
{
var shieldCoverage = shield.def?.GetModExtension<ShieldDefExtension>()?.PartIsCoveredByShield(part, SelPawnForGear);
var shieldCoverage = shield.def?.GetModExtension<ShieldDefExtension>()?.PartIsCoveredByShield(part, SelPawnForGear.IsCrouching());
if (shieldCoverage == true)
{
armorValue += shield.GetStatValue(stat);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public override string GetExplanationFinalizePart(StatRequest req, ToStringNumbe

if (partstat.stat == this.stat)
{
if (!partstat.useStatic)
if (partstat.staticValue <= 0f)
{
result += "\n" + "CE_Multiplier".Translate() + " " + partstat.mult.ToStringPercent();
}
Expand Down Expand Up @@ -164,7 +164,7 @@ public override string GetStatDrawEntryLabel(StatDef stat, float value, ToString
{

float thisArmor = value;
if (p.useStatic)
if (p.staticValue > 0f)
{
thisArmor = p.staticValue;
}
Expand Down Expand Up @@ -197,7 +197,7 @@ public override string GetStatDrawEntryLabel(StatDef stat, float value, ToString
float thisArmor = value;
if (partstat.stat == stat)
{
if (partstat.useStatic)
if (partstat.staticValue > 0f)
{
thisArmor = partstat.staticValue;
}
Expand Down

0 comments on commit 763f487

Please sign in to comment.