private List <int> GetStagesForAspect([NotNull] AspectDef aspectDef) { if (_lookupDict == null) { _lookupDict = new Dictionary <AspectDef, List <int> >(); foreach (Entry aspectEntry in aspectEntries) { if (aspectEntry.aspectDef == null) { continue; } List <int> lst; if (!_lookupDict.TryGetValue(aspectEntry.aspectDef, out lst)) { lst = new List <int>(); _lookupDict[aspectEntry.aspectDef] = lst; } lst.Add(aspectEntry.stageIndex); } } return(_lookupDict.TryGetValue(aspectDef)); }
private static void ApplyAspects(Pawn pawn, MorphPawnKindExtension extension) { if (pawn.GetAspectTracker() == null) { return; } if (extension.aspects.Count == 0) { return; } int addAspect = extension.aspectRange.RandomInRange; if (addAspect == 0) { return; } AspectTracker aspectTracker = pawn.GetAspectTracker(); if (aspectTracker == null) { return; } List <AspectDef> availableAspects = extension.GetAllAspectDefs().ToList(); addAspect = Mathf.Min(availableAspects.Count - 1, addAspect); if (addAspect == availableAspects.Count - 1) { foreach (AspectDef aspectDef in availableAspects) { int stage = extension.GetAvailableStagesFor(aspectDef).RandomElementWithFallback(); aspectTracker.Add(aspectDef, stage); } return; } for (var i = 0; i < addAspect; i++) { int r = Rand.Range(0, availableAspects.Count); //pick a random entry AspectDef def = availableAspects[r]; int stage = extension.GetAvailableStagesFor(def).RandomElementWithFallback(); aspectTracker.Add(def, stage); availableAspects.RemoveAt(r); //remove it so we don't pick it twice } }
private List <DebugMenuOption> GetAddAspectOptions(AspectDef def, Pawn p) { var outLst = new List <DebugMenuOption>(); for (var i = 0; i < def.stages.Count; i++) { AspectStage stage = def.stages[i]; int i1 = i; //need to make a copy var label = string.IsNullOrEmpty(stage.label) ? def.label : stage.label; outLst.Add(new DebugMenuOption($"{i}) {label}", DebugMenuOptionMode.Action, () => AddAspectAtStage(def, p, i1))); } return(outLst); }
private List <DebugMenuOption> GetAddAspectOptions(Pawn pawn) { AspectTracker tracker = pawn.GetAspectTracker(); var outLst = new List <DebugMenuOption>(); foreach (AspectDef aspectDef in DefDatabase <AspectDef> .AllDefs.Where(d => !tracker.Contains(d)) ) //don't allow aspects to be added more then once { AspectDef tmpDef = aspectDef; outLst.Add(new DebugMenuOption($"{aspectDef.defName}", DebugMenuOptionMode.Action, () => Find.WindowStack .Add(new Dialog_DebugOptionListLister(GetAddAspectOptions(tmpDef, pawn))))); } return(outLst); }
/// <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 AddAspectAtStage(AspectDef def, Pawn p, int i) { p.GetAspectTracker()?.Add(def, i); }
/// <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); } }