public static bool RegisterInRegions(Thing thing, Map map) { if (!ListerThings.EverListable(thing.def, ListerThingsUse.Region)) { return(false); } int tID = Thread.CurrentThread.ManagedThreadId; if (!tmpRegionsLists.TryGetValue(tID, out List <Region> tmpRegions)) { tmpRegions = new List <Region>(); tmpRegionsLists[tID] = tmpRegions; } else { tmpRegions.Clear(); } RegionListersUpdater.GetTouchableRegions(thing, map, tmpRegions, false); for (int i = 0; i < tmpRegions.Count; i++) { ListerThings listerThings = tmpRegions[i].ListerThings; lock (listerThings) { if (!listerThings.Contains(thing)) { listerThings.Add(thing); } } } return(false); }
private void TransformPawn(ThingDef @into, PawnKindDef intoKind) { Log.Message("Performing Transform on " + pawn + " to a " + into + "with a kind of " + intoKind); if (into == null || into == pawn.def) { return; } var map = pawn.Map; RegionListersUpdater.DeregisterInRegions(pawn, map); pawn.def = into; pawn.ChangeKind(intoKind); RegionListersUpdater.RegisterInRegions(pawn, map); map.mapPawns.UpdateRegistryForPawn(pawn); //save the pawn pawn.ExposeData(); //magic to make image change pawn.ageTracker.AgeBiologicalTicks = pawn.ageTracker.AgeBiologicalTicks - 1; //pawn.SpawnSetup(map, true); didIt = true; }
/// <summary> /// destroying a resource outright causes too much overhead: fog, area reveal, pathing, roof updates, etc /// we just want to replace it. So, we manually strip it out of the map and do some cleanup. /// The following is Thing.Despawn code with the unnecessary (for buildings, ar least) parts stripped out, plus key parts from Building.Despawn /// TODO: This approach may break with future releases (if thing despawning changes), so it's worth checking over. /// </summary> private static void SneakilyDestroyResource(Thing res) { var map = res.Map; RegionListersUpdater.DeregisterInRegions(res, map); map.spawnedThings.Remove(res); map.listerThings.Remove(res); map.thingGrid.Deregister(res); map.coverGrid.DeRegister(res); map.tooltipGiverList.Notify_ThingDespawned(res); if (res.def.graphicData != null && res.def.graphicData.Linked) { map.linkGrid.Notify_LinkerCreatedOrDestroyed(res); map.mapDrawer.MapMeshDirty(res.Position, MapMeshFlag.Things, true, false); } Find.Selector.Deselect(res); res.DirtyMapMesh(map); if (res.def.drawerType != DrawerType.MapMeshOnly) { map.dynamicDrawManager.DeRegisterDrawable(res); } ReflectionCache.Thing_State.SetValue(res, res.def.DiscardOnDestroyed ? ThingDiscardedState : ThingMemoryState); Find.TickManager.DeRegisterAllTickabilityFor(res); map.attackTargetsCache.Notify_ThingDespawned(res); StealAIDebugDrawer.Notify_ThingChanged(res); // building-specific cleanup var b = (Building)res; if (res.def.IsEdifice()) { map.edificeGrid.DeRegister(b); } var sustainer = (Sustainer)ReflectionCache.Building_SustainerAmbient.GetValue(res); if (sustainer != null) { sustainer.End(); } map.mapDrawer.MapMeshDirty(b.Position, MapMeshFlag.Buildings); map.glowGrid.MarkGlowGridDirty(b.Position); map.listerBuildings.Remove((Building)res); map.listerBuildingsRepairable.Notify_BuildingDeSpawned(b); map.designationManager.Notify_BuildingDespawned(b); }
private void TransformPawn(bool changeDef = true, bool keep = false) { IntVec3 where = pawn.Position; Map map = pawn.Map; //Body change to Astarte pawn.DeSpawn(); // pawn.DestroyOrPassToWorld(); RegionListersUpdater.DeregisterInRegions(pawn, map); var thingDef = PawnThingDef(); if (changeDef && thingDef != null) { HediffSet set = pawn.health.hediffSet; pawn.def = thingDef; pawn.health = new Pawn_HealthTracker(pawn); pawn.health.hediffSet.DirtyCache(); pawn.health.hediffSet = set; } // pawn.SpawnSetup(map, true); RegionListersUpdater.RegisterInRegions(pawn, map); map.mapPawns.UpdateRegistryForPawn(pawn); //remove the 19 if (BlowOffParts(keep)) { RemoveAstarteParts(); } //decache graphics pawn.Drawer.renderer.graphics.ResolveAllGraphics(); //save the pawn pawn.ExposeData(); GenSpawn.Spawn(pawn, where, map); // pawn.Position = map.Center; }
private void TransformPawn(bool changeDef = true, bool keep = false) { //Body change to Astarte var where = pawn.Position; var map = pawn.Map; pawn.DestroyOrPassToWorld(); pawn.DeSpawn(); RegionListersUpdater.DeregisterInRegions(pawn, map); var thingDef = PawnThingDef(); if (changeDef && thingDef != null) { pawn.def = thingDef; } pawn.SpawnSetup(map, true); RegionListersUpdater.RegisterInRegions(pawn, map); map.mapPawns.UpdateRegistryForPawn(pawn); //remove the 19 if (BlowOffParts(keep)) { RemoveAstarteParts(); } //decache graphics pawn.Drawer.renderer.graphics.ResolveAllGraphics(); //save the pawn pawn.ExposeData(); pawn.Position = map.Center; }
public static bool DeregisterInRegions(Thing thing, Map map) { if (!ListerThings.EverListable(thing.def, ListerThingsUse.Region)) { return(false); } List <Region> tmpRegions = new List <Region>(); RegionListersUpdater.GetTouchableRegions(thing, map, tmpRegions, true); for (int i = 0; i < tmpRegions.Count; i++) { ListerThings listerThings = tmpRegions[i].ListerThings; lock (listerThings) { if (listerThings.Contains(thing)) { listerThings.Remove(thing); } } } return(false); }
private void TransformPawn(bool changeDef = true, bool keep = false) { //sets position, faction and map IntVec3 intv = Pawn.Position; Faction faction = Pawn.Faction; Map map = Pawn.Map; RegionListersUpdater.DeregisterInRegions(Pawn, map); //Change Race to Props.raceDef if (changeDef && alienRace != null && alienRace != Pawn.def) { Pawn.def = alienRace; long ageB = Pawn.ageTracker.AgeBiologicalTicks; long ageC = Pawn.ageTracker.AgeChronologicalTicks; Pawn.ageTracker = new Pawn_AgeTracker(Pawn); Pawn.ageTracker.AgeBiologicalTicks = ageB; Pawn.ageTracker.AgeChronologicalTicks = ageC; if (!Pawn.RaceProps.hasGenders) { Pawn.gender = Gender.None; } if (Props.removeHair) { // Pawn.story.hairDef = DefDatabase<HairDef>.GetNamed("Shaved", true); Pawn.story.hairDef = PawnHairChooser.RandomHairDefFor(Pawn, noHairFaction); // Pawn.Drawer.renderer.graphics.hairGraphic; } else { if (Props.colourHairTwo || Props.colourHair) { if (compAlien != null) { ColorChannelGenerator Alienhair = alienRace.alienRace.generalSettings.alienPartGenerator.colorChannels.Find(x => x.name == "hair"); AlienPartGenerator.ExposableValueTuple <UnityEngine.Color, UnityEngine.Color> hair; if (compAlien.ColorChannels.TryGetValue("hair", out hair)) { if (Props.colourHair && Alienhair?.first != null) { hair.first = Alienhair.first.NewRandomizedColor(); } if (Props.colourHairTwo && Alienhair?.second != null) { hair.second = Alienhair.second.NewRandomizedColor(); } compAlien.ColorChannels.SetOrAdd("hair", hair); } Pawn.Notify_ColorChanged(); } } } //Change BodyType to Props.bodyTypeDef if (Props.changeBody) { if (Props.bodyTypeDef != null) { ChangeBodyType(Pawn, Props.bodyTypeDef); } else { ChangeBodyType(Pawn, alienRace.alienRace.generalSettings.alienPartGenerator.alienbodytypes[Rand.Range(0, alienRace.alienRace.generalSettings.alienPartGenerator.alienbodytypes.Count)]); } } } //Remove Disallowed Traits int maxTraits; if (MoreTraitSlotsUtil.TryGetMaxTraitSlots(out int max)) { maxTraits = max; } else { maxTraits = 4; } if (!Props.traitsToRemove.NullOrEmpty()) { if (Pawn.story.traits.allTraits.Any(x => Props.traitsToRemove.Any(y => y.def == x.def))) { foreach (ExtendedTraitEntry item in Props.traitsToRemove) { if (Pawn.story.traits.HasTrait(item.def)) { Rand.PushState(); if (Rand.Chance(item.Chance)) { Pawn.story.traits.allTraits.Remove(Pawn.story.traits.allTraits.Find(x => x.def == item.def)); } Rand.PopState(); } } } } if (!Props.traitsToAdd.NullOrEmpty()) { if (Props.traitsToAdd.Any(x => !Pawn.story.traits.HasTrait(x.def))) { foreach (ExtendedTraitEntry item in Props.traitsToAdd) { if (!Pawn.story.traits.HasTrait(item.def)) { Rand.PushState(); if (Rand.Chance(item.Chance)) { bool replace = false; int countTraits = Pawn.story.traits.allTraits.Count; if (countTraits >= maxTraits) { replace = true; } // Log.Message(string.Format("i have {0} of a max of {1} traits", countTraits, maxTraits)); Trait replacedTrait = Pawn.story.traits.allTraits.Where(x => Props.traitsToAdd.Any(y => y.def != x.def)).RandomElement(); if (replace) { Pawn.story.traits.allTraits.Remove(replacedTrait); } Pawn.story.traits.allTraits.Add(new Trait(item.def, item.degree)); } Rand.PopState(); } } } } RegionListersUpdater.RegisterInRegions(Pawn, map); map.mapPawns.UpdateRegistryForPawn(Pawn); //decache graphics Pawn.Drawer.renderer.graphics.ResolveAllGraphics(); Find.ColonistBar.drawer.Notify_RecachedEntries(); //save the pawn Pawn.ExposeData(); if (Pawn.Faction != faction) { Pawn.SetFaction(faction); } // pawn.Position = intv; }
private void TransformPawn(bool changeDef = true, bool keep = false) { //sets position, faction and map IntVec3 intv = parent.pawn.Position; Faction faction = parent.pawn.Faction; Map map = parent.pawn.Map; RegionListersUpdater.DeregisterInRegions(parent.pawn, map); //Change Race to Props.raceDef var thingDef = Props.raceDef ?? null; if (changeDef && thingDef != null && thingDef != parent.pawn.def) { parent.pawn.def = thingDef; long ageB = Pawn.ageTracker.AgeBiologicalTicks; long ageC = Pawn.ageTracker.AgeChronologicalTicks; Pawn.ageTracker = new Pawn_AgeTracker(Pawn); Pawn.ageTracker.AgeBiologicalTicks = ageB; Pawn.ageTracker.AgeChronologicalTicks = ageC; AlienRace.ThingDef_AlienRace alienRace = (AlienRace.ThingDef_AlienRace)thingDef; AlienRace.AlienPartGenerator.AlienComp alien = parent.pawn.TryGetComp <AlienRace.AlienPartGenerator.AlienComp>(); if (Props.colourSkinTwo || Props.colourSkin) { if (Props.colourSkin) { if (alien != null) { alien.skinColor = alienRace.alienRace.generalSettings.alienPartGenerator.SkinColor(parent.pawn); } } if (Props.colourSkinTwo) { if (alien != null) { alien.skinColorSecond = alienRace.alienRace.generalSettings.alienPartGenerator.SkinColor(parent.pawn, false); } } parent.pawn.Notify_ColorChanged(); } if (Props.removeHair) { parent.pawn.story.hairDef = PawnHairChooser.RandomHairDefFor(Pawn, noHairFaction); } else { if (Props.colourHairTwo || Props.colourHair) { if (Props.colourHair) { if (alien != null) { Pawn.story.hairColor = alienRace.alienRace.generalSettings.alienPartGenerator.alienhaircolorgen.NewRandomizedColor();; } } if (Props.colourHairTwo) { if (alien != null) { alien.hairColorSecond = alienRace.alienRace.generalSettings.alienPartGenerator.alienhaircolorgen.NewRandomizedColor(); } } parent.pawn.Notify_ColorChanged(); } } string head = alienRace.alienRace.graphicPaths.GetCurrentGraphicPath(Pawn.ageTracker.CurLifeStageRace.def).head; Traverse.Create(Pawn.story).Field("headGraphicPath").SetValue(alienRace.alienRace.generalSettings.alienPartGenerator.RandomAlienHead(head, Pawn)); } //Remove Disallowed Traits int maxTraits; if (MoreTraitSlotsUtil.TryGetMaxTraitSlots(out int max)) { maxTraits = max; } else { maxTraits = 4; } if (parent.pawn.story.traits.allTraits.Any(x => Props.traitsToRemove.Any(y => y.def == x.def))) { foreach (ExtendedTraitEntry item in Props.traitsToRemove) { if (parent.pawn.story.traits.HasTrait(item.def)) { Rand.PushState(); if (Rand.Chance(item.Chance)) { parent.pawn.story.traits.allTraits.Remove(parent.pawn.story.traits.allTraits.Find(x => x.def == item.def)); } Rand.PopState(); } } } if (Props.traitsToAdd.Any(x => !parent.pawn.story.traits.HasTrait(x.def))) { foreach (ExtendedTraitEntry item in Props.traitsToAdd) { if (!parent.pawn.story.traits.HasTrait(item.def)) { Rand.PushState(); if (Rand.Chance(item.Chance)) { bool replace = false; int countTraits = parent.pawn.story.traits.allTraits.Count; if (countTraits >= maxTraits) { replace = true; } // Log.Message(string.Format("i have {0} of a max of {1} traits", countTraits, maxTraits)); Trait replacedTrait = parent.pawn.story.traits.allTraits.Where(x => Props.traitsToAdd.Any(y => y.def != x.def)).RandomElement(); if (replace) { parent.pawn.story.traits.allTraits.Remove(replacedTrait); } parent.pawn.story.traits.allTraits.Add(new Trait(item.def, item.degree)); } Rand.PopState(); } } } RegionListersUpdater.RegisterInRegions(parent.pawn, map); map.mapPawns.UpdateRegistryForPawn(parent.pawn); //Change BodyType to Props.bodyTypeDef if (!Pawn.RaceProps.hasGenders) { Pawn.gender = Gender.None; } if (Props.bodyTypeDef != null) { ChangeBodyType(parent.pawn, Props.bodyTypeDef); } //decache graphics parent.pawn.Drawer.renderer.graphics.ResolveAllGraphics(); Find.ColonistBar.drawer.Notify_RecachedEntries(); //save the pawn parent.pawn.ExposeData(); if (parent.pawn.Faction != faction) { parent.pawn.SetFaction(faction); } // pawn.Position = intv; }
/// <summary> /// safely change the pawns race /// </summary> /// <param name="pawn"></param> /// <param name="race"></param> /// <param name="reRollTraits">if race related traits should be reRolled</param> public static void ChangePawnRace([NotNull] Pawn pawn, ThingDef race, bool reRollTraits = false) { if (pawn == null) { throw new ArgumentNullException(nameof(pawn)); } MorphDef oldMorph = pawn.def.GetMorphOfRace(); ThingDef oldRace = pawn.def; AspectTracker aTracker = pawn.GetAspectTracker(); AspectDef oldMorphAspectDef = oldMorph?.group?.aspectDef; if (oldMorphAspectDef != null && aTracker != null) { Aspect aspect = aTracker.GetAspect(oldMorphAspectDef); if (aspect != null) { aTracker.Remove(aspect); } } //var pos = pawn.Position; Faction faction = pawn.Faction; Map map = pawn.Map; if (map != null) { RegionListersUpdater.DeregisterInRegions(pawn, map); } var removed = false; if (map != null) { if (map.listerThings.Contains(pawn)) { map.listerThings.Remove(pawn); //make sure to update the lister things or else dying will break removed = true; } } pawn.def = race; if (removed && !map.listerThings.Contains(pawn)) { map.listerThings.Add(pawn); } if (map != null) { RegionListersUpdater.RegisterInRegions(pawn, map); } map?.mapPawns.UpdateRegistryForPawn(pawn); //add the group hediff if applicable AspectDef aspectDef = race.GetMorphOfRace()?.group?.aspectDef; if (aspectDef != null) { aTracker?.Add(aspectDef); } if (map != null) { var comp = map.GetComponent <MorphTracker>(); comp.NotifyPawnRaceChanged(pawn, oldMorph); } //no idea what HarmonyPatches.Patch.ChangeBodyType is for, not listed in pasterbin pawn.RefreshGraphics(); if (reRollTraits && race is ThingDef_AlienRace alienDef) { ReRollRaceTraits(pawn, alienDef); } //save location if (Current.ProgramState == ProgramState.Playing) { pawn.ExposeData(); } if (pawn.Faction != faction) { pawn.SetFaction(faction); } foreach (IRaceChangeEventReceiver raceChangeEventReceiver in pawn.AllComps.OfType <IRaceChangeEventReceiver>()) { raceChangeEventReceiver.OnRaceChange(oldRace); } }
private void TransformPawn(PawnKindDef kindDef, bool changeDef = true, bool keep = false) { //sets position, faction and map IntVec3 intv = parent.pawn.Position; Faction faction = parent.pawn.Faction; Map map = parent.pawn.Map; RegionListersUpdater.DeregisterInRegions(parent.pawn, map); //Change Race to Props.raceDef if (changeDef && kindDef != null && kindDef != parent.pawn.kindDef) { parent.pawn.def = kindDef.race; parent.pawn.kindDef = kindDef; long ageB = Pawn.ageTracker.AgeBiologicalTicks; long ageC = Pawn.ageTracker.AgeChronologicalTicks; Pawn.ageTracker = new Pawn_AgeTracker(Pawn); Pawn.ageTracker.AgeBiologicalTicks = ageB; Pawn.ageTracker.AgeChronologicalTicks = ageC; } RegionListersUpdater.RegisterInRegions(parent.pawn, map); map.mapPawns.UpdateRegistryForPawn(parent.pawn); //decache graphics parent.pawn.Drawer.renderer.graphics.ResolveAllGraphics(); // remove non whitelisted hediffs if (!Pawn.health.hediffSet.hediffs.NullOrEmpty()) { if (!Props.whitelists.NullOrEmpty()) { foreach (MetroidWhitelistDef list in Props.whitelists) { if (parent.pawn.health.hediffSet.hediffs.Any(x => !list.whitelist.Contains(x.def) && x != this.parent)) { List <Hediff> removeable = parent.pawn.health.hediffSet.hediffs.Where(x => !list.whitelist.Contains(x.def) && x != this.parent).ToList(); foreach (Hediff item in removeable) { if (item != this.parent) { Pawn.health.RemoveHediff(item); } } } } } else { List <Hediff> removeable = parent.pawn.health.hediffSet.hediffs; foreach (Hediff item in removeable) { if (item != this.parent) { Pawn.health.RemoveHediff(item); } } } } //save the pawn parent.pawn.ExposeData(); if (parent.pawn.Faction != faction) { parent.pawn.SetFaction(faction); } //spawn Husk if set if (Props.huskDef != null) { GenSpawn.Spawn(ThingMaker.MakeThing(Props.huskDef), parent.pawn.Position, parent.pawn.Map); } }
/// <summary> /// safely change the pawns race /// </summary> /// <param name="pawn">The pawn.</param> /// <param name="race">The race.</param> /// <param name="reRollTraits">if race related traits should be reRolled</param> /// <exception cref="ArgumentNullException">pawn</exception> public static void ChangePawnRace([NotNull] Pawn pawn, [NotNull] ThingDef race, bool reRollTraits = false) { if (pawn == null) { throw new ArgumentNullException(nameof(pawn)); } if (race == null) { throw new ArgumentNullException(nameof(race)); } MorphDef oldMorph = pawn.def.GetMorphOfRace(); ThingDef oldRace = pawn.def; AspectTracker aTracker = pawn.GetAspectTracker(); AspectDef oldMorphAspectDef = oldMorph?.group?.aspectDef; if (oldMorphAspectDef != null && aTracker != null) { Aspect aspect = aTracker.GetAspect(oldMorphAspectDef); if (aspect != null) { aTracker.Remove(aspect); } } TransformerUtility.ScaleInjuriesToNewRace(pawn, race); //var pos = pawn.Position; Faction faction = pawn.Faction; Map map = pawn.Map; if (map != null) { RegionListersUpdater.DeregisterInRegions(pawn, map); } var removed = false; if (map?.listerThings != null) { if (map.listerThings.Contains(pawn)) { map.listerThings.Remove(pawn); //make sure to update the lister things or else dying will break removed = true; } } pawn.def = race; if (removed && !map.listerThings.Contains(pawn)) { map.listerThings.Add(pawn); } if (map != null) { RegionListersUpdater.RegisterInRegions(pawn, map); } map?.mapPawns.UpdateRegistryForPawn(pawn); //add the group hediff if applicable AspectDef aspectDef = race.GetMorphOfRace()?.group?.aspectDef; if (aspectDef != null) { aTracker?.Add(aspectDef); } if (map != null) { var comp = map.GetComponent <MorphTracker>(); comp.NotifyPawnRaceChanged(pawn, oldMorph); } //always revert to human settings first so the race change is consistent ValidateReversion(pawn); //check if the body def changed and handle any apparel changes if (oldRace.race.body != race.race.body) { ValidateApparelForChangedPawn(pawn, oldRace); } if (race != ThingDefOf.Human) { ValidateExplicitRaceChange(pawn, race, oldRace); } var mTracker = pawn.GetComp <MorphTrackingComp>(); if (mTracker == null) { Warning($"changing the race of {pawn.Name} but they have no {nameof(MorphTrackingComp)}!"); } else { mTracker.needsRaceCompCheck = true; } //no idea what HarmonyPatches.Patch.ChangeBodyType is for, not listed in pasterbin pawn.RefreshGraphics(); if (reRollTraits && race is ThingDef_AlienRace alienDef) { ReRollRaceTraits(pawn, alienDef); } //save location if (Current.ProgramState == ProgramState.Playing) { pawn.ExposeData(); } if (pawn.Faction != faction) { pawn.SetFaction(faction); } foreach (IRaceChangeEventReceiver raceChangeEventReceiver in pawn.AllComps.OfType <IRaceChangeEventReceiver>()) { raceChangeEventReceiver.OnRaceChange(oldRace); } }