using System.Collections.Generic; using System.Linq; using RimWorld; using UnityEngine; using Verse; namespace WulaFallenEmpire { public static class Lifespan_Utility { public static IEnumerable deathThought = new List { 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 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 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 relationT = PawnRelationUtility.GetRelations( deadPawn, p ); if (relationT.EnumerableNullOrEmpty()) continue; List pThoughts = new List(); 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); } } }