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;
+ }
+ }
+}