diff --git a/1.4/Assemblies/CombatAI.dll b/1.4/Assemblies/CombatAI.dll
index cad93bd..0a82ce5 100644
Binary files a/1.4/Assemblies/CombatAI.dll and b/1.4/Assemblies/CombatAI.dll differ
diff --git a/Source/Rule56/CombatAI.csproj b/Source/Rule56/CombatAI.csproj
index c7da079..6f73657 100644
--- a/Source/Rule56/CombatAI.csproj
+++ b/Source/Rule56/CombatAI.csproj
@@ -32,35 +32,35 @@
true
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -94,11 +94,11 @@
-
-
-
-
-
+
+
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
@@ -107,17 +107,17 @@
-
+
-
+
$(PkgMono_TextTransform)\tools\TextTransform.exe
-
-
+
+
@@ -131,12 +131,12 @@
$(PubliciseOutputPath)UnityEngine.CoreModule_publicised.dll
-
-
-
-
+
+
+
+
-
+
false
@@ -153,10 +153,10 @@
-
+
-
-
+
+
@@ -166,7 +166,7 @@
-
+
diff --git a/Source/Rule56/CombatAIMod.cs b/Source/Rule56/CombatAIMod.cs
index ed2a715..545d109 100644
--- a/Source/Rule56/CombatAIMod.cs
+++ b/Source/Rule56/CombatAIMod.cs
@@ -28,9 +28,9 @@ public class CombatAIMod : Mod
private bool collapsibleGroupInited;
public CombatAIMod(ModContentPack contentPack) : base(contentPack)
{
+ Finder.Mod = this;
Finder.Harmony = new Harmony("Krkr.Rule56");
Finder.Harmony.PatchAll();
- Finder.Mod = this;
Finder.Settings = GetSettings();
if (Finder.Settings == null)
{
@@ -100,7 +100,7 @@ private void FillCollapsible_Basic(Listing_Collapsible collapsible)
Finder.Settings.Enable_Sprinting = false;
Finder.Settings.Enable_Groups = false;
- Finder.Settings.Pathfinding_SappingMul = 0.5f;
+ Finder.Settings.Pathfinding_SappingMul = 1.5f;
Finder.Settings.SightSettings_FriendliesAndRaiders.interval = 3;
if (Current.ProgramState != ProgramState.Playing)
@@ -135,7 +135,7 @@ private void FillCollapsible_Basic(Listing_Collapsible collapsible)
Finder.Settings.Flank_Enabled = true;
Finder.Settings.Enable_Sprinting = false;
Finder.Settings.Enable_Groups = true;
- Finder.Settings.Pathfinding_SappingMul = 1.0f;
+ Finder.Settings.Pathfinding_SappingMul = 1.3f;
Finder.Settings.SightSettings_FriendliesAndRaiders.interval = 3;
if (Current.ProgramState != ProgramState.Playing)
{
@@ -170,7 +170,7 @@ private void FillCollapsible_Basic(Listing_Collapsible collapsible)
Finder.Settings.Enable_Sprinting = false;
Finder.Settings.Enable_Groups = true;
- Finder.Settings.Pathfinding_SappingMul = 0.9f;
+ Finder.Settings.Pathfinding_SappingMul = 1.0f;
Finder.Settings.SightSettings_FriendliesAndRaiders.interval = 2;
if (Current.ProgramState != ProgramState.Playing)
@@ -207,7 +207,7 @@ private void FillCollapsible_Basic(Listing_Collapsible collapsible)
Finder.Settings.Enable_Sprinting = true;
Finder.Settings.Enable_Groups = true;
- Finder.Settings.Pathfinding_SappingMul = 0.85f;
+ Finder.Settings.Pathfinding_SappingMul = 1.0f;
Finder.Settings.SightSettings_FriendliesAndRaiders.interval = 1;
if (Current.ProgramState != ProgramState.Playing)
diff --git a/Source/Rule56/CombatAI_Utility.cs b/Source/Rule56/CombatAI_Utility.cs
index 38acd5e..3de64ed 100644
--- a/Source/Rule56/CombatAI_Utility.cs
+++ b/Source/Rule56/CombatAI_Utility.cs
@@ -1,4 +1,5 @@
-using RimWorld;
+using System.Collections.Generic;
+using RimWorld;
using UnityEngine;
using Verse;
using Verse.AI;
diff --git a/Source/Rule56/Comps/ThingComp_CombatAI.cs b/Source/Rule56/Comps/ThingComp_CombatAI.cs
index dee152b..bc06a0c 100644
--- a/Source/Rule56/Comps/ThingComp_CombatAI.cs
+++ b/Source/Rule56/Comps/ThingComp_CombatAI.cs
@@ -510,6 +510,11 @@ public void OnScanFinished()
/// Damage info
public void Notify_TookDamage(DamageInfo dInfo)
{
+ // notify the custom duty manager that this pawn took damage.
+ if (duties != null)
+ {
+ duties.Notify_TookDamage();
+ }
// if the pawn is tanky enough skip.
if (Finder.Settings.Retreat_Enabled && parent.Spawned && GenTicks.TicksGame - lastScanned < 90 && parent is Pawn pawn && !pawn.Dead && !pawn.Downed && armor.TankInt < 0.4f)
{
@@ -582,6 +587,12 @@ public void StartSapper(List blocked, IntVec3 cellBefore, bool findEsco
sapperNodes.AddRange(blocked);
_sap = 0;
TryStartSapperJob();
+// if ((pawn.needs?.food?.CurCategory != HungerCategory.Fed) && pawn.Position.DistanceToSquared(cellBefore) < 13f)
+// {
+// List pawns = escorts.ToList();
+// pawns.Add(pawn);
+// SuppliesUtility.FulfillFoodSupplies(pawns, pawn.Map);
+// }
}
///
@@ -694,10 +705,10 @@ private void TryStartSapperJob()
job.maxNumMeleeAttacks = 300;
pawn.jobs.StopAll();
pawn.jobs.StartJob(job, JobCondition.InterruptForced);
- if (findEscorts)
+ if (findEscorts && Rand.Chance(1 - Maths.Max(1f / (escorts.Count + 1f), 0.85f)))
{
int count = escorts.Count;
- int countTarget = Rand.Int % 6 + 4 + Maths.Min(sapperNodes.Count, 10);
+ int countTarget = Rand.Int % 4 + 3 + Maths.Min(sapperNodes.Count, 10);
Faction faction = pawn.Faction;
Predicate validator = t =>
{
@@ -708,16 +719,21 @@ private void TryStartSapperJob()
&& ally.skills?.GetSkill(SkillDefOf.Mining).Level < 10)
{
ThingComp_CombatAI comp = ally.GetComp_Fast();
- if (comp?.duties != null && comp.duties?.Any(DutyDefOf.Escort) == false && !comp.IsSapping && GenTicks.TicksGame - comp.releasedTick < 600)
+ if (comp?.duties != null && comp.duties?.Any(DutyDefOf.Escort) == false && !comp.IsSapping && GenTicks.TicksGame - comp.releasedTick > 600)
{
- Pawn_CustomDutyTracker.CustomPawnDuty custom = CustomDutyUtility.Escort(ally, pawn, 20, 100, 500 * sapperNodes.Count + Rand.Int % 1000);
- if (custom != null)
+ Pawn_CustomDutyTracker.CustomPawnDuty custom = CustomDutyUtility.Escort(pawn, 20, 100, (500 * sapperNodes.Count) / (escorts.Count + 1) + Rand.Int % 500);
+ if (ally.TryStartCustomDuty(custom))
{
- custom.duty.locomotion = Finder.Settings.Enable_Sprinting ? LocomotionUrgency.Sprint : LocomotionUrgency.Jog;
- comp.duties.StartDuty(custom);
escorts.Add(ally);
}
- count++;
+ if (comp.duties.curCustomDuty?.duty != duties.curCustomDuty?.duty)
+ {
+ count += 3;
+ }
+ else
+ {
+ count++;
+ }
}
return count == countTarget;
}
diff --git a/Source/Rule56/CustomDuties/CustomDutyUtility.cs b/Source/Rule56/CustomDuties/CustomDutyUtility.cs
new file mode 100644
index 0000000..92e7278
--- /dev/null
+++ b/Source/Rule56/CustomDuties/CustomDutyUtility.cs
@@ -0,0 +1,102 @@
+using System.Runtime.CompilerServices;
+using CombatAI.Comps;
+using RimWorld;
+using Verse;
+using Verse.AI;
+namespace CombatAI
+{
+ public static class CustomDutyUtility
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Pawn_CustomDutyTracker GetPawnCustomDutyTracker(this Pawn pawn)
+ {
+ return pawn.GetComp_Fast()?.duties ?? null;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool AnyCustomDuties(this Pawn pawn, DutyDef def)
+ {
+ return pawn.GetPawnCustomDutyTracker()?.Any(def) ?? false;
+ }
+
+ public static bool TryStartCustomDuty(this Pawn pawn, Pawn_CustomDutyTracker.CustomPawnDuty duty, bool returnCurDutyToQueue = true)
+ {
+ ThingComp_CombatAI comp = pawn.GetComp_Fast();
+ if (comp == null)
+ {
+ return false;
+ }
+ comp.duties.StartDuty(duty, returnCurDutyToQueue: returnCurDutyToQueue);
+ return true;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void EnqueueFirstCustomDuty(this Pawn pawn, Pawn_CustomDutyTracker.CustomPawnDuty duty)
+ {
+ ThingComp_CombatAI comp = pawn.GetComp_Fast();
+ if (comp?.duties == null)
+ {
+ comp.duties.EnqueueFirst(duty);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void EnqueueCustomDuty(this Pawn pawn, Pawn_CustomDutyTracker.CustomPawnDuty duty)
+ {
+ ThingComp_CombatAI comp = pawn.GetComp_Fast();
+ if (comp?.duties == null)
+ {
+ comp.duties.Enqueue(duty);
+ }
+ }
+
+ public static Pawn_CustomDutyTracker.CustomPawnDuty Escort(Pawn escortee, int radius = -1, int failOnDist = 0, int expireAfter = 0, int startAfter = 0, bool failOnFocusDowned = true, DutyDef failOnFocusDutyNot = null)
+ {
+ Pawn_CustomDutyTracker.CustomPawnDuty custom = new Pawn_CustomDutyTracker.CustomPawnDuty
+ {
+ duty = new PawnDuty(DutyDefOf.Escort, escortee, radius)
+ {
+ locomotion = LocomotionUrgency.Sprint
+ },
+ endOnDistToFocusLarger = failOnDist,
+ expireAfter = expireAfter,
+ startAfter = startAfter,
+ endOnFocusDowned = failOnFocusDowned,
+ endOnFocusDutyNot = failOnFocusDutyNot,
+ endOnFocusDestroyed = true,
+ endOnFocusDeath = true
+ };
+ return custom;
+ }
+
+ public static Pawn_CustomDutyTracker.CustomPawnDuty AssaultPoint(IntVec3 dest, int switchAssaultRadius = 15, int expireAfter = 0, int startAfter = 0)
+ {
+ Pawn_CustomDutyTracker.CustomPawnDuty custom = new Pawn_CustomDutyTracker.CustomPawnDuty
+ {
+ duty = new PawnDuty(DutyDefOf.Defend, dest, switchAssaultRadius)
+ {
+ locomotion = LocomotionUrgency.Sprint
+ },
+ endOnDistToFocusLess = switchAssaultRadius,
+ expireAfter = expireAfter,
+ startAfter = startAfter,
+ };
+ return custom;
+ }
+
+ public static Pawn_CustomDutyTracker.CustomPawnDuty DefendPoint(IntVec3 dest, int radius, bool endOnTookDamage, int expireAfter, int startAfter = 0)
+ {
+ Pawn_CustomDutyTracker.CustomPawnDuty custom = new Pawn_CustomDutyTracker.CustomPawnDuty
+ {
+ duty = new PawnDuty(DutyDefOf.Defend, dest, radius)
+ {
+ locomotion = LocomotionUrgency.Sprint
+ },
+ expireAfter = expireAfter,
+ startAfter = startAfter,
+ endOnTookDamage = endOnTookDamage
+ };
+ return custom;
+ }
+ }
+}
diff --git a/Source/Rule56/CustomDuties/Pawn_CustomDutyTracker.CustomPawnDuty.cs b/Source/Rule56/CustomDuties/Pawn_CustomDutyTracker.CustomPawnDuty.cs
new file mode 100644
index 0000000..c7ed44c
--- /dev/null
+++ b/Source/Rule56/CustomDuties/Pawn_CustomDutyTracker.CustomPawnDuty.cs
@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+using RimWorld;
+using Verse;
+using Verse.AI;
+namespace CombatAI
+{
+ public partial class Pawn_CustomDutyTracker
+ {
+ public class CustomPawnDuty : IExposable
+ {
+ public bool finished;
+ public int startAfter;
+ public int startsAt = -1;
+ public bool canExitMap = true;
+ public bool canFlee = true;
+ public int expireAfter;
+ public int expiresAt = -1;
+ public int endOnDistToFocusLess;
+ public int endOnDistToFocusLarger;
+ public bool endOnFocusDeath;
+ public bool endOnFocusDestroyed;
+ public bool endOnFocusDowned;
+ public bool endOnTookDamage;
+ public PawnDuty duty;
+ public DutyDef endOnFocusDutyNot;
+
+ public void ExposeData()
+ {
+ Scribe_Deep.Look(ref duty, "duty");
+ Scribe_Values.Look(ref finished, "finished");
+ Scribe_Values.Look(ref expireAfter, "expireAfter");
+ Scribe_Values.Look(ref startAfter, "startAfter");
+ Scribe_Values.Look(ref startsAt, "startsAt", -1);
+ Scribe_Values.Look(ref expiresAt, "expiresAt", -1);
+ Scribe_Values.Look(ref endOnDistToFocusLarger, "failOnDistanceToFocus");
+ Scribe_Values.Look(ref endOnDistToFocusLess, "endOnDistanceToFocus");
+ Scribe_Values.Look(ref endOnFocusDeath, "failOnFocusDeath");
+ Scribe_Values.Look(ref endOnFocusDowned, "failOnFocusDowned");
+ Scribe_Values.Look(ref endOnFocusDestroyed, "failOnFocusDestroyed");
+ Scribe_Values.Look(ref canFlee, "canFlee", true);
+ Scribe_Values.Look(ref endOnTookDamage, "endOnTookDamage", false);
+ Scribe_Values.Look(ref canExitMap, "canExitMap", true);
+ Scribe_Defs.Look(ref endOnFocusDutyNot, "failOnFocusDutyNot");
+ }
+ }
+ }
+}
diff --git a/Source/Rule56/Pawn_CustomDutyTracker.cs b/Source/Rule56/CustomDuties/Pawn_CustomDutyTracker.cs
similarity index 68%
rename from Source/Rule56/Pawn_CustomDutyTracker.cs
rename to Source/Rule56/CustomDuties/Pawn_CustomDutyTracker.cs
index 20f2dd2..ba3e524 100644
--- a/Source/Rule56/Pawn_CustomDutyTracker.cs
+++ b/Source/Rule56/CustomDuties/Pawn_CustomDutyTracker.cs
@@ -4,10 +4,9 @@
using Verse.AI;
namespace CombatAI
{
- public class Pawn_CustomDutyTracker : IExposable
+ public partial class Pawn_CustomDutyTracker : IExposable
{
- public CustomPawnDuty curCustomDuty;
-
+ public CustomPawnDuty curCustomDuty;
public Pawn pawn;
public List queue = new List();
@@ -50,20 +49,20 @@ public void TickRare()
curCustomDuty = null;
pawn.mindState.duty = null;
}
- else if (curCustomDuty.failOnDistanceToFocus > 0 && curCustomDuty.duty.focus.Cell.IsValid && curCustomDuty.duty.focus.Cell.DistanceToSquared(pawn.Position) > Maths.Sqr(curCustomDuty.failOnDistanceToFocus))
+ else if (curCustomDuty.endOnDistToFocusLarger > 0 && curCustomDuty.duty.focus.Cell.IsValid && curCustomDuty.duty.focus.Cell.DistanceToSquared(pawn.Position) > Maths.Sqr(curCustomDuty.endOnDistToFocusLarger))
{
curCustomDuty = null;
pawn.mindState.duty = null;
}
- else if (curCustomDuty.endOnDistanceToFocus > 0 && curCustomDuty.duty.focus.Cell.IsValid && curCustomDuty.duty.focus.Cell.DistanceToSquared(pawn.Position) < Maths.Sqr(curCustomDuty.endOnDistanceToFocus))
+ else if (curCustomDuty.endOnDistToFocusLess > 0 && curCustomDuty.duty.focus.Cell.IsValid && curCustomDuty.duty.focus.Cell.DistanceToSquared(pawn.Position) < Maths.Sqr(curCustomDuty.endOnDistToFocusLess))
{
curCustomDuty = null;
pawn.mindState.duty = null;
}
- else if (curCustomDuty?.duty.focus.Thing != null)
+ else if (curCustomDuty.duty.focus.Thing != null)
{
Thing focus = curCustomDuty.duty.focus.Thing;
- if (curCustomDuty.failOnFocusDestroyed && (focus.Destroyed || !focus.Spawned))
+ if (curCustomDuty.endOnFocusDestroyed && (focus.Destroyed || !focus.Spawned))
{
curCustomDuty = null;
pawn.mindState.duty = null;
@@ -74,7 +73,7 @@ public void TickRare()
curCustomDuty = null;
pawn.mindState.duty = null;
}
- else if (curCustomDuty.failOnFocusDeath || curCustomDuty.failOnFocusDowned)
+ else if (curCustomDuty.endOnFocusDeath || curCustomDuty.endOnFocusDowned)
{
Pawn fpawn = focus as Pawn;
if (fpawn == null)
@@ -82,17 +81,17 @@ public void TickRare()
curCustomDuty = null;
pawn.mindState.duty = null;
}
- else if ((curCustomDuty.failOnFocusDowned || curCustomDuty.failOnFocusDeath) && fpawn.Dead)
+ else if ((curCustomDuty.endOnFocusDowned || curCustomDuty.endOnFocusDeath) && fpawn.Dead)
{
curCustomDuty = null;
pawn.mindState.duty = null;
}
- else if (curCustomDuty.failOnFocusDowned && fpawn.Downed)
+ else if (curCustomDuty.endOnFocusDowned && fpawn.Downed)
{
curCustomDuty = null;
pawn.mindState.duty = null;
}
- else if (curCustomDuty.failOnFocusDutyNot != null && fpawn.mindState?.duty?.def != curCustomDuty.failOnFocusDutyNot)
+ else if (curCustomDuty.endOnFocusDutyNot != null && fpawn.mindState?.duty?.def != curCustomDuty.endOnFocusDutyNot)
{
curCustomDuty = null;
pawn.mindState.duty = null;
@@ -217,40 +216,11 @@ private bool IsForcedDuty(DutyDef def)
return def != null && (IsExitDuty(def) || def == DutyDefOf.PrisonerEscape || def == DutyDefOf.PrisonerEscapeSapper || def == DutyDefOf.PrisonerAssaultColony || def == DutyDefOf.Kidnap || def == DutyDefOf.Steal);
}
- public class CustomPawnDuty : IExposable
+ public void Notify_TookDamage()
{
- public bool canExitMap = true;
- public bool canFlee = true;
- public IntVec3 dest = IntVec3.Invalid;
- public PawnDuty duty;
- public int endOnDistanceToFocus;
- public int expireAfter;
- public int expiresAt = -1;
- public int failOnDistanceToFocus;
- public bool failOnFocusDeath;
- public bool failOnFocusDestroyed;
- public bool failOnFocusDowned;
- public DutyDef failOnFocusDutyNot;
- public bool finished;
- public int startAfter;
- public int startsAt = -1;
-
- public void ExposeData()
+ if (curCustomDuty is { endOnTookDamage: true })
{
- Scribe_Deep.Look(ref duty, "duty");
- Scribe_Values.Look(ref expireAfter, "expireAfter");
- Scribe_Values.Look(ref startAfter, "startAfter");
- Scribe_Values.Look(ref startsAt, "startsAt", -1);
- Scribe_Values.Look(ref expiresAt, "expiresAt", -1);
- Scribe_Values.Look(ref dest, "endNear", IntVec3.Invalid);
- Scribe_Values.Look(ref failOnDistanceToFocus, "failOnDistanceToFocus");
- Scribe_Values.Look(ref endOnDistanceToFocus, "endOnDistanceToFocus");
- Scribe_Values.Look(ref failOnFocusDeath, "failOnFocusDeath");
- Scribe_Values.Look(ref failOnFocusDowned, "failOnFocusDowned");
- Scribe_Values.Look(ref failOnFocusDestroyed, "failOnFocusDestroyed");
- Scribe_Values.Look(ref canFlee, "canFlee", true);
- Scribe_Values.Look(ref canExitMap, "canExitMap", true);
- Scribe_Defs.Look(ref failOnFocusDutyNot, "failOnFocusDutyNot");
+ curCustomDuty = null;
}
}
}
diff --git a/Source/Rule56/CustomDutyUtility.cs b/Source/Rule56/CustomDutyUtility.cs
deleted file mode 100644
index 9bd8a58..0000000
--- a/Source/Rule56/CustomDutyUtility.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-using CombatAI.Comps;
-using RimWorld;
-using Verse;
-using Verse.AI;
-namespace CombatAI
-{
- public static class CustomDutyUtility
- {
- public static Pawn_CustomDutyTracker.CustomPawnDuty Escort(Pawn escorter, Pawn escortee, int radius = -1, int failOnDist = 0, int expireAfter = 0, int startAfter = 0, bool failOnFocusDowned = true, DutyDef failOnFocusDutyNot = null)
- {
- if (!escorter.CanReach(escortee, PathEndMode.InteractionCell, Danger.Unspecified))
- {
- return null;
- }
- ThingComp_CombatAI compee = escortee.GetComp_Fast();
- if (compee == null)
- {
- return null;
- }
- Pawn_CustomDutyTracker tracker = compee.duties;
- if (tracker == null)
- {
- return null;
- }
- Pawn_CustomDutyTracker.CustomPawnDuty custom = new Pawn_CustomDutyTracker.CustomPawnDuty();
- custom.duty = new PawnDuty(DutyDefOf.Escort, escortee, radius);
- custom.duty.locomotion = LocomotionUrgency.Sprint;
- custom.failOnDistanceToFocus = failOnDist;
- custom.expireAfter = expireAfter;
- custom.startAfter = startAfter;
- custom.failOnFocusDowned = failOnFocusDowned;
- custom.failOnFocusDutyNot = failOnFocusDutyNot;
- custom.failOnFocusDestroyed = true;
- custom.failOnFocusDeath = true;
- return custom;
- }
-
- public static Pawn_CustomDutyTracker.CustomPawnDuty AssaultPoint(Pawn pawn, IntVec3 dest, int switchAssaultRadius = 15, int expireAfter = 0, int startAfter = 0)
- {
- //if (!pawn.CanReach(dest, PathEndMode.InteractionCell, Danger.Unspecified, true, true, TraverseMode.PassAllDestroyableThingsNotWater))
- //{
- // return null;
- //}
- ThingComp_CombatAI comp = pawn.GetComp_Fast();
- if (comp == null)
- {
- return null;
- }
- Pawn_CustomDutyTracker tracker = comp.duties;
- if (tracker == null)
- {
- return null;
- }
- Pawn_CustomDutyTracker.CustomPawnDuty custom = new Pawn_CustomDutyTracker.CustomPawnDuty();
- custom.duty = new PawnDuty(DutyDefOf.Defend, dest, switchAssaultRadius);
- custom.duty.locomotion = LocomotionUrgency.Sprint;
- custom.dest = dest;
- custom.endOnDistanceToFocus = switchAssaultRadius;
- custom.expireAfter = expireAfter;
- custom.startAfter = startAfter;
- custom.failOnFocusDestroyed = false;
- custom.failOnFocusDeath = false;
- return custom;
- }
- }
-}
diff --git a/Source/Rule56/IBuckets.cs b/Source/Rule56/IBuckets.cs
index e81fa97..a221886 100644
--- a/Source/Rule56/IBuckets.cs
+++ b/Source/Rule56/IBuckets.cs
@@ -3,12 +3,9 @@ namespace CombatAI
{
public class IBuckets where T : IBucketable
{
-
private readonly Dictionary bucketIndexByIds = new Dictionary();
-
- private readonly List[] buckets;
-
- public readonly int numBuckets;
+ private readonly List[] buckets;
+ public readonly int numBuckets;
public IBuckets(int numBuckets)
{
diff --git a/Source/Rule56/ITSignalGrid.cs b/Source/Rule56/ITSignalGrid.cs
index 9f55659..321a4c0 100644
--- a/Source/Rule56/ITSignalGrid.cs
+++ b/Source/Rule56/ITSignalGrid.cs
@@ -22,6 +22,7 @@ public class ITSignalGrid
private readonly IField[] cells_meta;
private readonly IField[] cells_sharp;
private readonly IField[] cells_strength;
+ private readonly IField[] cells_aiming;
private readonly CellIndices indices;
@@ -29,6 +30,7 @@ public class ITSignalGrid
private float curBlunt;
private MetaCombatAttribute curMeta;
private float curSharp;
+ private byte curAimAvailablity;
private short r_sig = 19;
@@ -45,6 +47,7 @@ public ITSignalGrid(Map map)
cells_blunt = new IField[NumGridCells];
cells_sharp = new IField[NumGridCells];
cells_meta = new IField[NumGridCells];
+ cells_aiming = new IField[NumGridCells];
}
public short CycleNum
@@ -73,6 +76,8 @@ public void Set(int index, float signalStrength, Vector2 dir)
cells_meta[index].value |= curMeta;
cells_sharp[index].value = Maths.Max(curSharp, cells_sharp[index].value);
cells_blunt[index].value = Maths.Max(curBlunt, cells_blunt[index].value);
+ cells_aiming[index].value += curAimAvailablity;
+// cells_aiming[index].value
}
else
{
@@ -92,6 +97,7 @@ public void Set(int index, float signalStrength, Vector2 dir)
cells_meta[index].ReSet(curMeta, expired);
cells_sharp[index].ReSet(curSharp, expired);
cells_blunt[index].ReSet(curBlunt, expired);
+ cells_aiming[index].ReSet(curAimAvailablity, expired);
info.cycle = CycleNum;
}
info.sig = r_sig;
@@ -120,6 +126,7 @@ public void Set(int index, float signalStrength, Vector2 dir, MetaCombatAttribut
cells_meta[index].value |= metaAttributes;
cells_sharp[index].value = Maths.Max(curSharp, cells_sharp[index].value);
cells_blunt[index].value = Maths.Max(curBlunt, cells_blunt[index].value);
+ cells_aiming[index].value += curAimAvailablity;
}
else
{
@@ -139,6 +146,7 @@ public void Set(int index, float signalStrength, Vector2 dir, MetaCombatAttribut
cells_meta[index].ReSet(metaAttributes, expired);
cells_sharp[index].ReSet(curSharp, expired);
cells_blunt[index].ReSet(curBlunt, expired);
+ cells_aiming[index].ReSet(curAimAvailablity, expired);
info.cycle = CycleNum;
}
info.sig = r_sig;
@@ -161,9 +169,10 @@ public void Set(int index, MetaCombatAttribute metaAttributes)
int dc = CycleNum - info.cycle;
if (dc == 0)
{
- cells_meta[index].value |= metaAttributes;
- cells_sharp[index].value = Maths.Max(curSharp, cells_sharp[index].value);
- cells_blunt[index].value = Maths.Max(curBlunt, cells_blunt[index].value);
+ cells_meta[index].value |= metaAttributes;
+ cells_sharp[index].value = Maths.Max(curSharp, cells_sharp[index].value);
+ cells_blunt[index].value = Maths.Max(curBlunt, cells_blunt[index].value);
+ cells_aiming[index].value += curAimAvailablity;
}
else
{
@@ -183,6 +192,7 @@ public void Set(int index, MetaCombatAttribute metaAttributes)
cells_meta[index].ReSet(metaAttributes, expired);
cells_sharp[index].ReSet(curSharp, expired);
cells_blunt[index].ReSet(curBlunt, expired);
+ cells_aiming[index].ReSet(curAimAvailablity, expired);
info.cycle = CycleNum;
}
info.sig = r_sig;
@@ -205,9 +215,10 @@ public void Set(int index, ulong flags)
int dc = CycleNum - info.cycle;
if (dc == 0)
{
- cells_flags[index].value |= flags;
- cells_sharp[index].value = Maths.Max(curSharp, cells_sharp[index].value);
- cells_blunt[index].value = Maths.Max(curBlunt, cells_blunt[index].value);
+ cells_flags[index].value |= flags;
+ cells_sharp[index].value = Maths.Max(curSharp, cells_sharp[index].value);
+ cells_blunt[index].value = Maths.Max(curBlunt, cells_blunt[index].value);
+ cells_aiming[index].value += curAimAvailablity;
}
else
{
@@ -227,6 +238,7 @@ public void Set(int index, ulong flags)
cells_meta[index].ReSet(curMeta, expired);
cells_sharp[index].ReSet(curSharp, expired);
cells_blunt[index].ReSet(curBlunt, expired);
+ cells_aiming[index].ReSet(curAimAvailablity, expired);
info.cycle = CycleNum;
}
info.sig = r_sig;
@@ -256,6 +268,7 @@ public void Set(int index, float signalStrength, Vector2 dir, ulong flags)
cells_meta[index].value |= curMeta;
cells_sharp[index].value = Maths.Max(curSharp, cells_sharp[index].value);
cells_blunt[index].value = Maths.Max(curBlunt, cells_blunt[index].value);
+ cells_aiming[index].value += curAimAvailablity;
}
else
{
@@ -275,6 +288,7 @@ public void Set(int index, float signalStrength, Vector2 dir, ulong flags)
cells_meta[index].ReSet(curMeta, expired);
cells_sharp[index].ReSet(curSharp, expired);
cells_blunt[index].ReSet(curBlunt, expired);
+ cells_aiming[index].ReSet(curAimAvailablity, expired);
info.cycle = CycleNum;
}
info.sig = r_sig;
@@ -466,6 +480,28 @@ public float GetBlunt(int index)
return 0;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public int GetAvailability(IntVec3 cell)
+ {
+ return GetAvailability(indices.CellToIndex(cell));
+ }
+ public int GetAvailability(int index)
+ {
+ if (index >= 0 && index < NumGridCells)
+ {
+ IFieldInfo cell = cells[index];
+ switch (CycleNum - cell.cycle)
+ {
+ case 0:
+ IField availability = cells_aiming[index];
+ return Maths.Max(availability.value, availability.valuePrev);
+ case 1:
+ return cells_aiming[index].value;
+ }
+ }
+ return 0;
+ }
+
public Vector2 GetSignalDirectionAt(IntVec3 cell)
{
return GetSignalDirectionAt(indices.CellToIndex(cell));
@@ -505,6 +541,14 @@ public void Next(float sharp, float blunt, MetaCombatAttribute meta)
curSharp = sharp;
curBlunt = blunt;
curMeta = meta;
+ if ((meta & MetaCombatAttribute.Free) != 0)
+ {
+ curAimAvailablity = 1;
+ }
+ else
+ {
+ curAimAvailablity = 0;
+ }
}
///
diff --git a/Source/Rule56/MetaCombatAttribute.cs b/Source/Rule56/MetaCombatAttribute.cs
index 73c2cf4..f1ccd71 100644
--- a/Source/Rule56/MetaCombatAttribute.cs
+++ b/Source/Rule56/MetaCombatAttribute.cs
@@ -11,6 +11,8 @@ public enum MetaCombatAttribute
Fire = 32,
Gas = 64,
Explosives = 128,
- Mortar = 256
+ Mortar = 256,
+ Free = 512,
+ Occupied = 1024,
}
}
diff --git a/Source/Rule56/Patches/LordToil_AssaultColony_Patch.cs b/Source/Rule56/Patches/LordToil_AssaultColony_Patch.cs
index 0364cb2..c68ba80 100644
--- a/Source/Rule56/Patches/LordToil_AssaultColony_Patch.cs
+++ b/Source/Rule56/Patches/LordToil_AssaultColony_Patch.cs
@@ -64,11 +64,16 @@ public static void Postfix(LordToil_AssaultColony __instance)
things.AddRange(map.listerThings.ThingsInGroup(ThingRequestGroup.Bed).Where(b => b is Building_Bed bed && bed.CompAssignableToPawn.AssignedPawns.Any(p => p.Faction == map.ParentFaction)));
things.AddRange(map.listerThings.ThingsInGroup(ThingRequestGroup.ResearchBench).Where(t => t.Faction == map.ParentFaction));
things.AddRange(map.listerThings.ThingsInGroup(ThingRequestGroup.FoodDispenser).Where(t => t.Faction == map.ParentFaction));
- things.AddRange(map.mapPawns.PrisonersOfColony);
+ things.AddRange(map.mapPawns.PrisonersOfColonySpawned);
if (ModsConfig.BiotechActive)
{
+ things.AddRange(map.listerThings.ThingsInGroup(ThingRequestGroup.MechCharger).Where(t => t.Faction == map.ParentFaction));
things.AddRange(map.listerThings.ThingsInGroup(ThingRequestGroup.GenepackHolder));
}
+ if (ModsConfig.IdeologyActive)
+ {
+ things.AddRange(map.mapPawns.SlavesOfColonySpawned);
+ }
if (ModsConfig.RoyaltyActive)
{
things.AddRange(map.listerThings.ThingsInGroup(ThingRequestGroup.Throne));
@@ -102,11 +107,22 @@ public static void Postfix(LordToil_AssaultColony __instance)
ThingComp_CombatAI comp = force[j].GetComp_Fast();
if (comp != null && !comp.duties.Any(DutyDefOf.Defend))
{
- Pawn_CustomDutyTracker.CustomPawnDuty customDuty = CustomDutyUtility.AssaultPoint(force[j], zone.Position, Rand.Range(7, 15), 3600 * Rand.Range(3, 8));
- comp.duties.StartDuty(customDuty);
- if (Finder.Settings.Debug)
+ Pawn_CustomDutyTracker.CustomPawnDuty customDuty = CustomDutyUtility.AssaultPoint(zone.Position, Rand.Range(7, 15), 3600 * Rand.Range(3, 8));
+ if(force[j].TryStartCustomDuty(customDuty))
{
- Log.Message($"{comp.parent} task force {i} attacking {zone}");
+ if (Finder.Settings.Debug)
+ {
+ Log.Message($"{comp.parent} task force {i} attacking {zone}");
+ }
+ Pawn_CustomDutyTracker.CustomPawnDuty customDuty2 = CustomDutyUtility.DefendPoint(zone.Position, (int)Rand.Range(30, 60), true, 3600 + Rand.Range(0, 3600));
+ if (Rand.Chance(0.33f))
+ {
+ force[j].EnqueueFirstCustomDuty(customDuty);
+ if (Finder.Settings.Debug)
+ {
+ Log.Message($"{comp.parent} task force {i} occupying area around {zone}");
+ }
+ }
}
}
}
@@ -121,11 +137,22 @@ public static void Postfix(LordToil_AssaultColony __instance)
ThingComp_CombatAI comp = force[j].GetComp_Fast();
if (comp != null && !comp.duties.Any(DutyDefOf.Defend))
{
- Pawn_CustomDutyTracker.CustomPawnDuty customDuty = CustomDutyUtility.AssaultPoint(force[j], thing.Position, Rand.Range(7, 15), 3600 * Rand.Range(3, 8));
- comp.duties.StartDuty(customDuty);
- if (Finder.Settings.Debug)
+ Pawn_CustomDutyTracker.CustomPawnDuty customDuty = CustomDutyUtility.AssaultPoint(thing.Position, Rand.Range(7, 15), 3600 * Rand.Range(3, 8));
+ if (force[j].TryStartCustomDuty(customDuty))
{
- Log.Message($"{comp.parent} task force {i} attacking {thing}");
+ if (Finder.Settings.Debug)
+ {
+ Log.Message($"{comp.parent} task force {i} attacking {thing}");
+ }
+ Pawn_CustomDutyTracker.CustomPawnDuty customDuty2 = CustomDutyUtility.DefendPoint(thing.Position, (int)Rand.Range(30, 60), true, 3600 + Rand.Range(0, 3600));
+ if (Rand.Chance(0.33f))
+ {
+ force[j].EnqueueFirstCustomDuty(customDuty);
+ if (Finder.Settings.Debug)
+ {
+ Log.Message($"{comp.parent} task force {i} occupying area around {thing}");
+ }
+ }
}
}
}
diff --git a/Source/Rule56/Patches/Trigger_FractionColonyDamageTaken_Patch.cs b/Source/Rule56/Patches/Trigger_FractionColonyDamageTaken_Patch.cs
index 2539c3c..12f9a3c 100644
--- a/Source/Rule56/Patches/Trigger_FractionColonyDamageTaken_Patch.cs
+++ b/Source/Rule56/Patches/Trigger_FractionColonyDamageTaken_Patch.cs
@@ -1,4 +1,5 @@
-using HarmonyLib;
+using System.Data.SqlTypes;
+using HarmonyLib;
using RimWorld;
using Verse;
namespace CombatAI.Patches
@@ -10,8 +11,20 @@ private static class Trigger_FractionColonyDamageTaken_Constructor
{
public static void Prefix(ref float desiredColonyDamageFraction, ref float minDamage)
{
- minDamage *= 10f;
- desiredColonyDamageFraction = Maths.Max(Rand.Range(0.25f, 0.80f), desiredColonyDamageFraction);
+ minDamage *= 15f;
+ desiredColonyDamageFraction = Maths.Max(Rand.Range(0.25f, 5.0f), desiredColonyDamageFraction);
+ }
+ }
+
+ [HarmonyPatch(typeof(Trigger_FractionColonyDamageTaken), nameof(Trigger_FractionColonyDamageTaken.ActivateOn))]
+ private static class Trigger_FractionColonyDamageTaken_ActivateOn
+ {
+ public static void Postfix(ref bool __result)
+ {
+ if (__result && !Rand.Chance(0.0001f))
+ {
+ __result = false;
+ }
}
}
}
diff --git a/Source/Rule56/Settings.cs b/Source/Rule56/Settings.cs
index 5499273..d451240 100644
--- a/Source/Rule56/Settings.cs
+++ b/Source/Rule56/Settings.cs
@@ -125,13 +125,13 @@ public override void ExposeData()
Scribe_Values.Look(ref Debug, $"Debug.{version}");
Scribe_Values.Look(ref Debug_ValidateSight, $"Debug_ValidateSight.{version}");
Scribe_Values.Look(ref Debug_DrawShadowCasts, $"Debug_DrawShadowCasts.{version}");
- Scribe_Values.Look(ref Enable_Sprinting, "Enable_Sprinting", true);
- Scribe_Values.Look(ref Enable_Groups, "Enable_Groups", true);
- Scribe_Values.Look(ref FogOfWar_Turrets, "FogOfWar_Turrets", true);
- Scribe_Values.Look(ref FogOfWar_Animals, "FogOfWar_Animals", true);
- Scribe_Values.Look(ref FogOfWar_AnimalsSmartOnly, "FogOfWar_AnimalsSmartOnly", true);
- Scribe_Values.Look(ref FogOfWar_Allies, "FogOfWar_Allies", true);
- Scribe_Values.Look(ref Pathfinding_SappingMul, "Pathfinding_SappingMul", 1.0f);
+ Scribe_Values.Look(ref Enable_Sprinting, $"Enable_Sprinting.{version}", true);
+ Scribe_Values.Look(ref Enable_Groups, $"Enable_Groups.{version}", true);
+ Scribe_Values.Look(ref FogOfWar_Turrets, $"FogOfWar_Turrets.{version}", true);
+ Scribe_Values.Look(ref FogOfWar_Animals, $"FogOfWar_Animals.{version}", true);
+ Scribe_Values.Look(ref FogOfWar_AnimalsSmartOnly, $"FogOfWar_AnimalsSmartOnly.{version}", true);
+ Scribe_Values.Look(ref FogOfWar_Allies, $"FogOfWar_Allies.{version}", true);
+ Scribe_Values.Look(ref Pathfinding_SappingMul, $"Pathfinding_SappingMul2.{version}", 1.0f);
//ScribeValues(); // Scribe values. (Will not scribe IExposables nor enums)
}
diff --git a/Source/Rule56/SightGrid.cs b/Source/Rule56/SightGrid.cs
index 0ce302a..692aa22 100644
--- a/Source/Rule56/SightGrid.cs
+++ b/Source/Rule56/SightGrid.cs
@@ -365,7 +365,23 @@ private bool TryCastSight(IBucketableThing item)
ops += 1;
suCentroid += pos;
}
- ISightRadius sightRadius = item.cachedSightRadius;
+ MetaCombatAttribute availability = 0;
+ if (item.thing != null)
+ {
+ Verb verb = item.thing.TryGetAttackVerb();
+ if (!verb.IsMeleeAttack)
+ {
+ if (verb.state != VerbState.Idle || verb.WarmingUp)
+ {
+ availability = MetaCombatAttribute.Occupied;
+ }
+ else
+ {
+ availability = MetaCombatAttribute.Free;
+ }
+ }
+ }
+ ISightRadius sightRadius = item.cachedSightRadius;
Action action = () =>
{
if (playerAlliance && sightRadius.fog > 0)
@@ -377,8 +393,8 @@ private bool TryCastSight(IBucketableThing item)
gridFog.Set(item.path[i], 1.0f);
}
}
- grid.Next(item.cachedDamage.adjustedSharp, item.cachedDamage.adjustedBlunt, item.cachedDamage.attributes);
- grid_regions.Next(GetFlags(item), item.cachedDamage.adjustedSharp, item.cachedDamage.adjustedBlunt, item.cachedDamage.attributes);
+ grid.Next(item.cachedDamage.adjustedSharp, item.cachedDamage.adjustedBlunt, item.cachedDamage.attributes | availability);
+ grid_regions.Next(GetFlags(item), item.cachedDamage.adjustedSharp, item.cachedDamage.adjustedBlunt, item.cachedDamage.attributes | availability);
float r_fade = sightRadius.fog * Finder.Settings.FogOfWar_RangeFadeMultiplier;
float d_fade = sightRadius.fog - r_fade;
float rSqr_sight = Maths.Sqr(sightRadius.sight);
diff --git a/Source/Rule56/SightTracker.cs b/Source/Rule56/SightTracker.cs
index bb23238..f5c4300 100644
--- a/Source/Rule56/SightTracker.cs
+++ b/Source/Rule56/SightTracker.cs
@@ -107,7 +107,7 @@ public override void MapComponentTick()
float value = reader.GetThreat(cell);
if (value > 0)
{
- map.debugDrawer.FlashCell(cell, Mathf.Clamp01(value / 4f), $"{Math.Round(value, 2)}", 15);
+ map.debugDrawer.FlashCell(cell, Mathf.Clamp01(value / 20f), $"{Math.Round(value, 2)}", 15);
}
//var value = reader.hostiles[0].GetSharp(cell) + reader.hostiles[0].GetBlunt(cell);
//if (value > 0)
@@ -564,19 +564,25 @@ public float GetThreat(IntVec3 cell)
}
public float GetThreat(int index)
{
- if (armor.weaknessAttributes != MetaCombatAttribute.None)
+ MetaCombatAttribute attributes = GetMetaAttributes(index);
+ float val;
+ if ((attributes & armor.weaknessAttributes) != MetaCombatAttribute.None)
{
- MetaCombatAttribute attributes = GetMetaAttributes(index);
- if ((attributes & armor.weaknessAttributes) != MetaCombatAttribute.None)
- {
- return 2.0f;
- }
+ val = 2.0f;
}
- if (!Mod_CE.active)
+ else
{
- return armor.createdAt != 0 ? Mathf.Clamp01(2f * Maths.Max(GetBlunt(index) / (armor.Blunt + 0.001f), GetSharp(index) / (armor.Sharp + 0.001f), 0f)) : 0f;
+ if (!Mod_CE.active)
+ {
+ val = armor.createdAt != 0 ? Mathf.Clamp01(2f * Maths.Max(GetBlunt(index) / (armor.Blunt + 0.001f), GetSharp(index) / (armor.Sharp + 0.001f), 0f)) : 0f;
+ }
+ else
+ {
+ val = armor.createdAt != 0 ? Mathf.Clamp01(Maths.Max(GetBlunt(index) / (armor.Blunt + 0.001f), GetSharp(index) / (armor.Sharp + 0.001f), 0f)) : 0f;
+ }
}
- return armor.createdAt != 0 ? Mathf.Clamp01(Maths.Max(GetBlunt(index) / (armor.Blunt + 0.001f), GetSharp(index) / (armor.Sharp + 0.001f), 0f)) : 0f;
+ val = Maths.Max((float)GetEnemyAvailability(index) * val, val);
+ return val;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float GetRegionThreat(Region region)
@@ -617,6 +623,33 @@ public float GetBlunt(int index)
}
return value;
}
+
+ public int GetEnemyAvailability(IntVec3 cell)
+ {
+ return GetEnemyAvailability(indices.CellToIndex(cell));
+ }
+ public int GetEnemyAvailability(int index)
+ {
+ int value = 0;
+ for (int i = 0; i < hostiles.Length; i++)
+ {
+ value += hostiles[i].GetAvailability(index);
+ }
+ return value;
+ }
+ public int GetFriendlyAvailability(IntVec3 cell)
+ {
+ return GetFriendlyAvailability(indices.CellToIndex(cell));
+ }
+ public int GetFriendlyAvailability(int index)
+ {
+ int value = 0;
+ for (int i = 0; i < friendlies.Length; i++)
+ {
+ value += friendlies[i].GetAvailability(index);
+ }
+ return value;
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float GetSharp(IntVec3 cell)
{
diff --git a/Source/Rule56/SuppliesUtility.cs b/Source/Rule56/SuppliesUtility.cs
new file mode 100644
index 0000000..a8dbd55
--- /dev/null
+++ b/Source/Rule56/SuppliesUtility.cs
@@ -0,0 +1,91 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using RimWorld;
+using Verse;
+namespace CombatAI
+{
+ public class SuppliesUtility
+ {
+ private readonly static HashSet temp = new HashSet();
+
+ public static void DropSupplies(Map map, IntVec3 position, ThingDef thingDef, int count)
+ {
+ List list = new List();
+ Thing thing = ThingMaker.MakeThing(thingDef);
+ thing.stackCount = count;
+ list.Add(thing);
+ DropPodUtility.DropThingsNear(position, map, list);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static IEnumerable PotentialFoodFor(Pawn pawn)
+ {
+ return PotentialFoodFor(pawn.RaceProps);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static IEnumerable PotentialFoodFor(RaceProperties race)
+ {
+ if (!race.EatsFood)
+ {
+ yield break;
+ }
+ // TODO add more food types.
+ yield return ThingDefOf.MealSurvivalPack;
+ }
+
+ public static void FulfillFoodSupplies(List pawns, Map map)
+ {
+ if (pawns.Count == 0)
+ {
+ return;
+ }
+ TechLevel tech = pawns.RandomElement().Faction?.def?.techLevel ?? TechLevel.Undefined;
+ if (tech == TechLevel.Animal || tech == TechLevel.Medieval || tech == TechLevel.Neolithic)
+ {
+ return;
+ }
+ temp.Clear();
+ temp.AddRange(pawns.SelectMany(PotentialFoodFor));
+ float mul = tech == TechLevel.Industrial ? Rand.Range(1.0f, 1.5f) : Rand.Range(1.5f, 2.5f);
+ IntVec3 center = IntVec3.Zero;
+ for (int i = 0; i < pawns.Count; i++)
+ {
+ center += pawns[i].Position;
+ }
+ center.x /= pawns.Count;
+ center.z /= pawns.Count;
+ IntVec3 dropPoint = center;
+ float minDistSqr = 1e6f;
+ for (int i = 0; i < pawns.Count; i++)
+ {
+ float distSqr = pawns[i].Position.DistanceToSquared(center);
+ if (distSqr < minDistSqr)
+ {
+ Region region = pawns[i].GetRegion();
+ if (region != null)
+ {
+ int k = 0;
+ IntVec3 cell = IntVec3.Invalid;
+ while (k++ < 16 && !(cell = region.RandomCell).Walkable(map))
+ {
+ }
+ if (cell.IsValid && cell.Walkable(map))
+ {
+ minDistSqr = distSqr;
+ dropPoint = region.RandomCell;
+ }
+ }
+ }
+ }
+ if (dropPoint.IsValid && dropPoint.Walkable(map))
+ {
+ foreach (ThingDef def in temp)
+ {
+ DropSupplies(map, dropPoint, def, (int) (pawns.Count() * mul));
+ }
+ }
+ }
+ }
+}
diff --git a/Source/Rule56/T4/Outputs/Keyed.generated.cs b/Source/Rule56/T4/Outputs/Keyed.generated.cs
index 4c3c742..715f22c 100644
--- a/Source/Rule56/T4/Outputs/Keyed.generated.cs
+++ b/Source/Rule56/T4/Outputs/Keyed.generated.cs
@@ -196,7 +196,7 @@ public static TaggedString CombatAI_Settings_Basic_Presets_Applied {
private static TaggedString _CombatAI_Settings_Basic_Presets_Description = null;
/// Keyed string. key=CombatAI.Settings.Basic.Presets.Description. inner text:
///
- /// Performance presets will determine the complexity of AI calculations\ and their interval. More complex calculations means harder AI but lower performance. Default is normal.
+ /// Performance presets will determine the complexity of AI calculations and their interval. More complex calculations means harder AI but lower performance. Default is normal.
///
public static TaggedString CombatAI_Settings_Basic_Presets_Description {
get => _CombatAI_Settings_Basic_Presets_Description != null ?
@@ -236,7 +236,7 @@ public static TaggedString CombatAI_Settings_Basic_Groups {
private static TaggedString _CombatAI_Settings_Basic_Groups_Description = null;
/// Keyed string. key=CombatAI.Settings.Basic.Groups.Description. inner text:
///
- /// Raiders will be divided into tactical groups (2-10) each with their own\ objective. Not all pawns will be assigned to groups, some will remain on the default assault duty.
+ /// Raiders will be divided into tactical groups (2-10) each with their own objective. Not all pawns will be assigned to groups, some will remain on the default assault duty.
///
public static TaggedString CombatAI_Settings_Basic_Groups_Description {
get => _CombatAI_Settings_Basic_Groups_Description != null ?
@@ -256,7 +256,7 @@ public static TaggedString CombatAI_Settings_Basic_SappingMul {
private static TaggedString _CombatAI_Settings_Basic_SappingMul_Description = null;
/// Keyed string. key=CombatAI.Settings.Basic.SappingMul.Description. inner text:
///
- /// Cost multiplier for pathing through walls. Higher values means\ raiders are less likely to path through walls.
+ /// Cost multiplier for pathing through walls. Higher values means raiders are less likely to path through walls.
///
public static TaggedString CombatAI_Settings_Basic_SappingMul_Description {
get => _CombatAI_Settings_Basic_SappingMul_Description != null ?
@@ -416,7 +416,7 @@ public static TaggedString CombatAI_Settings_Basic_PerformanceOpt {
private static TaggedString _CombatAI_Settings_Basic_PerformanceOpt_Warning = null;
/// Keyed string. key=CombatAI.Settings.Basic.PerformanceOpt.Warning. inner text:
///
- /// WARNING: NOT having dynamic performance settings ON will result in\ lag spikes and lose of performance!
+ /// WARNING: NOT having dynamic performance settings ON will result in lag spikes and lose of performance!
///
public static TaggedString CombatAI_Settings_Basic_PerformanceOpt_Warning {
get => _CombatAI_Settings_Basic_PerformanceOpt_Warning != null ?
@@ -426,7 +426,7 @@ public static TaggedString CombatAI_Settings_Basic_PerformanceOpt_Warning {
private static TaggedString _CombatAI_Settings_Basic_PerformanceOpt_Description = null;
/// Keyed string. key=CombatAI.Settings.Basic.PerformanceOpt.Description. inner text:
///
- /// Automatically adjust settings to maintain both a good level of\ TPS and a good AI.
+ /// Automatically adjust settings to maintain both a good level of TPS and a good AI.
///
public static TaggedString CombatAI_Settings_Basic_PerformanceOpt_Description {
get => _CombatAI_Settings_Basic_PerformanceOpt_Description != null ?
@@ -506,7 +506,7 @@ public static TaggedString CombatAI_Settings_Basic_DestWeight {
private static TaggedString _CombatAI_Settings_Basic_DestWeight_Description = null;
/// Keyed string. key=CombatAI.Settings.Basic.DestWeight.Description. inner text:
///
- /// Lower numbers mean pathfinding will be more aggressive at avoiding\ enemies, flanking and minimizing risk to pawns.
+ /// Lower numbers mean pathfinding will be more aggressive at avoiding enemies, flanking and minimizing risk to pawns.
///
public static TaggedString CombatAI_Settings_Basic_DestWeight_Description {
get => _CombatAI_Settings_Basic_DestWeight_Description != null ?
@@ -556,7 +556,7 @@ public static TaggedString CombatAI_Settings_Advance {
private static TaggedString _CombatAI_Settings_Advance_Warning = null;
/// Keyed string. key=CombatAI.Settings.Advance.Warning. inner text:
///
- /// WARNING: This is only for advanced users! Don't enable this if you don't know\ what you're doing!
+ /// WARNING: This is only for advanced users! Don't enable this if you don't know what you're doing!
///
public static TaggedString CombatAI_Settings_Advance_Warning {
get => _CombatAI_Settings_Advance_Warning != null ?
@@ -586,7 +586,7 @@ public static TaggedString CombatAI_Settings_Advance_Sight_Performance {
private static TaggedString _CombatAI_Settings_Advance_Sight_Performance_Description = null;
/// Keyed string. key=CombatAI.Settings.Advance.Sight.Performance.Description. inner text:
///
- /// You can adjust how many buckets pawns/turrets are divided\ into and how often they updates. Warning: DON'T USE THIS IF YOU DON'T KNOW WHAT YOU'RE DOING
+ /// You can adjust how many buckets pawns/turrets are divided into and how often they updates. Warning: DON'T USE THIS IF YOU DON'T KNOW WHAT YOU'RE DOING
///
public static TaggedString CombatAI_Settings_Advance_Sight_Performance_Description {
get => _CombatAI_Settings_Advance_Sight_Performance_Description != null ?
@@ -676,7 +676,7 @@ public static TaggedString CombatAI_Settings_Advance_Sight_Performance_Readouts_
private static TaggedString _CombatAI_Settings_Advance_Sight_Performance_Readouts_CarryLimit_Description = null;
/// Keyed string. key=CombatAI.Settings.Advance.Sight.Performance.Readouts.CarryLimit.Description. inner text:
///
- /// The maximum number of things along line\ of sight. This includes trees, buildings, etc. Higher values means more accurate sight model but higher\ performance impact.
+ /// The maximum number of things along line of sight. This includes trees, buildings, etc. Higher values means more accurate sight model but higher performance impact.
///
public static TaggedString CombatAI_Settings_Advance_Sight_Performance_Readouts_CarryLimit_Description {
get => _CombatAI_Settings_Advance_Sight_Performance_Readouts_CarryLimit_Description != null ?