Files
ArachnaeSwarm/Source/ArachnaeSwarm/WULA_MutiFuelSpawner/Utility.cs
2025-09-16 12:20:36 +08:00

303 lines
11 KiB
C#

using System.Collections.Generic;
using System.Linq;
using RimWorld;
using UnityEngine;
using Verse;
namespace ArachnaeSwarm
{
public static class Lifespan_Utility
{
public static IEnumerable<ThoughtDef> deathThought = new List<ThoughtDef>
{
ThoughtDefOf.KnowColonistDied,
ThoughtDefOf.PawnWithGoodOpinionDied,
ThoughtDefOf.WitnessedDeathFamily,
ThoughtDefOf.WitnessedDeathAlly,
};
public static bool IsDeathThought(this ThoughtDef tDef)
{
return (deathThought.Contains(tDef));
}
public static Thing ThingInCaseOfDeath(Pawn p)
{
Thing refThing;
if (p.Dead)
{
if (p.Corpse == null)
return null;
refThing = p.Corpse;
}
else
refThing = p;
return refThing;
}
public static void TrySpawnFilth(Thing refT, float filthRadius, ThingDef filthDef)
{
if (
refT.Map != null
&& CellFinder.TryFindRandomReachableNearbyCell(
refT.Position,
refT.Map,
filthRadius,
TraverseParms.For(TraverseMode.NoPassClosedDoors),
x => x.Standable(refT.Map),
x => true,
out IntVec3 result
)
)
FilthMaker.TryMakeFilth(result, refT.Map, filthDef);
}
public static void ThrowCustomSmoke(ThingDef moteDef, Vector3 loc, Map map, float size)
{
if (loc.ShouldSpawnMotesAt(map) && !map.moteCounter.SaturatedLowPriority)
{
MoteThrown obj = (MoteThrown)ThingMaker.MakeThing(moteDef);
obj.Scale = Rand.Range(1.5f, 2.5f) * size;
obj.rotationRate = Rand.Range(-30f, 30f);
obj.exactPosition = loc;
obj.SetVelocity(Rand.Range(30, 40), Rand.Range(0.5f, 0.7f));
GenSpawn.Spawn(obj, loc.ToIntVec3(), map);
}
}
public static bool TryDoSpawn(
Pawn pawn,
ThingDef thingDef,
int thingNum,
int spawnMaxAdjacent,
bool tryToUnstack,
bool inheritFaction,
bool spawnForbidden,
bool showMessageIfOwned
)
{
Thing refThing = ThingInCaseOfDeath(pawn);
IntVec3 spawnPos;
Map map;
if (refThing == null)
return false;
else
{
map = refThing.Map;
spawnPos = refThing.Position;
}
if (spawnMaxAdjacent >= 0)
{
int num = 0;
for (int i = 0; i < 9; i++)
{
IntVec3 c = spawnPos + GenAdj.AdjacentCellsAndInside[i];
if (!c.InBounds(map))
continue;
List<Thing> thingList = c.GetThingList(map);
for (int j = 0; j < thingList.Count; j++)
{
if (thingList[j].def == thingDef)
{
if (tryToUnstack)
continue;
num += thingList[j].stackCount;
if (num >= spawnMaxAdjacent)
return false;
}
}
}
}
if (TryFindSpawnCell(refThing, thingDef, thingNum, tryToUnstack, out IntVec3 result))
{
Thing thing = ThingMaker.MakeThing(thingDef);
thing.stackCount = thingNum;
if (thing == null)
Log.Error("Could not spawn anything for " + refThing);
if (inheritFaction && thing.Faction != refThing.Faction)
thing.SetFaction(refThing.Faction);
GenPlace.TryPlaceThing(
thing,
result,
map,
ThingPlaceMode.Direct,
out Thing lastResultingThing
);
if (spawnForbidden)
lastResultingThing.SetForbidden(value: true);
if (showMessageIfOwned && refThing.Faction == Faction.OfPlayer)
Messages.Message(
"MessageCompSpawnerSpawnedItem".Translate(thingDef.LabelCap),
thing,
MessageTypeDefOf.PositiveEvent
);
return true;
}
return false;
}
public static bool TryFindSpawnCell(
Thing parent,
ThingDef thingToSpawn,
int spawnCount,
bool tryToUnstack,
out IntVec3 result
)
{
foreach (IntVec3 item in GenAdj.CellsAdjacent8Way(parent).InRandomOrder())
{
if (item.Walkable(parent.Map))
{
Building edifice = item.GetEdifice(parent.Map);
if (edifice == null || !thingToSpawn.IsEdifice())
{
Building_Door building_Door = edifice as Building_Door;
if (
(building_Door == null || building_Door.FreePassage)
&& (
parent.def.passability == Traversability.Impassable
|| GenSight.LineOfSight(parent.Position, item, parent.Map)
)
)
{
bool flag = false;
List<Thing> thingList = item.GetThingList(parent.Map);
for (int i = 0; i < thingList.Count; i++)
{
Thing thing = thingList[i];
if (
thing.def.category == ThingCategory.Item
&& (
thing.def != thingToSpawn
|| thing.stackCount > thingToSpawn.stackLimit - spawnCount
)
)
{
flag = true;
break;
}
}
if (!flag)
{
result = item;
return true;
}
}
}
}
}
result = IntVec3.Invalid;
return false;
}
public static bool RemoveBadMemoriesOfDeadPawn(Pawn deadPawn, bool myDebug = false)
{
bool didIt = false;
if (deadPawn == null)
{
Log.Warning("removingRelationAndThoughts, null pawn");
return didIt;
}
string deadName = deadPawn.LabelShortCap;
Log.Warning(">>>>>" + deadName + " dissappeared, the world must not know");
foreach (
Pawn p in Find.CurrentMap.mapPawns.AllPawnsSpawned.Where(pH =>
pH != deadPawn
&& pH.needs.mood?.thoughts?.memories != null
&& pH.needs.mood.thoughts.memories.AnyMemoryConcerns(deadPawn)
)
)
{
Log.Warning(p.LabelShortCap + " has memories of " + deadName);
Log.Warning(
"pre removal mem count: " + p.needs.mood.thoughts.memories.Memories.Count
);
p.needs.mood.thoughts.memories.Memories.RemoveAll(TM =>
TM.otherPawn == deadPawn && TM.MoodOffset() <= 0f
);
Log.Warning(
"post removal mem count: " + p.needs.mood.thoughts.memories.Memories.Count
);
}
return didIt;
}
public static void removingRelationAndThoughts(Pawn deadPawn, bool myDebug = false)
{
if (deadPawn == null)
{
Log.Warning("removingRelationAndThoughts, null pawn");
return;
}
string deadName = deadPawn.LabelShortCap;
Log.Warning(">>>>>" + deadName + " dissappeared, the world must not know");
foreach (
Pawn p in Find.CurrentMap.mapPawns.AllPawnsSpawned.Where(pH =>
//!pH.AnimalOrWildMan() &&
pH != deadPawn
&& !pH.GetRelations(deadPawn).EnumerableNullOrEmpty()
)
)
{
string pName = p.LabelShortCap;
Log.Warning("Considering :" + pName);
IEnumerable<PawnRelationDef> relationT = PawnRelationUtility.GetRelations(
deadPawn,
p
);
if (relationT.EnumerableNullOrEmpty())
continue;
List<Thought> pThoughts = new List<Thought>();
if (p.needs.mood == null || p.needs.mood.thoughts == null)
continue;
//p.needs.mood.thoughts.memories.AnyMemoryConcerns()
if (pThoughts.NullOrEmpty())
return;
int tNum = 0;
foreach (Thought thought in pThoughts)
{
Log.Warning(pName + "'s Thought n" + tNum);
tNum++;
if (thought.pawn == null || deadPawn == null)
continue;
if (IsDeathThought(thought.def))
{
if (
!(
thought is Thought_MemorySocial TMS
&& TMS.otherPawn != null
&& TMS.otherPawn == deadPawn
)
)
continue;
deadPawn.needs.mood.thoughts.memories.RemoveMemory(TMS);
Log.Warning(
"removed " + pName + "'s thought " + thought.def.defName
);
}
}
}
Log.Warning("<<<<<" + deadName);
}
}
}