diff --git a/Assemblies/CombatExtended.dll b/Assemblies/CombatExtended.dll index 3b35078073..f7d87cf991 100644 Binary files a/Assemblies/CombatExtended.dll and b/Assemblies/CombatExtended.dll differ diff --git a/Languages/English/Keyed/Keys.xml b/Languages/English/Keyed/Keys.xml index 7d30222151..2a0df5cb23 100644 --- a/Languages/English/Keyed/Keys.xml +++ b/Languages/English/Keyed/Keys.xml @@ -20,6 +20,7 @@ Marked for artillery, expires in Visibility error + Smoke Lead error Range error Sway diff --git a/Patches/Core/ThingDefs_Buildings/Buildings_Security.xml b/Patches/Core/ThingDefs_Buildings/Buildings_Security.xml index cdca9c50be..9012f047a0 100644 --- a/Patches/Core/ThingDefs_Buildings/Buildings_Security.xml +++ b/Patches/Core/ThingDefs_Buildings/Buildings_Security.xml @@ -3,6 +3,13 @@ + + */ThingDef[defName="Sandbags"]/costList/Steel + + 2 + + + */ThingDef[defName="Sandbags"]/fillPercent diff --git a/Patches/Core/ThingDefs_Misc/Weapons_Grenades.xml b/Patches/Core/ThingDefs_Misc/Weapons_Grenades.xml index 9ac2a1b8c0..5e9cab048f 100644 --- a/Patches/Core/ThingDefs_Misc/Weapons_Grenades.xml +++ b/Patches/Core/ThingDefs_Misc/Weapons_Grenades.xml @@ -47,7 +47,7 @@ 1.5 Bomb - 80 + 50 60 true Mote_GrenadePin diff --git a/Source/CombatExtended/CombatExtended.csproj b/Source/CombatExtended/CombatExtended.csproj index 937ad0ee40..eca236ea64 100644 --- a/Source/CombatExtended/CombatExtended.csproj +++ b/Source/CombatExtended/CombatExtended.csproj @@ -228,10 +228,12 @@ + + diff --git a/Source/CombatExtended/CombatExtended/ArmorUtilityCE.cs b/Source/CombatExtended/CombatExtended/ArmorUtilityCE.cs index 160f487316..c342b48caa 100644 --- a/Source/CombatExtended/CombatExtended/ArmorUtilityCE.cs +++ b/Source/CombatExtended/CombatExtended/ArmorUtilityCE.cs @@ -385,7 +385,7 @@ public static void ApplyParryDamage(DamageInfo dinfo, Thing parryThing) } else { - float dmgAmount = dinfo.Amount; + float dmgAmount = dinfo.Amount * 0.5f; float penAmount = GetPenetrationValue(dinfo); TryPenetrateArmor(dinfo.Def, parryThing.GetStatValue(dinfo.Def.armorCategory.deflectionStat), ref penAmount, ref dmgAmount, parryThing); } diff --git a/Source/CombatExtended/CombatExtended/ShiftVecReport.cs b/Source/CombatExtended/CombatExtended/ShiftVecReport.cs index ca2737a2c3..b1a75e65e1 100644 --- a/Source/CombatExtended/CombatExtended/ShiftVecReport.cs +++ b/Source/CombatExtended/CombatExtended/ShiftVecReport.cs @@ -47,7 +47,7 @@ public float visibilityShift { if (visibilityShiftInt < 0) { - visibilityShiftInt = (lightingShift + weatherShift) * (shotDist / 50) * (2 - aimingAccuracy); + visibilityShiftInt = (lightingShift + weatherShift + smokeDensity) * (shotDist / 50) * (2 - aimingAccuracy); } return visibilityShiftInt; } @@ -105,6 +105,7 @@ public float distShift public float swayDegrees = 0f; public float spreadDegrees = 0f; public Thing cover = null; + public float smokeDensity = 0f; // Copy-constructor public ShiftVecReport(ShiftVecReport report) @@ -121,6 +122,7 @@ public ShiftVecReport(ShiftVecReport report) swayDegrees = report.swayDegrees; spreadDegrees = report.spreadDegrees; cover = report.cover; + smokeDensity = report.smokeDensity; } public ShiftVecReport() @@ -176,6 +178,10 @@ public string GetTextReadout() { stringBuilder.AppendLine(" " + "Weather".Translate() + "\t" + AsPercent(weatherShift)); } + if (smokeDensity > 0) + { + stringBuilder.AppendLine(" " + "CE_SmokeDensity".Translate() + "\t" + AsPercent(smokeDensity)); + } } if (leadShift > 0) { diff --git a/Source/CombatExtended/CombatExtended/Verbs/Verb_LaunchProjectileCE.cs b/Source/CombatExtended/CombatExtended/Verbs/Verb_LaunchProjectileCE.cs index 73f41c3668..cb5e332870 100644 --- a/Source/CombatExtended/CombatExtended/Verbs/Verb_LaunchProjectileCE.cs +++ b/Source/CombatExtended/CombatExtended/Verbs/Verb_LaunchProjectileCE.cs @@ -343,8 +343,10 @@ public virtual ShiftVecReport ShiftVecReportFor(LocalTargetInfo target) report.swayDegrees = this.SwayAmplitude; report.spreadDegrees = this.ownerEquipment.GetStatValue(StatDef.Named("ShotSpread")) * this.projectilePropsCE.spreadMult; Thing cover; - this.GetHighestCoverForTarget(target, out cover); + float smokeDensity; + this.GetHighestCoverAndSmokeForTarget(target, out cover, out smokeDensity); report.cover = cover; + report.smokeDensity = smokeDensity; return report; } @@ -355,14 +357,16 @@ public virtual ShiftVecReport ShiftVecReportFor(LocalTargetInfo target) /// The target of which to find cover of /// Output parameter, filled with the highest cover object found /// True if cover was found, false otherwise - private bool GetHighestCoverForTarget(LocalTargetInfo target, out Thing cover) + private bool GetHighestCoverAndSmokeForTarget(LocalTargetInfo target, out Thing cover, out float smokeDensity) { Map map = caster.Map; Thing targetThing = target.Thing; Thing highestCover = null; float highestCoverHeight = 0f; - // Iterate through all cells on second half of line of sight and check for cover + smokeDensity = 0; + + // Iterate through all cells on line of sight and check for cover and smoke var cells = GenSight.PointsOnLineOfSight(target.Cell, caster.Position).ToArray(); if (cells.Length < 3) { @@ -375,20 +379,31 @@ private bool GetHighestCoverForTarget(LocalTargetInfo target, out Thing cover) if (cell.AdjacentTo8Way(caster.Position)) continue; - Pawn pawn = cell.GetFirstPawn(map); - Thing newCover = pawn == null ? cell.GetCover(map) : pawn; - float newCoverHeight = new CollisionVertical(newCover).Max; - - // Cover check, if cell has cover compare collision height and get the highest piece of cover, ignore if cover is the target (e.g. solar panels, crashed ship, etc) - if (newCover != null - && (targetThing == null || !newCover.Equals(targetThing)) - && (highestCover == null || highestCoverHeight < newCoverHeight) - && newCover.def.Fillage == FillCategory.Partial - && !newCover.IsTree()) + // Check for smoke + var gas = cell.GetGas(map); + if (gas != null) + { + smokeDensity += gas.def.gas.accuracyPenalty; + } + + // Check for cover in the second half of LoS + if (i <= cells.Length / 2) { - highestCover = newCover; - highestCoverHeight = newCoverHeight; - if (Controller.settings.DebugDrawTargetCoverChecks) map.debugDrawer.FlashCell(cell, highestCoverHeight, highestCoverHeight.ToString()); + Pawn pawn = cell.GetFirstPawn(map); + Thing newCover = pawn == null ? cell.GetCover(map) : pawn; + float newCoverHeight = new CollisionVertical(newCover).Max; + + // Cover check, if cell has cover compare collision height and get the highest piece of cover, ignore if cover is the target (e.g. solar panels, crashed ship, etc) + if (newCover != null + && (targetThing == null || !newCover.Equals(targetThing)) + && (highestCover == null || highestCoverHeight < newCoverHeight) + && newCover.def.Fillage == FillCategory.Partial + && !newCover.IsTree()) + { + highestCover = newCover; + highestCoverHeight = newCoverHeight; + if (Controller.settings.DebugDrawTargetCoverChecks) map.debugDrawer.FlashCell(cell, highestCoverHeight, highestCoverHeight.ToString()); + } } } cover = highestCover; diff --git a/Source/CombatExtended/Harmony/Harmony-Hediff_MissingPart.cs b/Source/CombatExtended/Harmony/Harmony-Hediff_MissingPart.cs index cc5d7be615..17662a7eec 100644 --- a/Source/CombatExtended/Harmony/Harmony-Hediff_MissingPart.cs +++ b/Source/CombatExtended/Harmony/Harmony-Hediff_MissingPart.cs @@ -9,6 +9,7 @@ namespace CombatExtended.Harmony { + // FIXME: Destructive detour [HarmonyPatch(typeof(Hediff_MissingPart))] [HarmonyPatch("IsFreshNonSolidExtremity", PropertyMethod.Getter)] static class Harmony_Hediff_MissingPart_IsFresh_Patch diff --git a/Source/CombatExtended/Harmony/Harmony-SmokepopBelt.cs b/Source/CombatExtended/Harmony/Harmony-SmokepopBelt.cs new file mode 100644 index 0000000000..a278bc0671 --- /dev/null +++ b/Source/CombatExtended/Harmony/Harmony-SmokepopBelt.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RimWorld; +using Verse; +using UnityEngine; +using Harmony; + +namespace CombatExtended.Harmony +{ + // FIXME: Destructive detour + [HarmonyPatch(typeof(SmokepopBelt), "CheckPreAbsorbDamage")] + static class Harmony_SmokepopBelt + { + public static bool Prefix(SmokepopBelt __instance, DamageInfo dinfo) + { + if (!dinfo.Def.isExplosive + && dinfo.Def.harmsHealth + && dinfo.Def.externalViolence + && dinfo.WeaponGear != null + && (dinfo.WeaponGear.IsRangedWeapon || dinfo.WeaponGear.projectile is ProjectilePropertiesCE)) // Add a check for CE projectiles since we're using them as weaponGear to pass data to our ArmorUtility + { + ThingDef gas_Smoke = ThingDefOf.Gas_Smoke; + GenExplosion.DoExplosion(__instance.Wearer.Position, __instance.Wearer.Map, __instance.GetStatValue(StatDefOf.SmokepopBeltRadius, true), DamageDefOf.Smoke, null, null, null, null, gas_Smoke, 1f, 1, false, null, 0f, 1); + __instance.Destroy(DestroyMode.Vanish); + } + return false; + } + } +}