예제 #1
0
        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);
            }
        }
예제 #2
0
        /// <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);
            }
        }
예제 #3
0
        /// <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);
            }
        }