Skip to content

Commit

Permalink
Merge pull request #20 from kbatbouta/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
kbatbouta authored Jan 31, 2023
2 parents 4030619 + ce9f942 commit b97f501
Show file tree
Hide file tree
Showing 14 changed files with 508 additions and 169 deletions.
Binary file modified 1.4/Assemblies/CombatAI.dll
Binary file not shown.
27 changes: 18 additions & 9 deletions Source/Rule56/CombatAI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@
<None Update="..\..\1.4\Defs\ThingDef_Buildings\Buildings_Security.xml">
<Link>Xml\Defs\ThingDef_Buildings\\Buildings_Security.xml</Link>
</None>
<None Update="..\..\1.4\Defs\Misc\Designation_categories.xml">
<Link>Xml\Defs\Misc\\Designation_categories.xml</Link>
</None>
<None Update="..\..\1.4\Defs\ThingDef_Research\Cai5000_Researchtab.xml">
<Link>Xml\Defs\ThingDef_Research\\Cai5000_Researchtab.xml</Link>
</None>
<None Update="..\..\1.4\Defs\ThingDef_Research\Cai5000_ResearchDefs.xml">
<Link>Xml\Defs\ThingDef_Research\\Cai5000_ResearchDefs.xml</Link>
</None>
</ItemGroup>
<!-- ................ -->
<!-- Packages -->
Expand All @@ -107,8 +116,8 @@
<PropertyGroup>
<TextTransform>$(PkgMono_TextTransform)\tools\TextTransform.exe</TextTransform>
</PropertyGroup>
<Message Text="Processing T4 files: @(TTFiles->'%(Identity)')" />
<Exec WorkingDirectory="$(ProjectDir)" Command="@(TTFiles->'pwd; mono $(TextTransform) --out=T4/Outputs/%(FileName).generated.cs T4/Sources/%(FileName).tt')" />
<Message Text="Processing T4 files: @(TTFiles-&gt;'%(Identity)')" />
<Exec WorkingDirectory="$(ProjectDir)" Command="@(TTFiles-&gt;'pwd; mono $(TextTransform) --out=T4/Outputs/%(FileName).generated.cs T4/Sources/%(FileName).tt')" />
</Target>
<!-- ................ -->
<!-- Publisize -->
Expand Down Expand Up @@ -154,12 +163,12 @@
<TransformOnBuild>false</TransformOnBuild>
</PropertyGroup>
<ProjectExtensions>
<MonoDevelop>
<Properties>
<Policies>
<StandardHeader Text="&#xA;${FileName}&#xA; &#xA;Author:&#xA; ${AuthorName} &lt;${AuthorEmail}&gt;&#xA;&#xA;Copyright (c) ${Year} ${CopyrightHolder}&#xA;&#xA;Permission is hereby granted, free of charge, to any person obtaining a copy&#xA;of this software and associated documentation files (the &quot;Software&quot;), to deal&#xA;in the Software without restriction, including without limitation the rights&#xA;to use, copy, modify, merge, publish, distribute, sublicense, and/or sell&#xA;copies of the Software, and to permit persons to whom the Software is&#xA;furnished to do so, subject to the following conditions:&#xA;&#xA;The above copyright notice and this permission notice shall be included in&#xA;all copies or substantial portions of the Software.&#xA;&#xA;THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR&#xA;IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,&#xA;FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE&#xA;AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER&#xA;LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,&#xA;OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN&#xA;THE SOFTWARE." IncludeInNewFiles="False" />
</Policies>
</Properties>
</MonoDevelop>
<MonoDevelop>
<Properties>
<Policies>
<StandardHeader Text="&#xA;${FileName}&#xA; &#xA;Author:&#xA; ${AuthorName} &lt;${AuthorEmail}&gt;&#xA;&#xA;Copyright (c) ${Year} ${CopyrightHolder}&#xA;&#xA;Permission is hereby granted, free of charge, to any person obtaining a copy&#xA;of this software and associated documentation files (the &quot;Software&quot;), to deal&#xA;in the Software without restriction, including without limitation the rights&#xA;to use, copy, modify, merge, publish, distribute, sublicense, and/or sell&#xA;copies of the Software, and to permit persons to whom the Software is&#xA;furnished to do so, subject to the following conditions:&#xA;&#xA;The above copyright notice and this permission notice shall be included in&#xA;all copies or substantial portions of the Software.&#xA;&#xA;THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR&#xA;IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,&#xA;FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE&#xA;AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER&#xA;LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,&#xA;OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN&#xA;THE SOFTWARE." IncludeInNewFiles="False" />
</Policies>
</Properties>
</MonoDevelop>
</ProjectExtensions>
</Project>
58 changes: 57 additions & 1 deletion Source/Rule56/CombatAI_Utility.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
using RimWorld;
using CombatAI.R;
using RimWorld;
using UnityEngine;
using Verse;
using Verse.AI;
using Verse.Noise;
using static CombatAI.AvoidanceTracker;
using static CombatAI.SightTracker;

