void IRaceChangeEventReceiver.OnRaceChange(ThingDef oldRace) { var oldMorph = oldRace.GetMorphOfRace(); var curMorph = parent.def.GetMorphOfRace(); HandleMorphChangeAffinities(oldMorph, curMorph); foreach (IRaceChangeEventReceiver raceChangeEventReceiver in _aspects.OfType <IRaceChangeEventReceiver>()) { raceChangeEventReceiver.OnRaceChange(oldRace); } }
/// <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); } }
/// <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); } }