public static void DirtyCache_Postfix(HediffSet __instance) { if (Current.ProgramState != ProgramState.Playing) { return; } Pawn pawn = __instance.pawn; // Traverse.Create(__instance).Field("pawn").GetValue<Pawn>(); if (pawn == null || !pawn.Spawned || pawn.Map == null) { return; } if (!pawn.GetCompFace(out CompFace compFace)) { return; } if (!compFace.Deactivated && pawn.CheckForAddedOrMissingParts()) { pawn.Drawer.renderer.graphics.nakedGraphic = null; PortraitsCache.SetDirty(pawn); } pawn.GetCompAnim()?.PawnBodyGraphic?.Initialize(); }
public override void CompTickRare() { Pawn pawn = base.parent as Pawn; Map map = pawn?.Map; if (Settings.OnlyApplyToColonists && pawn.Faction?.IsPlayer == false) { return; } if (map != null && Settings.Indoors != Indoors.ShowHats && pawn.RaceProps?.Humanlike == true && !pawn.Dead) { if (this.isIndoors == null) { this.isIndoors = DetermineIsIndoors(pawn, map); PortraitsCache.SetDirty(pawn); GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(pawn); return; } bool orig = this.isIndoors.Value; this.isIndoors = this.DetermineIsIndoors(pawn, map); if (orig != this.isIndoors.Value) { PortraitsCache.SetDirty(pawn); GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(pawn); } } }
// ReSharper disable once MissingXmlDoc public override void WriteSettings() { settings?.Write(); SetMainButtons(); if (Current.ProgramState != ProgramState.Playing) { return; } { } List <Pawn> allPawns = PawnsFinder.AllMapsWorldAndTemporary_AliveOrDead.ToList(); for (int i = 0; i < allPawns.Count; i++) { Pawn pawn = allPawns[i]; if (!pawn.HasCompFace()) { continue; } pawn.Drawer.renderer.graphics.nakedGraphic = null; PortraitsCache.SetDirty(pawn); } // Bug: Not working when called or retrieved inside a mod // if (Find.ColonistBar != null) // { // Find.ColonistBar.MarkColonistsDirty(); // } }
static void Postfix(ref PawnGraphicSet __instance) { if (!__instance.pawn.Spawned) { return; } if (!(RimbrellasMod.settings.showUmbrellasInRain || RimbrellasMod.settings.showUmbrellasInSnow)) { return; } if ((!RimbrellasMod.settings.showUmbrellas) || (!(ShowFoldablesNow(__instance.pawn.Map)) || (__instance.pawn.Map.roofGrid.Roofed(__instance.pawn.Position) && !RimbrellasMod.settings.showUmbrellasWhenInside))) { List <ApparelGraphicRecord> remove = new List <ApparelGraphicRecord>(); foreach (ApparelGraphicRecord rec in __instance.apparelGraphics) { if (UmbrellaDefMethods.HideableUmbrellaDefs.Contains(rec.sourceApparel.def) || (UmbrellaDefMethods.UmbrellaDefs.Contains(rec.sourceApparel.def) && !RimbrellasMod.settings.showUmbrellas)) { remove.Add(rec); } } foreach (ApparelGraphicRecord rec in remove) { __instance.apparelGraphics.Remove(rec); } PortraitsCache.SetDirty(__instance.pawn); // NOTE: this is not necessarily required for when the weather changes and could be moved to only call when checking for roof above } }
static void Postfix(Pawn pawn) { if (!pawn.Spawned) { return; // Should never be the case here but copied from previous logic anyway just in case } if (!(RimbrellasMod.settings.showUmbrellasInRain || RimbrellasMod.settings.showUmbrellasInSnow)) { return; } if ((!RimbrellasMod.settings.showUmbrellas) || (!(ShowFoldablesNow(pawn.Map)) || (pawn.Map.roofGrid.Roofed(pawn.Position) && !RimbrellasMod.settings.showUmbrellasWhenInside))) { List <ApparelGraphicRecord> remove = new List <ApparelGraphicRecord>(); foreach (ApparelGraphicRecord rec in pawn.Drawer.renderer.graphics.apparelGraphics) { if (UmbrellaDefMethods.HideableUmbrellaDefs.Contains(rec.sourceApparel.def) || (UmbrellaDefMethods.UmbrellaDefs.Contains(rec.sourceApparel.def) && !RimbrellasMod.settings.showUmbrellas)) { remove.Add(rec); } } foreach (ApparelGraphicRecord rec in remove) { pawn.Drawer.renderer.graphics.apparelGraphics.Remove(rec); } PortraitsCache.SetDirty(pawn); // this gets called twice (once in the patched method) which is a bit unfortunate but makes the portraits correct at least } }
public static bool ResolveAllGraphicsWereWolf(PawnGraphicSet __instance) { if (Current.ProgramState != ProgramState.Playing) { return(true); } var pawn = Traverse.Create(__instance).Field("pawn").GetValue <Pawn>(); if (!pawn.Spawned) { return(true); } var compWerewolf = pawn.GetComp <CompWerewolf>(); if (compWerewolf == null || !compWerewolf.IsTransformed) { return(true); } compWerewolf.CurrentWerewolfForm.bodyGraphicData = compWerewolf.CurrentWerewolfForm.def.graphicData; __instance.nakedGraphic = compWerewolf.CurrentWerewolfForm.bodyGraphicData.Graphic; __instance.ResolveApparelGraphics(); PortraitsCache.SetDirty(pawn); return(false); }
public override void PostClose() { base.PostClose(); Prefs.HatsOnlyOnMap = this.originalHatsHideSetting; this.dresserDto.Pawn.Drawer.renderer.graphics.ResolveAllGraphics(); PortraitsCache.SetDirty(this.dresserDto.Pawn); }
private void MakeUndowned() { if (!this.Downed) { Log.Error(this.pawn + " tried to do MakeUndowned when already undowned.", false); } else { this.healthState = PawnHealthState.Mobile; if (PawnUtility.ShouldSendNotificationAbout(this.pawn)) { Messages.Message("MessageNoLongerDowned".Translate(new object[] { this.pawn.LabelCap }), this.pawn, MessageTypeDefOf.PositiveEvent, true); } if (this.pawn.Spawned && !this.pawn.InBed()) { this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable, true); } PortraitsCache.SetDirty(this.pawn); if (this.pawn.guest != null) { this.pawn.guest.Notify_PawnUndowned(); } } }
public static void Androidify(Pawn pawn) { ThingDef_AlienRace alien = ThingDefOf.ChjAndroid as ThingDef_AlienRace; pawn.story.hairColor = alien.alienRace.generalSettings.alienPartGenerator.colorChannels.FirstOrDefault(channel => channel.name == "hair").first.NewRandomizedColor(); AlienComp alienComp = pawn.TryGetComp <AlienComp>(); if (alienComp != null) { alienComp.ColorChannels["skin"].first = alien.alienRace.generalSettings.alienPartGenerator.colorChannels.FirstOrDefault(channel => channel.name == "skin").first.NewRandomizedColor(); } PortraitsCache.SetDirty(pawn); PortraitsCache.PortraitsCacheUpdate(); //Add Android Hediff. pawn.health.AddHediff(HediffDefOf.ChjAndroidLike); //Remove old wounds and bad birthday related ones. List <Hediff> hediffs = pawn.health.hediffSet.hediffs.ToList(); foreach (Hediff hediff in hediffs) { if (hediff is Hediff_Injury injury && injury.IsPermanent()) { pawn.health.hediffSet.hediffs.Remove(injury); injury.PostRemoved(); pawn.health.Notify_HediffChanged(null); }
protected override IEnumerable <Toil> MakeNewToils() { // Go to hairdressing table var gotoToil = Toils_Goto.GotoThing(TableIndex, PathEndMode.InteractionCell); yield return(gotoToil); // Bring up interface yield return(new Toil() { initAction = () => { Find.WindowStack.Add(new Dialog_ChangeHairstyle(this)); }, defaultCompleteMode = ToilCompleteMode.Never }); // Change hairstyle var hairdressToil = new Toil { tickAction = () => { // Work on changing hairstyle restyleTicksDone += pawn.GetStatValue(RimWorld.StatDefOf.GeneralLaborSpeed); if (restyleTicksDone >= ticksToRestyle) { if (AnyChanges) { FilthMaker.TryMakeFilth(pawn.Position, pawn.Map, ThingDefOf.VHE_Filth_Hair, 3); } if (newHairDef != null) { pawn.story.hairDef = newHairDef; } if (newHairColour.HasValue) { pawn.story.hairColor = newHairColour.Value; } if (newBeardDef != null) { this.pawn.style.beardDef = newBeardDef; } pawn.Drawer.renderer.graphics.ResolveAllGraphics(); PortraitsCache.SetDirty(pawn); GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(pawn); pawn.jobs.EndCurrentJob(JobCondition.Succeeded); } }, defaultCompleteMode = ToilCompleteMode.Never }; hairdressToil.WithProgressBar(TableIndex, () => restyleTicksDone / ticksToRestyle, true); hairdressToil.FailOnCannotTouch(TableIndex, PathEndMode.Touch); hairdressToil.PlaySustainerOrSound(SoundDefOf.Recipe_Tailor); yield return(hairdressToil); }
private static void ApparelChanged(this Pawn_ApparelTracker _this) { LongEventHandler.ExecuteWhenFinished(delegate { _this.pawn.Drawer.renderer.graphics.ResolveApparelGraphics(); PortraitsCache.SetDirty(_this.pawn); }); }
public static void Notify_EquipmentChanged(this Pawn_EquipmentTracker tracker) { LongEventHandler.ExecuteWhenFinished(delegate { tracker.pawn.Drawer.renderer.graphics.SetApparelGraphicsDirty(); PortraitsCache.SetDirty(tracker.pawn); GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(tracker.pawn); }); }
protected void rerenderPawn(Pawn pawn) { // Tell the pawn's Drawer that the Person has had a hair-change makeover. // This code is from https://github.com/KiameV/rimworld-changedresser/blob/f0b8fcf9073cd1c232fcd26b0b083cb3137924a3/Source/UI/DresserUI.cs // Copyright (c) 2017 Travis Offtermatt // MIT License pawn.Drawer.renderer.graphics.ResolveAllGraphics(); PortraitsCache.SetDirty(pawn); }
private void UpdateTarget() { Pawn pawn = parent.pawn; if (pawn.Spawned) { pawn.Map.attackTargetsCache.UpdateTarget(pawn); } PortraitsCache.SetDirty(pawn); }
private void UpdatePawnInfo() { if (Current.ProgramState == ProgramState.Playing && MutationUtilities.AllMutationsWithGraphics.Contains(def) && pawn.IsColonist) { pawn.Drawer.renderer.graphics.ResolveAllGraphics(); PortraitsCache.SetDirty(pawn); } pawn.GetMutationTracker()?.NotifyMutationAdded(this); }
public static void UpdateApparelGraphicsFor(Pawn pawn) { if (pawn != null) { pawn.Drawer.renderer.graphics.ResolveApparelGraphics(); PortraitsCache.SetDirty(pawn); PortraitsCache.Clear(); PortraitsCache.PortraitsCacheUpdate(); } }
static void Postfix(Pawn_DraftController __instance) { var p = __instance.pawn; if (p.IsColonist && !p.Dead && p.def.race.Humanlike) { PortraitsCache.SetDirty(p); GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(p); } }
public void ApplyToPawn(Pawn pawn) { pawn.story.hairDef = (HairDef)hairDef; pawn.story.hairColor = hairColour; pawn.style.beardDef = (BeardDef)this.beardDef; pawn.Drawer.renderer.graphics.ResolveAllGraphics(); PortraitsCache.SetDirty(pawn); }
protected override IEnumerable <Toil> MakeNewToils() { // Go to hairdressing table Toil gotoToil = Toils_Goto.GotoThing(TableIndex, PathEndMode.InteractionCell); yield return(gotoToil); // Bring up interface yield return(new Toil() { initAction = () => { Find.WindowStack.Add(new Dialog_ChangeFacepaint(this)); }, defaultCompleteMode = ToilCompleteMode.Never }); // Change hairstyle Toil hairdressToil = new Toil { tickAction = () => { // Work on changing hairstyle restyleTicksDone += pawn.GetStatValue(RimWorld.StatDefOf.GeneralLaborSpeed); if (restyleTicksDone >= ticksToRestyle) { //if (AnyChanges) ; //FilthMaker.TryMakeFilth(pawn.Position, pawn.Map, ThingDefOf.VHE_Filth_Hair, 3); if (pawn.GetComp <CompFacepaint>() is CompFacepaint facepaintComp) { facepaintComp.facepaintDefOne = this.newFacepaintDefOne; if (this.newFacepaintColorOne.HasValue) { facepaintComp.colorOne = this.newFacepaintColorOne.Value; } facepaintComp.facepaintDefTwo = this.newFacepaintDefTwo; if (this.newFacepaintColorTwo.HasValue) { facepaintComp.colorTwo = this.newFacepaintColorTwo.Value; } } GlobalTextureAtlasManager.TryMarkPawnFrameSetDirty(pawn); pawn.Drawer.renderer.graphics.ResolveAllGraphics(); PortraitsCache.SetDirty(pawn); pawn.jobs.EndCurrentJob(JobCondition.Succeeded); } }, defaultCompleteMode = ToilCompleteMode.Never }; hairdressToil.WithProgressBar(TableIndex, () => restyleTicksDone / ticksToRestyle, true); hairdressToil.FailOnCannotTouch(TableIndex, PathEndMode.Touch); hairdressToil.PlaySustainerOrSound(SoundDefOf.TinyBell); yield return(hairdressToil); }
static void Postfix(ref WeatherManager __instance, Map ___map) { foreach (Pawn pawn in ___map.mapPawns.AllPawnsSpawned) { if (!pawn.AnimalOrWildMan()) { pawn.Drawer.renderer.graphics.ResolveApparelGraphics(); PortraitsCache.SetDirty(pawn); } } }
/// <summary> /// refresh the graphics associated with this pawn, including the portraits if it's a colonist /// </summary> /// <param name="pawn"></param> public static void RefreshGraphics([NotNull] this Pawn pawn) { if (Current.ProgramState != ProgramState.Playing) { return; //make sure we don't refresh the graphics while the game is loading } pawn.Drawer.renderer.graphics.ResolveAllGraphics(); if (pawn.IsColonist) { PortraitsCache.SetDirty(pawn); } }
public void ApplyToPawn(Pawn pawn, bool coloursTied) { if (pawn.GetComp <CompFacepaint>() is CompFacepaint facepaintComp) { facepaintComp.facepaintDefOne = this.facepaintDefOne; facepaintComp.colorOne = this.colourOne; facepaintComp.facepaintDefTwo = this.facepaintDefTwo; facepaintComp.colorTwo = this.FacepaintColor(coloursTied); } pawn.Drawer.renderer.graphics.ResolveAllGraphics(); PortraitsCache.SetDirty(pawn); }
public override void PostClose() { Apparel apparel = this.thing as Apparel; if (apparel?.Wearer != null) { AdeptusApparelUtility.UpdateApparelGraphicsFor(apparel.Wearer); apparel.Wearer.Drawer.renderer.graphics.SetAllGraphicsDirty(); PortraitsCache.SetDirty(apparel.Wearer); } base.PostClose(); }
public override void PostTick() { if (pawn.RaceProps.Humanlike) //for now, only humans are supported { hediffs_semen = this.pawn.health.hediffSet.hediffs.FindAll(x => (x.def == RJW_SemenoOverlayHediffDefOf.Hediff_Semen || x.def == RJW_SemenoOverlayHediffDefOf.Hediff_InsectSpunk || x.def == RJW_SemenoOverlayHediffDefOf.Hediff_MechaFluids)); float bukkakeLevel = CalculateBukkakeLevel(); //sum of severity of all the s***n hediffs x semenWeight this.Severity = bukkakeLevel; bool updatePortrait = false; //loop through all s***n hediffs, add missing ones to dictionary for (int i = 0; i < hediffs_semen.Count(); i++) { Hediff_Semen h = (Hediff_Semen)hediffs_semen[i]; string ID = h.GetUniqueLoadID(); //unique ID for each hediff if (!splatches.ContainsKey(ID)) //if it isn't here yet, make new object { updatePortrait = true; bool leftSide = h.Part.Label.Contains("left") ? true : false; //depending on whether the body part is left or right, drawing-offset on x-aixs may be inverted splatches[ID] = new SemenSplatch(h, pawn.story.bodyType, h.Part.def, leftSide, h.semenType); } } //remove splatch objects once their respective s***n hediff is gone List <string> removeKeys = new List <string>(); foreach (string key in splatches.Keys) { SemenSplatch s = splatches[key]; if (!hediffs_semen.Contains(s.hediff_Semen)) { removeKeys.Add(key); updatePortrait = true; } } //loop over and remove elements that should be destroyed: foreach (string key in removeKeys) { SemenSplatch s = splatches[key]; splatches.Remove(key); } if (updatePortrait) //right now, portraits are only updated when a completely new s***n hediff is added or an old one removed - maybe that should be done more frequently { PortraitsCache.SetDirty(pawn); } } }
/// <summary> /// change the given pawn to the hybrid race of the desired morph /// </summary> /// <param name="pawn">The pawn.</param> /// <param name="morph">the morph to change the pawn to</param> /// <param name="addMissingMutations">if true, any missing mutations will be applied to the pawn</param> /// <param name="displayNotifications">if set to <c>true</c> display race shit notifications.</param> /// <exception cref="ArgumentNullException"> /// pawn /// or /// morph /// </exception> public static void ChangePawnToMorph([NotNull] Pawn pawn, [NotNull] MorphDef morph, bool addMissingMutations = true, bool displayNotifications = true) { if (pawn == null) { throw new ArgumentNullException(nameof(pawn)); } if (morph == null) { throw new ArgumentNullException(nameof(morph)); } if (morph.hybridRaceDef == null) { Log.Error($"tried to change pawn {pawn.Name.ToStringFull} to morph {morph.defName} but morph has no hybridRace!"); } if (pawn.def != ThingDefOf.Human && !pawn.IsHybridRace()) { return; } //apply mutations if (addMissingMutations) { SwapMutations(pawn, morph); } var hRace = morph.hybridRaceDef; MorphDef.TransformSettings tfSettings = morph.transformSettings; HandleGraphicsChanges(pawn, morph); ChangePawnRace(pawn, hRace, true); if (pawn.IsColonist) { PortraitsCache.SetDirty(pawn); } if (displayNotifications && (pawn.IsColonist || pawn.IsPrisonerOfColony)) { SendHybridTfMessage(pawn, tfSettings); } if (tfSettings?.transformTale != null) { TaleRecorder.RecordTale(tfSettings.transformTale, pawn); } pawn.TryGainMemory(tfSettings?.transformationMemory ?? PMThoughtDefOf.DefaultMorphTfMemory); }
public override void WriteSettings() { if (Find.Maps != null) { //when settings get written re-render portraits foreach (var map in Find.Maps) { foreach (var pawn in map.mapPawns.AllPawnsSpawned.Where(p => p.IsColonist)) { PortraitsCache.SetDirty(pawn); } } } base.WriteSettings(); }
/// <summary> /// Apply this coloration to a pawn directly. /// </summary> /// <param name="graphics">Pawn's graphics set</param> public void TryDirectRecolorAnimal(PawnGraphicSet graphics) { if (this.Pawn != null && this.Pawn.RaceProps != null && !this.Pawn.RaceProps.Humanlike) { if (ColorSet.skinColor.HasValue || ColorSet.skinColorTwo.HasValue) { graphics.nakedGraphic = graphics.nakedGraphic.GetColoredVersion(graphics.nakedGraphic.Shader, ColorSet.skinColor.HasValue ? ColorSet.skinColor.Value : graphics.nakedGraphic.color, ColorSet.skinColorTwo.HasValue ? ColorSet.skinColorTwo.Value : graphics.nakedGraphic.colorTwo); } if (this.Pawn.IsColonist || this.Pawn.IsColonistAnimal()) { PortraitsCache.SetDirty(this.Pawn); Find.ColonistBar.MarkColonistsDirty(); } } }
//fixes issue of portraits of pawns having blank portraits on first load of the game after boot public static void OnLoadPortraitsBugfix(ColonistBar __instance) { if (HarmonyPatches_BHair.colonistBarFirstDraw) { __instance.MarkColonistsDirty(); List <Pawn> pawnList = __instance.GetColonistsInOrder(); foreach (Pawn pawn in pawnList) { pawn.Drawer.renderer.graphics.ResolveAllGraphics(); PortraitsCache.SetDirty(pawn); } HarmonyPatches_BHair.colonistBarFirstDraw = false; } }
protected override IEnumerable <string> ApplyPartWorker(Pawn pawn, object cause) { CompTFTracker tracker = pawn.GetComp <CompTFTracker>(); Color target = tracker.LoadData <Color>(this, SkinColorTarget); if (target.NullOrClear()) { target = colorGenerator.NewRandomizedColor(); tracker.SaveData(this, SkinColorTarget, target); } tracker.SaveData(null, "skinColor", ColorUtility.MoveTowards(pawn.story.SkinColor, target, delta)); tracker.SaveData(null, SkinColorPower, power); pawn.Drawer.renderer.graphics.ResolveAllGraphics(); PortraitsCache.SetDirty(pawn); yield break; }
public static void TintClothes(Pawn pawn) { if (pawn?.apparel == null) { return; } #if V12 bool changedAny = false; #endif int colorIndex = 0; foreach (var item in pawn.apparel.WornApparel) { var comp = item?.GetComp <CompColorable>(); if (comp == null) { continue; } Color color = ClothesColors[colorIndex % ClothesColors.Length]; colorIndex++; #if V13 comp.SetColor(color); #else comp.Color = color; changedAny = true; #endif } #if V12 if (!changedAny) { return; } // Update apparel graphics. pawn.Drawer.renderer.graphics.SetApparelGraphicsDirty(); PortraitsCache.SetDirty(pawn); #endif }