Expand All @@ -22,6 +26,51 @@ public static bool IsDormant(this Thing thing)
return value;
}

public static IntVec3 TryGetNextDutyDest(this Pawn pawn, float maxDistFromPawn = -1)
{
if (pawn.mindState?.duty == null || !pawn.mindState.duty.focus.IsValid)
{
return IntVec3.Invalid;
}
DutyDestCache key = new DutyDestCache()
{
pawnId = pawn.thingIDNumber,
dutyDefId = pawn.mindState.duty.def.index,
dutyDest = pawn.mindState.duty.focus.Cell
};
if (!TKVCache<DutyDestCache, PawnDuty, IntVec3>.TryGet(key, out IntVec3 dutyDest, 600))
{
dutyDest = IntVec3.Invalid;
if (pawn.mindState.duty.focus.Cell.DistanceToSquared(pawn.Position) > Maths.Sqr(Maths.Max(pawn.mindState.duty.radius, 10)))
{
PawnPath path = pawn.Map.pathFinder.FindPath(pawn.Position, pawn.mindState.duty.focus.Cell, pawn);
if (path != null)
{
maxDistFromPawn = Mathf.Clamp(maxDistFromPawn, 5f, 64f);
int k = path.NodesLeftCount;
int i = 0;
float maxDistSqr = Maths.Sqr(maxDistFromPawn);
IntVec3 pawnPos = pawn.Position;
while (i < k && path.Peek(i).DistanceToSquared(pawnPos) < maxDistSqr)
{
i++;
}
if (i == k)
{
dutyDest = pawn.Position;
}
else
{
dutyDest = path.Peek(i);
}
path.ReleaseToPool();
}
}
TKVCache<DutyDestCache, PawnDuty, IntVec3>.Put(key, dutyDest);
}
return dutyDest;
}

public static Verb TryGetAttackVerb(this Thing thing)
{
if (thing is Pawn pawn)
Expand Down Expand Up @@ -78,5 +127,12 @@ public static int GetThingFlagsIndex(this Thing thing)
{
return thing.thingIDNumber % 64;
}

private struct DutyDestCache
{
public int pawnId;
public int dutyDefId;
public IntVec3 dutyDest;
}
}
}
72 changes: 40 additions & 32 deletions Source/Rule56/Comps/ThingComp_CombatAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ public override void PostExposeData()

private void TryStartSapperJob()
{
if (sightReader.GetVisibilityToEnemies(cellBefore) > 0)
if (sightReader.GetVisibilityToEnemies(cellBefore) > 0 || sapperNodes.Count == 0)
{
ReleaseEscorts();
cellBefore = IntVec3.Invalid;
Expand All @@ -686,46 +686,54 @@ private void TryStartSapperJob()
return;
}
Pawn pawn = parent as Pawn;
if(pawn.Destroyed || pawn.Downed || pawn.Dead || pawn.mindState?.duty == null || !(pawn.mindState.duty.def.Is(DutyDefOf.AssaultColony) || pawn.mindState.duty.def.Is(DutyDefOf.Defend) || pawn.mindState.duty.def.Is(DutyDefOf.AssaultThing) || pawn.mindState.duty.def.Is(DutyDefOf.Breaching)))
{
ReleaseEscorts();
return;
}
Map map = pawn.Map;
Thing blocker = sapperNodes[0].GetEdifice(map);
Job job = DigUtility.PassBlockerJob(pawn, blocker, cellBefore, true, true);
if (job != null)
if (blocker != null)
{
job.playerForced = true;
job.expiryInterval = 3600;
job.maxNumMeleeAttacks = 300;
pawn.jobs.StopAll();
pawn.jobs.StartJob(job, JobCondition.InterruptForced);
if (findEscorts)
Job job = DigUtility.PassBlockerJob(pawn, blocker, cellBefore, true, true);
if (job != null)
{
int count = escorts.Count;
int countTarget = Rand.Int % 6 + 4 + Maths.Min(sapperNodes.Count, 10);
Faction faction = pawn.Faction;
Predicate<Thing> validator = t =>
job.playerForced = true;
job.expiryInterval = 3600;
job.maxNumMeleeAttacks = 300;
pawn.jobs.StopAll();
pawn.jobs.StartJob(job, JobCondition.InterruptForced);
if (findEscorts)
{
if (count < countTarget && t.Faction == faction && t is Pawn ally && !ally.Destroyed
&& !ally.CurJobDef.Is(JobDefOf.Mine)
&& ally.mindState?.duty?.def != DutyDefOf.Escort
&& (sightReader == null || sightReader.GetAbsVisibilityToEnemies(ally.Position) == 0)
&& ally.skills?.GetSkill(SkillDefOf.Mining).Level < 10)
int count = escorts.Count;
int countTarget = Rand.Int % 6 + 4 + Maths.Min(sapperNodes.Count, 10);
Faction faction = pawn.Faction;
Predicate<Thing> validator = t =>
{
ThingComp_CombatAI comp = ally.GetComp_Fast<ThingComp_CombatAI>();
if (comp?.duties != null && comp.duties?.Any(DutyDefOf.Escort) == false && !comp.IsSapping && GenTicks.TicksGame - comp.releasedTick < 600)
if (count < countTarget && t.Faction == faction && t is Pawn ally && !ally.Destroyed
&& !ally.CurJobDef.Is(JobDefOf.Mine)
&& ally.mindState?.duty?.def != DutyDefOf.Escort
&& (sightReader == null || sightReader.GetAbsVisibilityToEnemies(ally.Position) == 0)
&& ally.skills?.GetSkill(SkillDefOf.Mining).Level < 10)
{
Pawn_CustomDutyTracker.CustomPawnDuty custom = CustomDutyUtility.Escort(ally, pawn, 20, 100, 500 * sapperNodes.Count + Rand.Int % 1000);
if (custom != null)
ThingComp_CombatAI comp = ally.GetComp_Fast<ThingComp_CombatAI>();
if (comp?.duties != null && comp.duties?.Any(DutyDefOf.Escort) == false && !comp.IsSapping && GenTicks.TicksGame - comp.releasedTick < 600)
{
custom.duty.locomotion = LocomotionUrgency.Sprint;
comp.duties.StartDuty(custom);
escorts.Add(ally);
Pawn_CustomDutyTracker.CustomPawnDuty custom = CustomDutyUtility.Escort(ally, pawn, 20, 100, 500 * sapperNodes.Count + Rand.Int % 1000);
if (custom != null)
{
custom.duty.locomotion = LocomotionUrgency.Sprint;
comp.duties.StartDuty(custom);
escorts.Add(ally);
}
count++;
}
count++;
}
return count == countTarget;
}
return false;
};
Verse.GenClosest.RegionwiseBFSWorker(pawn.Position, map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.InteractionCell, TraverseParms.For(pawn), validator, null, 1, 10, 40, out int _);
return count == countTarget;
}
return false;
};
Verse.GenClosest.RegionwiseBFSWorker(pawn.Position, map, ThingRequest.ForGroup(ThingRequestGroup.Pawn), PathEndMode.InteractionCell, TraverseParms.For(pawn), validator, null, 1, 10, 40, out int _);
}
}
}
}
Expand Down
Loading

0 comments on commit b97f501

Please sign in to comment.