using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEngine; using RimWorld; using rjw; using Verse; namespace SizedApparel { [StaticConstructorOnStartup] public class ApparelRecorderComp : ThingComp { Pawn pawn;// Parent Cache public bool recentClothFlag = true; public bool isDrawAge = true; public bool testbool = false; public ApparelRecorderCompProperties Props => (ApparelRecorderCompProperties)this.props; public bool hasUpdateBefore = false; public bool hasUpdateBeforeSuccess = false; public bool hasGraphicUpdatedBefore = false; // not yet public bool needToCheckApparelGraphicRecords = false; public bool isDirty = true; public bool hasUnsupportedApparel = true; public bool havingSex = false;//Obsolete public bool hasUpdateForSex = false;//Obsolete public List cachedApparelGraphicRecord = new List(); public Hediff breastHediff = null; //TODO: Make this as List public Hediff vaginaHediff = null; public List penisHediffs = null; // RJW can attach multiple penis public Hediff anusHediff = null; public Hediff udderHediff = null;//RJW 4.6.8: Udder is not partof chest's breast. it attached to torso. public float breastSeverity = -1; public float breastSeverityCapToDraw = 1000; public float BreastSeverityCache = 0; //public float BiggestBreastSeverityInAvailableTextures = 0; //for breasts animation or something. public bool ForceUpdateTickAnimation = false; public bool PrePositionCache; public Vector3? prePositionCache; public float? preAngleCache; public int? preTickCache; public Vector3 preVelocity = Vector3.zero; public float preRotation = 0; public Dictionary tickCache = new Dictionary(); public SizedApparelBodyPart bodyPartBreasts;//TODO: Make this as List public SizedApparelBodyPart bodyPartNipple;//TODO public List bodyPartPenises = new List(); public List bodyPartBalls = new List(); public SizedApparelBodyPart bodyPartVagina; public SizedApparelBodyPart bodyPartAnus; public SizedApparelBodyPart bodyPartBelly; public SizedApparelBodyPart bodyPartMuscleOverlay;//TODO public SizedApparelBodyPart bodyPartUdder; public SizedApparelBodyPart bodyPartPubicHair; //TODO public SizedApparelBodyPart bodyPartHips; public List bodyPartThighs = new List(); public List bodyPartHands = new List(); public List bodyPartFeet = new List(); public Graphic graphicSourceNaked = null; //original Graphic public Graphic graphicSourceRotten = null; //original Graphic public Graphic graphicSourceFurCovered = null; //original Graphic public Graphic graphicbaseBodyNaked = null; public Graphic graphicbaseBodyCorpse = null; public Graphic graphicbaseBodyRotten = null; public Graphic graphicbaseBodyFurCovered = null; [Obsolete] public Graphic graphicBreasts = null; [Obsolete] public Graphic graphicBreasts_horny = null; [Obsolete] public Graphic graphicVagina = null; [Obsolete] public Graphic graphicVagina_horny = null; [Obsolete] public Graphic graphicAnus = null; [Obsolete] public Graphic graphicAnus_horny = null; [Obsolete] public List graphicPenises = new List(); [Obsolete] public List graphicBallsOfPenises = new List(); [Obsolete] public Graphic graphicBelly = null; [Obsolete] public Graphic graphicUdder = null; //RJW 4.6.8: Udder is not partof chest's breast. it attached to torso. [Obsolete] public Graphic graphicUdder_horny = null; [Obsolete] public List graphicPenises_horny = new List(); [Obsolete] public List graphicBalls_horny = new List();//Does it need? //size uncapped breasts graphics. [Obsolete] public Graphic graphicBreastsNude = null; [Obsolete] public Graphic graphicBreastsNude_horny = null; private bool drawingBreastsAddon = false; public AlienRaceSetting raceSetting = new AlienRaceSetting(); public string customPose = null; public SizedApparelPose currentCustomPose = null; public bool forceHorny = false; public bool canDrawBreasts = false; public bool canDrawPenis = false; public bool canDrawVaginaAndAnus = false; public bool canDrawTorsoParts = false; //belly and udder public override void Initialize(CompProperties props) { base.Initialize(props); this.pawn = this.parent as Pawn; bodyPartBreasts = new SizedApparelBodyPart(pawn, this, "Breasts", SizedApparelBodyPartOf.Breasts, "Breasts", true, false); bodyPartBreasts.SetDepthOffsets(0.0113f, 0.001f, 0.0113f, 0.0113f); bodyPartNipple = new SizedApparelBodyPart(pawn, this, "Nippple", SizedApparelBodyPartOf.Breasts, "Breasts", true, false); bodyPartBreasts.SetDepthOffsets(0.0114f, 0.000f, 0.0114f, 0.0114f); bodyPartUdder = new SizedApparelBodyPart(pawn, this, "Udder", SizedApparelBodyPartOf.Udder, "UdderBreasts", true, false); bodyPartUdder.SetDepthOffsets(0.0112f, 0.0005f, 0.0112f, 0.0112f); //UdderNipple...? //bodyPartUdder = new SizedApparelBodyPart(p, "Udder", SizedApparelBodyPartOf.Udder, "UdderBreasts", true, false); //bodyPartUdder.SetDepthOffsets(0.0112f, 0.0005f, 0.0112f, 0.0112f); bodyPartVagina = new SizedApparelBodyPart(pawn, this, "Vagina", SizedApparelBodyPartOf.Vagina, "Vagina", false, false); bodyPartVagina.SetDepthOffsets(0.0088f, 0.0100f, 0.0088f, 0.0088f); bodyPartAnus = new SizedApparelBodyPart(pawn, this, "Anus", SizedApparelBodyPartOf.Anus, "Anus", false, false); bodyPartAnus.SetDepthOffsets(0.0093f, 0.0105f, 0.0093f, 0.0093f); bodyPartBelly = new SizedApparelBodyPart(pawn, this, "Belly", SizedApparelBodyPartOf.Belly, "BellyBulge", false, false); bodyPartBelly.SetDepthOffsets(0.0098f, 0.0002f, 0.0098f, 0.0098f); } public override void PostExposeData() { base.PostExposeData(); Scribe_Values.Look(ref customPose, "customPose"); // save pawn's custom pose //Scribe_Values.Look<>(); //TODO: save pubic hair data } /* public override void CompTick() { if (PrePositionCache) { } base.CompTick(); }*/ /* public override void CompTickRare() { base.CompTickRare(); }*/ float penisAngle = 0; public void SetPenisAngle(float angle) { penisAngle = angle; bool penisDown = false; if (angle >= 120 && angle <= 250) penisDown = true; foreach (var p in bodyPartPenises) { if (penisDown) { p.SetCustomPose("PenisDown"); } else { p.SetCustomPose(null); } } } public void SetBreastJiggle(bool jiggle, int cooltime = 5) { //SetJiggle has cooltime if (Find.TickManager.TicksGame < bodyPartBreasts.lastPoseTick + cooltime) return; if (jiggle) { //may need to check apparels for aply pose //bodyPartBreasts.CheckCanPose("JiggleUp",) bodyPartBreasts.SetCustomPose("JiggleUp"); } else { //SetPoseFromPoseSet(null); bodyPartBreasts.SetCustomPose(null); } } string[] testPose = { null, "JiggleUp", "JiggleCenter" }; string[] testPose2 = { null, "PenisDown" }; public void UpdateTickAnim(Vector3 rootLoc, float angle) // call this in DrawPawnBody <- only called when it rendered { //do not calculate physics camera is far if (Find.CameraDriver.CurrentZoom >= CameraZoomRange.Furthest) return; //int IdTick = parent.thingIDNumber * 20; //hint from yayo animation mod if (!SizedApparelUtility.CanApplySizedApparel(pawn)) return; if (SizedApparelSettings.breastsPhysics || ForceUpdateTickAnimation)//SizedApparelSettings.autoJiggleBreasts { int tick; if (this.preTickCache != null) tick = Find.TickManager.TicksGame - this.preTickCache.Value; else tick = Find.TickManager.TicksGame; if (tick == 0) return; Vector3 velocity; if (this.prePositionCache != null) velocity = (rootLoc - this.prePositionCache.Value);// /tick else velocity = Vector3.zero; float rotation; if (this.preAngleCache != null) rotation = angle - this.preAngleCache.Value; else rotation = 0; float rotAcc = rotation - preRotation; //Log.Message(velocity.ToString() + " , " + preVelocity.ToString()); //UnityEngine's vector.normalize is safe for zero vector //(Vector3.Dot(velocity.normalized, preVelocity.normalized)) < 0.2f float dotV = Vector3.Dot(velocity.normalized, preVelocity.normalized); /* Log.Message(pawn.ToString()); Log.Message("rotAcc : " + rotAcc.ToString()); Log.Message("Velocity.x : " + velocity.x.ToString()); Log.Message("Velocity.z : " + velocity.z.ToString()); Log.Message("dotV : " + dotV.ToString()); */ if (dotV < 0.2f || Mathf.Abs(rotAcc) > 0.5) //(dotV == 0 ? 0:1), Mathf.Abs(dotV) // || Mathf.Abs(rotation) > 20 { //tickCache.Add("BreastsJiggleUp", Find.TickManager.TicksGame); SetBreastJiggle(true,10); } else { SetBreastJiggle(false,10); } this.prePositionCache = rootLoc; this.preAngleCache = angle; this.preRotation = rotation; this.preTickCache = Find.TickManager.TicksGame; this.preVelocity = velocity; } //SetPoseFromPoseSet(testPose2.RandomElement()); } public bool isApparelGraphicRecordChanged() { if (pawn == null) return false; var apparelGraphics = pawn.Drawer?.renderer?.graphics?.apparelGraphics; if (apparelGraphics == null) return false; //return false; //since 1.3 broken. force to return false; if (!apparelGraphics.SequenceEqual(cachedApparelGraphicRecord)) { if (SizedApparelSettings.Debug) Log.Message("[SizedApparel]:" + pawn + "'s apparel Record Changed! need to updating comp"); return true; } return false; } public void DrawAllBodyParts(Vector3 rootLoc, float angle, Rot4 facing, RotDrawMode bodyDrawType, PawnRenderFlags flags, Pawn ___pawn, Mesh bodyMesh) { if (this.isDrawAge && (!flags.FlagSet(PawnRenderFlags.Clothes) || !this.hasUnsupportedApparel || SizedApparelUtility.isPawnNaked(___pawn))) //TODO : Move it to CanDraw { if (bodyDrawType != RotDrawMode.Dessicated && SizedApparelSettings.drawVagina && SizedApparelUtility.CanDrawVagina(___pawn, flags)) { if (this.bodyPartVagina != null) this.bodyPartVagina.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh); /* //Draw Vagina. AllwaysDraw Vector3 vector = rootLoc; if (facing == Rot4.North) vector.y += 0.0100f;//not sure what to do else vector.y += 0.0088f; Graphic graphic = null; if (SizedApparelUtility.IsHorny(___pawn)) graphic = this.graphicVagina_horny; if (graphic == null) graphic = this.graphicVagina; if (graphic != null) { Material mat; if (!flags.FlagSet(PawnRenderFlags.Cache)) { graphic = graphic.GetColoredVersion(graphic.Shader, skinColor, skinColor2); mat = flags.FlagSet(PawnRenderFlags.Cache) ? graphic.MatAt(facing) : (Material)overrideMatMethod.Invoke(__instance, new object[] { graphic.MatAt(facing), ___pawn, flags.FlagSet(PawnRenderFlags.Portrait) }); GenDraw.DrawMeshNowOrLater(bodyMesh, vector, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); // draw for writeZ data to solve shadow issue } graphic = graphic.GetColoredVersion(shader, skinColor, skinColor2); vector.y += 0.00001f; mat = flags.FlagSet(PawnRenderFlags.Cache) ? graphic.MatAt(facing) : (Material)overrideMatMethod.Invoke(__instance, new object[] { graphic.MatAt(facing), ___pawn, flags.FlagSet(PawnRenderFlags.Portrait) }); GenDraw.DrawMeshNowOrLater(bodyMesh, vector, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); }*/ } if (bodyDrawType != RotDrawMode.Dessicated && SizedApparelSettings.drawAnus && SizedApparelUtility.CanDrawAnus(___pawn, flags)) { if (this.bodyPartAnus != null) this.bodyPartAnus.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh); /* //Draw Anus. //Allways draw Vector3 vector = rootLoc; if (facing == Rot4.North) vector.y += 0.0105f;//not sure what to do else vector.y += 0.0093f; Graphic graphic = null; if (SizedApparelUtility.IsHorny(___pawn)) graphic = this.graphicAnus_horny; if (graphic == null) graphic = this.graphicAnus; if (graphic != null) { Material mat; if (!flags.FlagSet(PawnRenderFlags.Cache)) { graphic = graphic.GetColoredVersion(graphic.Shader, skinColor, skinColor2); mat = flags.FlagSet(PawnRenderFlags.Cache) ? graphic.MatAt(facing) : (Material)overrideMatMethod.Invoke(__instance, new object[] { graphic.MatAt(facing), ___pawn, flags.FlagSet(PawnRenderFlags.Portrait) }); GenDraw.DrawMeshNowOrLater(bodyMesh, vector, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); // draw for writeZ data to solve shadow issue } graphic = graphic.GetColoredVersion(shader, skinColor, skinColor2); vector.y += 0.00001f; mat = flags.FlagSet(PawnRenderFlags.Cache) ? graphic.MatAt(facing) : (Material)overrideMatMethod.Invoke(__instance, new object[] { graphic.MatAt(facing), ___pawn, flags.FlagSet(PawnRenderFlags.Portrait) }); GenDraw.DrawMeshNowOrLater(bodyMesh, vector, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); }*/ } if (bodyDrawType != RotDrawMode.Dessicated && SizedApparelSettings.drawBelly && SizedApparelUtility.CanDrawBelly(___pawn, flags)) { if (this.bodyPartBelly != null) this.bodyPartBelly.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh); /* //Draw Belly. Need Complex Hiding Calculation Vector3 vector = rootLoc; if (facing == Rot4.North) vector.y += 0.0002f;//not sure what to do else vector.y += 0.0098f; Graphic graphic = this.graphicBelly; if (graphic != null) { Material mat; if (!flags.FlagSet(PawnRenderFlags.Cache)) { graphic = graphic.GetColoredVersion(graphic.Shader, skinColor, skinColor2); mat = flags.FlagSet(PawnRenderFlags.Cache) ? graphic.MatAt(facing) : (Material)overrideMatMethod.Invoke(__instance, new object[] { graphic.MatAt(facing), ___pawn, flags.FlagSet(PawnRenderFlags.Portrait) }); GenDraw.DrawMeshNowOrLater(bodyMesh, vector, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); // draw for writeZ data to solve shadow issue } graphic = graphic.GetColoredVersion(shader, skinColor, skinColor2); vector.y += 0.00001f; mat = flags.FlagSet(PawnRenderFlags.Cache) ? graphic.MatAt(facing) : (Material)overrideMatMethod.Invoke(__instance, new object[] { graphic.MatAt(facing), ___pawn, flags.FlagSet(PawnRenderFlags.Portrait) }); GenDraw.DrawMeshNowOrLater(bodyMesh, vector, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); }*/ } if (bodyDrawType != RotDrawMode.Dessicated && SizedApparelSettings.drawUdder && SizedApparelUtility.CanDrawUdder(___pawn, flags)) { if (this.bodyPartUdder != null) this.bodyPartUdder.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh); //Draw Udder. Need Complex Hiding Calculation -> /* Vector3 vector = rootLoc; if (facing == Rot4.North) vector.y += 0.0015f;//not sure what to do else vector.y += 0.0088f; Graphic graphic = null; if (SizedApparelUtility.IsHorny(___pawn)) graphic = this.graphicUdder_horny; if (graphic == null) graphic = this.graphicUdder; if (graphic != null) { Material mat; if (!flags.FlagSet(PawnRenderFlags.Cache)) { graphic = graphic.GetColoredVersion(graphic.Shader, skinColor, skinColor2); mat = flags.FlagSet(PawnRenderFlags.Cache) ? graphic.MatAt(facing) : (Material)overrideMatMethod.Invoke(__instance, new object[] { graphic.MatAt(facing), ___pawn, flags.FlagSet(PawnRenderFlags.Portrait) }); GenDraw.DrawMeshNowOrLater(bodyMesh, vector, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); // draw for writeZ data to solve shadow issue } graphic = graphic.GetColoredVersion(shader, skinColor, skinColor2); vector.y += 0.00001f; mat = flags.FlagSet(PawnRenderFlags.Cache) ? graphic.MatAt(facing) : (Material)overrideMatMethod.Invoke(__instance, new object[] { graphic.MatAt(facing), ___pawn, flags.FlagSet(PawnRenderFlags.Portrait) }); GenDraw.DrawMeshNowOrLater(bodyMesh, vector, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); }*/ } if (bodyDrawType != RotDrawMode.Dessicated && SizedApparelSettings.drawBreasts && SizedApparelUtility.CanDrawBreasts(___pawn, flags) && (SizedApparelSettings.drawSizedApparelBreastsOnlyWorn ? !SizedApparelUtility.isPawnNaked(___pawn, flags) : true)) { if (this.bodyPartBreasts != null) this.bodyPartBreasts.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh); //Log.Message("DrawBreasts for " + ___pawn.Name); //if (SizedApparelSettings.Debug) // Log.Message("trying to draw breasts"); //Draw Breasts. Allways draw /* Vector3 vector = rootLoc; if (facing == Rot4.North) vector.y += 0.001f;//not sure what to do else vector.y += 0.0113f; Graphic graphic = null; if (SizedApparelUtility.IsHorny(___pawn)) graphic = this.graphicBreasts_horny; if (graphic == null) graphic = this.graphicBreasts; if (graphic != null) { Material mat; if (!flags.FlagSet(PawnRenderFlags.Cache)) { graphic = graphic.GetColoredVersion(graphic.Shader, skinColor, skinColor2); mat = flags.FlagSet(PawnRenderFlags.Cache) ? graphic.MatAt(facing) : (Material)overrideMatMethod.Invoke(__instance, new object[] { graphic.MatAt(facing), ___pawn, flags.FlagSet(PawnRenderFlags.Portrait) }); GenDraw.DrawMeshNowOrLater(bodyMesh, vector, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); // draw for writeZ data to solve shadow issue } graphic = graphic.GetColoredVersion(shader, skinColor, skinColor2); vector.y += 0.00001f; mat = flags.FlagSet(PawnRenderFlags.Cache) ? graphic.MatAt(facing) : (Material)overrideMatMethod.Invoke(__instance, new object[] { graphic.MatAt(facing), ___pawn, flags.FlagSet(PawnRenderFlags.Portrait) }); GenDraw.DrawMeshNowOrLater(bodyMesh, vector, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); } else { //Log.Warning("[SizedApparel] Missing Breasts Graphic for: " + ___pawn.Name); } */ } if (bodyDrawType != RotDrawMode.Dessicated && SizedApparelSettings.drawPenis && SizedApparelUtility.CanDrawPenis(___pawn, flags, true)) { if (SizedApparelSettings.hideBallOfFuta ? !Genital_Helper.is_futa(___pawn) : true) { foreach (SizedApparelBodyPart b in this.bodyPartBalls) { b.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh); } } foreach (SizedApparelBodyPart p in this.bodyPartPenises) { p.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh); } /* //Render Penis And Balls Vector3 vector = rootLoc; if (facing == Rot4.North) vector.y += 0.0025f; else vector.y += 0.0108f; float offsetX = 0; // right and left float offsetZ = 0; // up and down if(this.graphicPenises != null && this.graphicBallsOfPenises != null) { for (int i = 0; i < this.graphicPenises.Count; i++) { float t = (i + 1f) / (this.graphicPenises.Count + 1); offsetX = Mathf.Lerp(-0.1f, 0.1f, t); offsetZ = Mathf.Lerp(-0.05f, 0.05f, t); Graphic penisGraphic = null; Graphic ballGraphic = null; if (SizedApparelUtility.IsHorny(___pawn)) { penisGraphic = this.graphicPenises_horny[i]; } if (penisGraphic == null) penisGraphic = this.graphicPenises[i]; ballGraphic = this.graphicBallsOfPenises[i];//Balls Doesn't support HornyVariation if (ballGraphic != null && (SizedApparelSettings.hideBallOfFuta ? Genital_Helper.is_futa(___pawn) : true)) { Material mat; //TODO: vector2.y Vector3 vector2 = vector; if (facing == Rot4.North) vector2.y += 0.0060f; else vector2.y -= 0.0012f; if (facing == Rot4.North || facing == Rot4.South) vector2.x += offsetX; else vector2.x += offsetX * 0.5f; if (facing == Rot4.East) vector2.z += offsetZ; if (facing == Rot4.West) vector2.z -= offsetZ; if (!flags.FlagSet(PawnRenderFlags.Cache)) { ballGraphic = ballGraphic.GetColoredVersion(ballGraphic.Shader, skinColor, skinColor2); mat = flags.FlagSet(PawnRenderFlags.Cache) ? ballGraphic.MatAt(facing) : (Material)overrideMatMethod.Invoke(__instance, new object[] { ballGraphic.MatAt(facing), ___pawn, flags.FlagSet(PawnRenderFlags.Portrait) }); GenDraw.DrawMeshNowOrLater(bodyMesh, vector2, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); // draw for writeZ data to solve shadow issue } ballGraphic = ballGraphic.GetColoredVersion(shader, skinColor, skinColor2); vector2.y += 0.00001f; mat = flags.FlagSet(PawnRenderFlags.Cache) ? ballGraphic.MatAt(facing) : (Material)overrideMatMethod.Invoke(__instance, new object[] { ballGraphic.MatAt(facing), ___pawn, flags.FlagSet(PawnRenderFlags.Portrait) }); GenDraw.DrawMeshNowOrLater(bodyMesh, vector2, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); } if (penisGraphic != null) { Material mat; Vector3 vector2 = vector; if (facing == Rot4.North || facing == Rot4.South) vector2.x += offsetX; else vector2.x += offsetX * 0.5f; if (facing == Rot4.East) vector2.z += offsetZ; if (facing == Rot4.West) vector2.z -= offsetZ; if (!flags.FlagSet(PawnRenderFlags.Cache)) { penisGraphic = penisGraphic.GetColoredVersion(penisGraphic.Shader, skinColor, skinColor2); mat = flags.FlagSet(PawnRenderFlags.Cache) ? penisGraphic.MatAt(facing) : (Material)overrideMatMethod.Invoke(__instance, new object[] { penisGraphic.MatAt(facing), ___pawn, flags.FlagSet(PawnRenderFlags.Portrait) }); GenDraw.DrawMeshNowOrLater(bodyMesh, vector2, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); // draw for writeZ data to solve shadow issue } penisGraphic = penisGraphic.GetColoredVersion(shader, skinColor, skinColor2); //TODO: vector2.y vector2.y += 0.00001f; mat = flags.FlagSet(PawnRenderFlags.Cache) ? penisGraphic.MatAt(facing) : (Material)overrideMatMethod.Invoke(__instance, new object[] { penisGraphic.MatAt(facing), ___pawn, flags.FlagSet(PawnRenderFlags.Portrait) }); GenDraw.DrawMeshNowOrLater(bodyMesh, vector2, quaternion, mat, flags.FlagSet(PawnRenderFlags.DrawNow)); } } }*/ }//Draw BodyParts //Draw Modular Apparel Parts if (flags.FlagSet(PawnRenderFlags.Clothes)) { } } } //not working public override void PostPostMake() { /* Pawn pawn; try { pawn = (Pawn)parent; if (pawn != null) { if (!pawn.RaceProps.Humanlike) return; pawn.Drawer.renderer.graphics.ResolveAllGraphics(); if (SizedApparelSettings.Debug) Log.Message("[SizedApparels] Component Inint And Resolve all Graphics for "+ pawn.Name); } } catch { } */ } public void ClearHediffs() { breastHediff = null; vaginaHediff = null; if(penisHediffs != null) penisHediffs.Clear(); anusHediff = null; udderHediff = null; } public void ClearBreastCacheValue() { breastHediff = null; breastSeverity = -1; breastSeverityCapToDraw = 1000; BreastSeverityCache = 0; } public void ClearPenisCacheValue() { //TODO } public void ClearCanDraw() { canDrawBreasts = false; canDrawPenis = false; canDrawTorsoParts = false; canDrawVaginaAndAnus = false; } public void ClearGraphics(bool clearBreasts = true) { //Since Injection of base body is now in Matarial. no need to keep graphicSourceNaked = null; graphicSourceFurCovered = null; graphicSourceRotten = null; hasGraphicUpdatedBefore = false; graphicbaseBodyNaked = null; graphicbaseBodyRotten = null; graphicbaseBodyFurCovered = null; //Clear BodyParts if(clearBreasts) bodyPartBreasts.Clear(); bodyPartAnus.Clear(); bodyPartBelly.Clear(); bodyPartVagina.Clear(); graphicBreasts = null; graphicVagina = null; graphicAnus = null; if (graphicPenises == null) graphicPenises = new List(); else graphicPenises.Clear(); if (graphicBallsOfPenises == null) graphicBallsOfPenises = new List(); else graphicBallsOfPenises.Clear(); graphicBelly = null; graphicUdder = null; graphicUdder_horny = null; graphicBreasts_horny = null; graphicVagina_horny = null; graphicAnus_horny = null; if (graphicPenises_horny == null) graphicPenises_horny = new List(); else graphicPenises_horny.Clear(); if (graphicBalls_horny == null) graphicBalls_horny = new List(); else graphicBalls_horny.Clear(); } public void ClearAll(bool clearGraphics = true) { ClearBreastCacheValue(); if(clearGraphics) ClearGraphics(); ClearHediffs(); ClearCanDraw(); hasUnsupportedApparel = false; hasUpdateBefore = false; hasUpdateBeforeSuccess = false; needToCheckApparelGraphicRecords = false; } public void SetDirty(bool clearPawnGraphicSet = false) { this.isDirty = true; if (clearPawnGraphicSet) { if (pawn == null) return; if (pawn.Drawer == null) return; if (pawn.Drawer.renderer == null) return; pawn.Drawer.renderer.graphics.ClearCache(); } } public void UpdateIfDirty() { } public void UpdateBodyGraphics() { } public void UpdateSettingData() { if (pawn == null) return; var loc_raceSetting = SizedApparelSettings.alienRaceSettings.FirstOrDefault((AlienRaceSetting s) => s.raceName == pawn.def.defName); if (raceSetting == null) return; raceSetting = loc_raceSetting; } public void CheckAgeChanged() { if (pawn == null) return; if (pawn.ageTracker == null) return; //TODO. Cleanup UpdateSettingData(); if (raceSetting == null) return; if (raceSetting.drawMinAge < 0 || pawn.ageTracker.AgeBiologicalYearsFloat >= raceSetting.drawMinAge) isDrawAge = true; else isDrawAge = false; } public void FindAndApplyBodyGraphic(Pawn pawn, Graphic sourceGraphic, ref Graphic targetGraphicBaseBody, ref Graphic cachedSourceGraphic, string debugName) { const string baseBodyString = "_BaseBody"; string baseBodyStringWithSex; if (SizedApparelSettings.useGenderSpecificTexture) { if (pawn.gender == Gender.Female) { baseBodyStringWithSex = baseBodyString + "F"; } else if (pawn.gender == Gender.Male) { baseBodyStringWithSex = baseBodyString + "M"; } else { baseBodyStringWithSex = baseBodyString; // + "N" //Does it need to add N? } } else baseBodyStringWithSex = baseBodyString; string targetGraphicPath = null; if (sourceGraphic != null) { //path = path.Insert(Math.Max(path.LastIndexOf('/'), 0), "/CustomPose/"+ customPose); if (cachedSourceGraphic == null) cachedSourceGraphic = sourceGraphic; targetGraphicPath = cachedSourceGraphic.path; if (customPose != null) targetGraphicPath = targetGraphicPath.Insert(Math.Max(targetGraphicPath.LastIndexOf('/'), 0), "/CustomPose/" + customPose); if (!targetGraphicPath.Contains(baseBodyString)) { if (SizedApparelSettings.useGenderSpecificTexture && pawn.gender != Gender.None) { if (targetGraphicBaseBody == null) { if (ContentFinder.Get((targetGraphicPath + baseBodyStringWithSex + "_south"), false) != null) { //cachedSourceGraphic = sourceGraphic; Shader shader = sourceGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; targetGraphicBaseBody = GraphicDatabase.Get(targetGraphicPath + baseBodyStringWithSex, shader, sourceGraphic.drawSize, sourceGraphic.color, sourceGraphic.colorTwo, sourceGraphic.data); //sourceGraphic = targetGraphicBaseBody; } else if (customPose != null) { targetGraphicPath = sourceGraphic.path; if (ContentFinder.Get((targetGraphicPath + baseBodyStringWithSex + "_south"), false) != null) { //cachedSourceGraphic = sourceGraphic; Shader shader = sourceGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; targetGraphicBaseBody = GraphicDatabase.Get(targetGraphicPath + baseBodyStringWithSex, shader, sourceGraphic.drawSize, sourceGraphic.color, sourceGraphic.colorTwo, sourceGraphic.data); //sourceGraphic = targetGraphicBaseBody; } else { if (SizedApparelSettings.Debug) Log.Warning("[SizedApparel] Missing BaseBodyTexture for "+ debugName + " Graphic: " + targetGraphicPath + baseBodyStringWithSex + "_south"); } } } } if (targetGraphicBaseBody == null) { if (ContentFinder.Get((targetGraphicPath + baseBodyString + "_south"), false) != null) { // cachedSourceGraphic = sourceGraphic; Shader shader = sourceGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; targetGraphicBaseBody = GraphicDatabase.Get(targetGraphicPath + baseBodyString, shader, sourceGraphic.drawSize, sourceGraphic.color, sourceGraphic.colorTwo, sourceGraphic.data); //sourceGraphic = targetGraphicBaseBody; } else if (customPose != null) { targetGraphicPath = sourceGraphic.path; if (ContentFinder.Get((targetGraphicPath + baseBodyString + "_south"), false) != null) { //cachedSourceGraphic = sourceGraphic; Shader shader = sourceGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; targetGraphicBaseBody = GraphicDatabase.Get(targetGraphicPath + baseBodyString, shader, sourceGraphic.drawSize, sourceGraphic.color, sourceGraphic.colorTwo, sourceGraphic.data); //sourceGraphic = targetGraphicBaseBody; } else { if (SizedApparelSettings.Debug) Log.Warning("[SizedApparel] Missing BaseBodyTexture for " + debugName + " Graphic: " + targetGraphicPath + baseBodyString + "_south"); } } } } else targetGraphicBaseBody = sourceGraphic; } } public void Update(bool cache = true, bool fromGraphicRecord = true, bool updateGraphics = true, bool CheckApparel = true) { if (cache) recentClothFlag = CheckApparel; isDirty = false; bool flag = fromGraphicRecord; needToCheckApparelGraphicRecords = false; //flag = false; //TODO:fromGraphicRecord is forced not to do for a while. it will update later hasUpdateBefore = true; if (!SizedApparelUtility.CanApplySizedApparel(pawn)) return; if (SizedApparelSettings.Debug) Log.Message("[SizedApparel] Updating Component of " + pawn.Name); if (updateGraphics) { ClearGraphics(); ClearHediffs(); } CheckAgeChanged(); SizedApparelUtility.GetBreastSeverity(pawn, out breastSeverity, out breastHediff); if (breastHediff != null) { if (pawn.gender == Gender.Male && !SizedApparelSettings.ApplyApparelPatchForMale) { CheckApparel = false; } BreastSeverityCache = 1000; if (CheckApparel) hasUnsupportedApparel = SizedApparelUtility.hasUnSupportedApparelFromWornData(pawn, breastSeverity, breastHediff, true, flag); else hasUnsupportedApparel = false; //float validBreastTextureSeverity = SizedApparelUtility.GetBreastSeverityValidTextures(pawn, breastHediff); if (hasUnsupportedApparel) BreastSeverityCache = breastSeverity; //float validBreastTextureSeverity = SizedApparelUtility.GetBreastSeverityValidTextures(pawn, breastHediff); //breast cache forApparel brests Check. This ignore variation! //SizedApparelMod.CheckAndLoadAlienRaces(); var key = new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, pawn.story?.bodyType?.defName, breastHediff.def.defName, "Breasts", pawn.gender ,SizedApparelUtility.BreastSeverityInt(breastHediff.Severity)); var raceSetting = SizedApparelSettings.alienRaceSettings.FirstOrDefault((AlienRaceSetting s) => s.raceName == key.raceName); float validBreastTextureSeverity = SizedApparelUtility.BreastSizeIndexToSeverity(SizedApparelsDatabase.GetSupportedBodyPartPath(key,true,"Breasts","Breasts").size); //if (validBreastTextureSeverity < -5 && SizedApparelSettings.alienRaceSettings.settings[key.raceName].asHumanlike)//old: SizedApparelSettings.UnsupportedRaceToUseHumanlike // validBreastTextureSeverity = SizedApparelUtility.GetBreastSeverityValidTextures(pawn, breastHediff, "Humanlike"); BreastSeverityCache = Math.Min(BreastSeverityCache, validBreastTextureSeverity); if (SizedApparelSettings.Debug) Log.Message("[Sized Apparel] cached Severity : " + BreastSeverityCache); } //penisHediff = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_genitalsBPR(pawn)).FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("penis")); //since rjw race support's part name are too variation, not handling it. BodyPartRecord genitalPart = Genital_Helper.get_genitalsBPR(pawn); if (genitalPart != null) { var genitalList = Genital_Helper.get_PartsHediffList(pawn, genitalPart); if (!genitalList.NullOrEmpty()) { if (SizedApparelSettings.Debug) { foreach (var g in genitalList) { Log.Message(" [SizedApparel] "+ pawn.Name + "has hediff in genital (" + g.def.defName + ")"); } } //penisHediffs = genitalList.FindAll((Hediff h) => SizedApparelUtility.isPenis(h.def.defName)); penisHediffs = genitalList.FindAll((Hediff h) => Genital_Helper.is_penis(h)); //vaginaHediff = genitalList.FirstOrDefault((Hediff h) => SizedApparelUtility.isVagina(h.def.defName)); vaginaHediff = genitalList.FirstOrDefault((Hediff h) => Genital_Helper.is_vagina(h)); } } var anusList = Genital_Helper.get_PartsHediffList(pawn, Genital_Helper.get_anusBPR(pawn)); if(!anusList.NullOrEmpty()) anusHediff = anusList.FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("anus")); //udderHediff = Genital_Helper.get_PartsHediffList(pawn, pawn.RaceProps.body.AllParts.Find((BodyPartRecord bpr) => bpr.def.defName == "Torso")).FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("anus")); //not yet supported udderHediff = pawn.health?.hediffSet?.hediffs?.FirstOrDefault((Hediff h) => h.def.defName.ToLower().Contains("udder")); var pawnRenderer = pawn.Drawer?.renderer?.graphics; if (updateGraphics) { if (pawnRenderer != null) { //pawnRenderer.ResolveAllGraphics(); //TODO Use Function To Make Clear Code /* FindAndApplyBodyGraphic(pawn, pawnRenderer.nakedGraphic, ref graphicbaseBodyNaked, ref graphicSourceNaked,"Naked"); FindAndApplyBodyGraphic(pawn, pawnRenderer.rottingGraphic, ref graphicbaseBodyRotten, ref graphicSourceRotten, "Rotting"); FindAndApplyBodyGraphic(pawn, pawnRenderer.nakedGraphic, ref graphicbaseBodyFurCovered, ref graphicSourceFurCovered, "FurCuvered"); */ const string baseBodyString = "_BaseBody"; string baseBodyStringWithSex; if (SizedApparelSettings.useGenderSpecificTexture) { if (pawn.gender == Gender.Female) { baseBodyStringWithSex = baseBodyString + "F"; } else if (pawn.gender == Gender.Male) { baseBodyStringWithSex = baseBodyString + "M"; } else { baseBodyStringWithSex = baseBodyString; // + "N" //Does it need to add N? } } else baseBodyStringWithSex = baseBodyString; string nakedGraphicPath = null; if (pawnRenderer.nakedGraphic != null) { //path = path.Insert(Math.Max(path.LastIndexOf('/'), 0), "/CustomPose/"+ customPose); if(graphicSourceNaked == null) graphicSourceNaked = pawnRenderer.nakedGraphic; nakedGraphicPath = graphicSourceNaked.path; if (customPose != null) nakedGraphicPath = nakedGraphicPath.Insert(Math.Max(nakedGraphicPath.LastIndexOf('/'), 0), "/CustomPose/" + customPose); if (!nakedGraphicPath.Contains(baseBodyString)) { if (SizedApparelSettings.useGenderSpecificTexture & pawn.gender != Gender.None) { if (graphicbaseBodyNaked == null) { if (ContentFinder.Get((nakedGraphicPath + baseBodyStringWithSex + "_south"), false) != null) { //graphicSourceNaked = pawnRenderer.nakedGraphic; Shader shader = pawnRenderer.nakedGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; graphicbaseBodyNaked = GraphicDatabase.Get(nakedGraphicPath + baseBodyStringWithSex, shader, pawnRenderer.nakedGraphic.drawSize, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo, pawnRenderer.nakedGraphic.data); //pawnRenderer.nakedGraphic = graphicbaseBodyNaked; } else if (customPose != null) { nakedGraphicPath = pawnRenderer.nakedGraphic.path; if (ContentFinder.Get((nakedGraphicPath + baseBodyStringWithSex + "_south"), false) != null) { //graphicSourceNaked = pawnRenderer.nakedGraphic; Shader shader = pawnRenderer.nakedGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; graphicbaseBodyNaked = GraphicDatabase.Get(nakedGraphicPath + baseBodyStringWithSex, shader, pawnRenderer.nakedGraphic.drawSize, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo, pawnRenderer.nakedGraphic.data); //pawnRenderer.nakedGraphic = graphicbaseBodyNaked; } else { if (SizedApparelSettings.Debug) Log.Warning("[SizedApparel] Missing BaseBodyTexture for naked Graphic: " + nakedGraphicPath + baseBodyStringWithSex + "_south"); } } } } if (graphicbaseBodyNaked == null) { if (ContentFinder.Get((nakedGraphicPath + baseBodyString + "_south"), false) != null) { // graphicSourceNaked = pawnRenderer.nakedGraphic; Shader shader = pawnRenderer.nakedGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; graphicbaseBodyNaked = GraphicDatabase.Get(nakedGraphicPath + baseBodyString, shader, pawnRenderer.nakedGraphic.drawSize, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo, pawnRenderer.nakedGraphic.data); //pawnRenderer.nakedGraphic = graphicbaseBodyNaked; } else if (customPose != null) { nakedGraphicPath = pawnRenderer.nakedGraphic.path; if (ContentFinder.Get((nakedGraphicPath + baseBodyString + "_south"), false) != null) { //graphicSourceNaked = pawnRenderer.nakedGraphic; Shader shader = pawnRenderer.nakedGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; graphicbaseBodyNaked = GraphicDatabase.Get(nakedGraphicPath + baseBodyString, shader, pawnRenderer.nakedGraphic.drawSize, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo, pawnRenderer.nakedGraphic.data); //pawnRenderer.nakedGraphic = graphicbaseBodyNaked; } else { if (SizedApparelSettings.Debug) Log.Warning("[SizedApparel] Missing BaseBodyTexture for naked Graphic: " + nakedGraphicPath + baseBodyString + "_south"); } } } } else graphicbaseBodyNaked = pawnRenderer.nakedGraphic; } string rottingGraphicPath = null; if (pawnRenderer.rottingGraphic != null) { if (graphicSourceRotten == null) graphicSourceRotten = pawnRenderer.rottingGraphic; rottingGraphicPath = graphicSourceRotten.path; if (customPose != null) rottingGraphicPath = rottingGraphicPath.Insert(Math.Max(rottingGraphicPath.LastIndexOf('/'), 0), "/CustomPose/" + customPose); if (!rottingGraphicPath.Contains(baseBodyString)) { if (graphicbaseBodyRotten == null) { if (ContentFinder.Get((rottingGraphicPath + baseBodyStringWithSex + "_south"), false) != null) { //graphicSourceRotten = pawnRenderer.rottingGraphic; Shader shader = pawnRenderer.rottingGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; graphicbaseBodyRotten = GraphicDatabase.Get(rottingGraphicPath + baseBodyStringWithSex, shader, pawnRenderer.rottingGraphic.drawSize, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo, pawnRenderer.rottingGraphic.data); //pawnRenderer.rottingGraphic = graphicbaseBodyRotten; } else if (customPose != null) { rottingGraphicPath = pawnRenderer.rottingGraphic.path; if (ContentFinder.Get((rottingGraphicPath + baseBodyStringWithSex + "_south"), false) != null) { graphicSourceRotten = pawnRenderer.rottingGraphic; Shader shader = pawnRenderer.rottingGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; graphicbaseBodyRotten = GraphicDatabase.Get(rottingGraphicPath + baseBodyStringWithSex, shader, pawnRenderer.rottingGraphic.drawSize, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo, pawnRenderer.rottingGraphic.data); //pawnRenderer.rottingGraphic = graphicbaseBodyRotten; } else { if (SizedApparelSettings.Debug) Log.Warning("[SizedApparel] Missing BaseBodyTexture for rotting Graphic: " + rottingGraphicPath + baseBodyStringWithSex + "_south"); } } if (graphicbaseBodyRotten == null) { if (ContentFinder.Get((rottingGraphicPath + baseBodyString + "_south"), false) != null) { //graphicSourceRotten = pawnRenderer.rottingGraphic; Shader shader = pawnRenderer.rottingGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; graphicbaseBodyRotten = GraphicDatabase.Get(rottingGraphicPath + baseBodyString, shader, pawnRenderer.rottingGraphic.drawSize, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo, pawnRenderer.rottingGraphic.data); //pawnRenderer.rottingGraphic = graphicbaseBodyRotten; } else if (customPose != null) { rottingGraphicPath = pawnRenderer.rottingGraphic.path; if (ContentFinder.Get((rottingGraphicPath + baseBodyString + "_south"), false) != null) { graphicSourceRotten = pawnRenderer.rottingGraphic; Shader shader = pawnRenderer.rottingGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; graphicbaseBodyRotten = GraphicDatabase.Get(rottingGraphicPath + baseBodyString, shader, pawnRenderer.rottingGraphic.drawSize, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo, pawnRenderer.rottingGraphic.data); //pawnRenderer.rottingGraphic = graphicbaseBodyRotten; } else { if (SizedApparelSettings.Debug) Log.Warning("[SizedApparel] Missing BaseBodyTexture for rotting Graphic: " + rottingGraphicPath + baseBodyString + "_south"); } } } } } else graphicbaseBodyRotten = pawnRenderer.rottingGraphic; } string furCoveredGraphicPath = null; if (pawnRenderer.furCoveredGraphic != null) { if (graphicSourceFurCovered == null) graphicSourceFurCovered = pawnRenderer.furCoveredGraphic; furCoveredGraphicPath = graphicSourceFurCovered.path; if (customPose != null) furCoveredGraphicPath = furCoveredGraphicPath.Insert(Math.Max(furCoveredGraphicPath.LastIndexOf('/'), 0), "/CustomPose/" + customPose); if (!furCoveredGraphicPath.Contains(baseBodyString)) { if (graphicbaseBodyFurCovered == null) { if (ContentFinder.Get((furCoveredGraphicPath + baseBodyStringWithSex + "_south"), false) != null) { Shader shader = pawnRenderer.furCoveredGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; graphicbaseBodyFurCovered = GraphicDatabase.Get(furCoveredGraphicPath + baseBodyStringWithSex, shader, pawnRenderer.furCoveredGraphic.drawSize, pawnRenderer.furCoveredGraphic.color, pawnRenderer.furCoveredGraphic.colorTwo, pawnRenderer.furCoveredGraphic.data); } else if (customPose != null) { furCoveredGraphicPath = pawnRenderer.furCoveredGraphic.path; if (ContentFinder.Get((furCoveredGraphicPath + baseBodyStringWithSex + "_south"), false) != null) { graphicSourceFurCovered = pawnRenderer.furCoveredGraphic; Shader shader = pawnRenderer.furCoveredGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; graphicbaseBodyFurCovered = GraphicDatabase.Get(furCoveredGraphicPath + baseBodyStringWithSex, shader, pawnRenderer.furCoveredGraphic.drawSize, pawnRenderer.furCoveredGraphic.color, pawnRenderer.furCoveredGraphic.colorTwo, pawnRenderer.furCoveredGraphic.data); } else { if (SizedApparelSettings.Debug) Log.Warning("[SizedApparel] Missing BaseBodyTexture for furCovered Graphic: " + furCoveredGraphicPath + baseBodyStringWithSex + "_south"); } } if (graphicbaseBodyFurCovered == null) { if (ContentFinder.Get((furCoveredGraphicPath + baseBodyString + "_south"), false) != null) { Shader shader = pawnRenderer.furCoveredGraphic.Shader; //if (!ShaderUtility.SupportsMaskTex(shader)) // shader = ShaderDatabase.CutoutSkinOverlay; graphicbaseBodyFurCovered = GraphicDatabase.Get(furCoveredGraphicPath + baseBodyString, shader, pawnRenderer.furCoveredGraphic.drawSize, pawnRenderer.furCoveredGraphic.color, pawnRenderer.furCoveredGraphic.colorTwo, pawnRenderer.furCoveredGraphic.data); } else if (customPose != null) { furCoveredGraphicPath = pawnRenderer.furCoveredGraphic.path; if (ContentFinder.Get((furCoveredGraphicPath + baseBodyString + "_south"), false) != null) { graphicSourceFurCovered = pawnRenderer.furCoveredGraphic; Shader shader = pawnRenderer.furCoveredGraphic.Shader; graphicbaseBodyFurCovered = GraphicDatabase.Get(furCoveredGraphicPath + baseBodyString, shader, pawnRenderer.furCoveredGraphic.drawSize, pawnRenderer.furCoveredGraphic.color, pawnRenderer.furCoveredGraphic.colorTwo, pawnRenderer.furCoveredGraphic.data); } else { if (SizedApparelSettings.Debug) Log.Warning("[SizedApparel] Missing BaseBodyTexture for naked Graphic: " + furCoveredGraphicPath + baseBodyString + "_south"); } } } } } else graphicbaseBodyFurCovered = pawnRenderer.furCoveredGraphic; } /* //Try to find sized Body if it's valid int offset = 9999; int currentBreastSizeIndex = 0; float currentBreastSeverity = 0; bool validNakedTexture = false; bool validRottingTexture = false; Graphic nakedGraphic; Graphic rottingGraphic; while (offset < SizedApparelUtility.size.Length) { string breastSeverityStringCache = SizedApparelUtility.BreastSeverityString(breastSeverity, offset, true, ref currentBreastSizeIndex, ref currentBreastSeverity); //search bigger //SizedApparelSettings.matchBodyTextureToMinimumApparelSize? currentBreastSizeIndex <= minSupportedBreasSizeIndex:true if (validNakedTexture == false && nakedGraphicPath !=null) { if ((ContentFinder.Get((nakedGraphicPath + breastSeverityStringCache + "_south"), false) != null)) { if (SizedApparelSettings.matchBodyTextureToMinimumApparelSize ? SizedApparelUtility.BreastSizeIndexToSeverity(currentBreastSizeIndex) <= breastSeverityCapToDraw : true) { nakedGraphic = GraphicDatabase.Get(nakedGraphicPath + breastSeverityStringCache, pawnRenderer.nakedGraphic.Shader, pawnRenderer.nakedGraphic.drawSize, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo, pawnRenderer.nakedGraphic.data); //newAgr.Add(new ApparelGraphicRecord(graphic, agr.sourceApparel)); //validTexture = true; //Log.Message(path + BreastSeverityString(BreastSeverity, offset, !findBigger) + ":Texture Found"); pawnRenderer.nakedGraphic = nakedGraphic; validNakedTexture = true; } } } if (validRottingTexture == false && rottingGraphicPath != null) { if ((ContentFinder.Get((rottingGraphicPath + breastSeverityStringCache + "_south"), false) != null)) { if (SizedApparelSettings.matchBodyTextureToMinimumApparelSize ? SizedApparelUtility.BreastSizeIndexToSeverity(currentBreastSizeIndex) <= breastSeverityCapToDraw : true) { rottingGraphic = GraphicDatabase.Get(rottingGraphicPath + breastSeverityStringCache, pawnRenderer.rottingGraphic.Shader, pawnRenderer.rottingGraphic.drawSize, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo, pawnRenderer.rottingGraphic.data); //newAgr.Add(new ApparelGraphicRecord(graphic, agr.sourceApparel)); //validTexture = true; //Log.Message(path + BreastSeverityString(BreastSeverity, offset, !findBigger) + ":Texture Found"); pawnRenderer.rottingGraphic = rottingGraphic; validRottingTexture = true; } } } //search smaller breastSeverityStringCache = SizedApparelUtility.BreastSeverityString(breastSeverity, offset, false, ref currentBreastSizeIndex, ref currentBreastSeverity); if (validNakedTexture == false) { if ((ContentFinder.Get((nakedGraphicPath + breastSeverityStringCache + "_south"), false) != null)) { if (SizedApparelSettings.matchBodyTextureToMinimumApparelSize ? SizedApparelUtility.BreastSizeIndexToSeverity(currentBreastSizeIndex) <= breastSeverityCapToDraw : true) { nakedGraphic = GraphicDatabase.Get(nakedGraphicPath + breastSeverityStringCache, pawnRenderer.nakedGraphic.Shader, pawnRenderer.nakedGraphic.drawSize, pawnRenderer.nakedGraphic.color, pawnRenderer.nakedGraphic.colorTwo, pawnRenderer.nakedGraphic.data); //newAgr.Add(new ApparelGraphicRecord(graphic, agr.sourceApparel)); //validTexture = true; //Log.Message(path + BreastSeverityString(BreastSeverity, offset, !findBigger) + ":Texture Found"); pawnRenderer.nakedGraphic = nakedGraphic; validNakedTexture = true; } } } if (validRottingTexture == false) { if ((ContentFinder.Get((rottingGraphicPath + breastSeverityStringCache + "_south"), false) != null)) { if (SizedApparelSettings.matchBodyTextureToMinimumApparelSize ? SizedApparelUtility.BreastSizeIndexToSeverity(currentBreastSizeIndex) <= breastSeverityCapToDraw : true) { rottingGraphic = GraphicDatabase.Get(rottingGraphicPath + breastSeverityStringCache, pawnRenderer.rottingGraphic.Shader, pawnRenderer.rottingGraphic.drawSize, pawnRenderer.rottingGraphic.color, pawnRenderer.rottingGraphic.colorTwo, pawnRenderer.rottingGraphic.data); //newAgr.Add(new ApparelGraphicRecord(graphic, agr.sourceApparel)); //validTexture = true; //Log.Message(path + BreastSeverityString(BreastSeverity, offset, !findBigger) + ":Texture Found"); pawnRenderer.rottingGraphic = rottingGraphic; validRottingTexture = true; } } } if (validNakedTexture == true && validRottingTexture == true) { if (SizedApparelSettings.Debug) Log.Message("[Sized Apparel] " + pawn.Name + "'s body texture has changed."); break; } offset++; } */ } //graphicBreasts = SizedApparelUtility.GetBodyPartGraphic(pawn, breastHediff, true, "Breasts", "Breasts"); //if(graphicBreasts == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) // graphicBreasts = SizedApparelUtility.GetBodyPartGraphic(pawn, breastHediff, true, "Breasts", "Breasts", false, true, "Humanlike"); if (SizedApparelSettings.drawBodyParts)//body parts update { string bodyPartPath = null; SizedApparelsDatabase.PathAndSize cachedPathAndSize; if (SizedApparelSettings.drawBreasts) { float breastSeverityCapped = breastSeverity; if (SizedApparelSettings.useBreastSizeCapForApparels) //SizedApparelSettings.useBreastSizeCapForApparels //wip breastSeverityCapped = Math.Min(BreastSeverityCache, breastSeverityCapped); string bodyTypeDefName = null; if (pawn.story != null) bodyTypeDefName = pawn.story.bodyType?.defName; if (breastHediff != null) { var breastvar = breastHediff.TryGetComp(); bodyPartBreasts.SetHediffData(breastHediff.def.defName, SizedApparelUtility.BreastSeverityInt(breastHediff.Severity), SizedApparelUtility.BreastSeverityInt(breastSeverityCapped), breastvar?.variation); bodyPartBreasts.UpdateGraphic(); } } if (SizedApparelSettings.drawUdder) { if (udderHediff != null) { var udderVar = udderHediff.TryGetComp(); bodyPartUdder.SetHediffData(udderHediff.def.defName, SizedApparelUtility.BreastSeverityInt(udderHediff.Severity), 1000, udderVar?.variation); bodyPartUdder.UpdateGraphic(); } else bodyPartUdder.SetHediffData(null, -1); } if (SizedApparelSettings.drawBelly) { float bellySeverity = 0; List pregnancies = pawn.health?.hediffSet?.hediffs?.FindAll((Hediff h) => h.def.defName.ToLower().Contains("pregnan"));//pregnancy and pregnant if (!pregnancies.NullOrEmpty()) { foreach (Hediff h in pregnancies) { bellySeverity = Math.Max(bellySeverity, h.Severity); } } /* List eggs = pawn.health?.hediffSet?.hediffs?.FindAll((Hediff h) => h.def.defName.ToLower().Contains("rjw") && h.def.defName.ToLower().Contains("egg")); if (!eggs.NullOrEmpty()) { foreach (Hediff h in eggs) { bellySeverity = Math.Max(bellySeverity, h.Severity); } } List mech = pawn.health?.hediffSet?.hediffs?.FindAll((Hediff h) => h.def.defName.ToLower().Contains("rjw") && h.def.defName.ToLower().Contains("mech")); if (!mech.NullOrEmpty()) { foreach (Hediff h in mech) { bellySeverity = Math.Max(bellySeverity, h.Severity); } } List parasite = pawn.health?.hediffSet?.hediffs?.FindAll((Hediff h) => h.def.defName.ToLower().Contains("parasite")); if (!parasite.NullOrEmpty()) { foreach (Hediff h in parasite) { bellySeverity = Math.Max(bellySeverity, h.Severity); } }*/ //Licentia Lab Hediff if (SizedApparelPatch.LicentiaActive) { Hediff cumflation = pawn.health?.hediffSet?.GetFirstHediffOfDef(HediffDef.Named("Cumflation")); Hediff cumstuffed = pawn.health?.hediffSet?.GetFirstHediffOfDef(HediffDef.Named("Cumstuffed")); bellySeverity += cumflation != null ? cumflation.Severity : 0; bellySeverity += cumstuffed != null ? cumstuffed.Severity : 0; } if (bellySeverity >= 0) { //var bellyVar = breastHediff.GetComp(); string BellyVar = null; bodyPartBelly.SetHediffData("BellyBulge", SizedApparelUtility.PrivatePartSeverityInt(bellySeverity), 1000, BellyVar); bodyPartBelly.UpdateGraphic(); /* bodyPartPath = null; cachedPathAndSize = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, bodyTypeDefName, "BellyBulge", "Belly", SizedApparelUtility.PrivatePartSeverityInt(bellySeverity), false), false, "Belly", "BellyBulge"); bodyPartPath = cachedPathAndSize.pathWithSizeIndex; if (bodyPartPath != null) { if (cachedPathAndSize.isUnsupportedHumanlikePath) { if (SizedApparelSettings.UnsupportedRaceToUseHumanlike && pawn.RaceProps.Humanlike) graphicBelly = GraphicDatabase.Get(bodyPartPath); } else graphicBelly = GraphicDatabase.Get(bodyPartPath); }*/ //if (graphicVagina_horny == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) //{ // bodyPartPath = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, pawn.story?.bodyType.defName, vaginaHediff.def.defName, "Vagina", SizedApparelUtility.PrivatePartSeverityInt(vaginaHediff.Severity), true), false, "Vagina", "Vagina", "Humanlike").pathWithSizeIndex; // if (bodyPartPath != null) // graphicVagina_horny = GraphicDatabase.Get(bodyPartPath); //} } } if (SizedApparelSettings.drawVagina) { //graphicVagina = SizedApparelUtility.GetBodyPartGraphic(pawn, vaginaHediff, false, "Vagina", "Vagina"); //if(graphicVagina == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) // graphicVagina = SizedApparelUtility.GetBodyPartGraphic(pawn, vaginaHediff, false, "Vagina", "Vagina", false, true,"Humanlike"); if (vaginaHediff != null) { var vaginaVar = vaginaHediff.TryGetComp(); bodyPartVagina.SetHediffData(vaginaHediff.def.defName, SizedApparelUtility.PrivatePartSeverityInt(vaginaHediff.Severity), 1000, vaginaVar?.variation); bodyPartVagina.UpdateGraphic(); /* bodyPartPath = null; cachedPathAndSize = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, bodyTypeDefName, vaginaHediff.def.defName, "Vagina", SizedApparelUtility.PrivatePartSeverityInt(vaginaHediff.Severity), false), false, "Vagina", "Vagina"); bodyPartPath = cachedPathAndSize.pathWithSizeIndex; if (bodyPartPath != null) { if (cachedPathAndSize.isUnsupportedHumanlikePath) { if (SizedApparelSettings.UnsupportedRaceToUseHumanlike && pawn.RaceProps.Humanlike) graphicVagina = GraphicDatabase.Get(bodyPartPath); } else graphicVagina = GraphicDatabase.Get(bodyPartPath); } bodyPartPath = null; cachedPathAndSize = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, bodyTypeDefName, vaginaHediff.def.defName, "Vagina", SizedApparelUtility.PrivatePartSeverityInt(vaginaHediff.Severity), true), false, "Vagina", "Vagina"); bodyPartPath = cachedPathAndSize.pathWithSizeIndex; if (bodyPartPath != null) { if (cachedPathAndSize.isUnsupportedHumanlikePath) { if (SizedApparelSettings.UnsupportedRaceToUseHumanlike && pawn.RaceProps.Humanlike) graphicVagina_horny = GraphicDatabase.Get(bodyPartPath); } else graphicVagina_horny = GraphicDatabase.Get(bodyPartPath); }*/ //if (graphicVagina_horny == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) //{ // bodyPartPath = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, pawn.story?.bodyType.defName, vaginaHediff.def.defName, "Vagina", SizedApparelUtility.PrivatePartSeverityInt(vaginaHediff.Severity), true), false, "Vagina", "Vagina", "Humanlike").pathWithSizeIndex; // if (bodyPartPath != null) // graphicVagina_horny = GraphicDatabase.Get(bodyPartPath); //} } else bodyPartVagina.SetHediffData(null, -1); } //graphicVagina_horny = SizedApparelUtility.GetBodyPartGraphic(pawn, vaginaHediff, false, "Vagina", "Vagina", true); //if(graphicVagina_horny == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) // graphicVagina_horny = SizedApparelUtility.GetBodyPartGraphic(pawn, vaginaHediff, false, "Vagina", "Vagina", true, true, "Humanlike"); /* graphicPenises.Clear(); graphicPenises_horny.Clear(); graphicBallsOfPenises.Clear(); */ if (SizedApparelSettings.drawPenis) { //TODO: Optimize bodyPartPenises.Clear(); bodyPartBalls.Clear(); if (penisHediffs != null) { for (int i = 0; i < penisHediffs.Count; i++) { Hediff penisHediff = penisHediffs[i]; float offsetX = 0; // right and left float offsetZ = 0; // up and down float t = (i + 1f) / (penisHediffs.Count + 1); offsetX = Mathf.Lerp(-0.05f, 0.05f, t); offsetZ = Mathf.Lerp(-0.02f, 0.02f, t); if (penisHediff == null) continue; var penisVar = penisHediff.TryGetComp(); SizedApparelBodyPart penis = new SizedApparelBodyPart(pawn, this, "Penis", SizedApparelBodyPartOf.Penis, "Penis", false, false); penis.SetDepthOffsets(0.0108f, 0.0025f, 0.0108f, 0.0108f); penis.SetPositionOffsets(new Vector2(offsetX, 0), new Vector2(-offsetX, 0), new Vector2(offsetX, offsetZ), new Vector2(offsetX, -offsetZ)); penis.SetHediffData(penisHediff.def.defName, SizedApparelUtility.PrivatePartSeverityInt(penisHediff.Severity), 1000, penisVar?.variation); penis.UpdateGraphic(); bodyPartPenises.Add(penis); SizedApparelBodyPart balls = new SizedApparelBodyPart(pawn, this, "Balls", SizedApparelBodyPartOf.Penis, "Penis", false, false, "Penis/Balls"); balls.SetDepthOffsets(0.0096f, 0.0085f, 0.0096f, 0.0096f); balls.SetPositionOffsets(new Vector2(offsetX, 0), new Vector2(-offsetX, 0), new Vector2(offsetX, offsetZ), new Vector2(offsetX, -offsetZ)); balls.SetHediffData(penisHediff.def.defName, SizedApparelUtility.PrivatePartSeverityInt(penisHediff.Severity), 1000, penisVar?.variation); balls.UpdateGraphic(); bodyPartBalls.Add(balls); /* Graphic penisGraphic = SizedApparelUtility.GetBodyPartGraphic(pawn, penisHediff, false, "Penis", "Penis"); if (penisGraphic == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) penisGraphic = SizedApparelUtility.GetBodyPartGraphic(pawn, penisHediff, false, "Penis", "Penis", false, true, "Humanlike"); Graphic penisGraphicHorny = SizedApparelUtility.GetBodyPartGraphic(pawn, penisHediff, false, "Penis", "Penis", true); if (penisGraphicHorny == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) penisGraphicHorny = SizedApparelUtility.GetBodyPartGraphic(pawn, penisHediff, false, "Penis", "Penis", true, true, "Humanlike"); */ /* Graphic penisGraphic = null; bodyPartPath = null; cachedPathAndSize = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, bodyTypeDefName, penisHediff.def.defName, "Penis", SizedApparelUtility.PrivatePartSeverityInt(penisHediff.Severity), false), false, "Penis", "Penis"); bodyPartPath = cachedPathAndSize.pathWithSizeIndex; if (bodyPartPath != null) { if (cachedPathAndSize.isUnsupportedHumanlikePath) { if (SizedApparelSettings.UnsupportedRaceToUseHumanlike && pawn.RaceProps.Humanlike) penisGraphic = GraphicDatabase.Get(bodyPartPath); } else penisGraphic = GraphicDatabase.Get(bodyPartPath); } //if (penisGraphic == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) //{ // bodyPartPath = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, pawn.story?.bodyType.defName, penisHediff.def.defName, "Penis", SizedApparelUtility.PrivatePartSeverityInt(penisHediff.Severity), false), false, "Penis", "Penis", "Humanlike").pathWithSizeIndex; // if (bodyPartPath != null) // penisGraphic = GraphicDatabase.Get(bodyPartPath); //} Graphic penisGraphicHorny = null; bodyPartPath = null; cachedPathAndSize = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, bodyTypeDefName, penisHediff.def.defName, "Penis", SizedApparelUtility.PrivatePartSeverityInt(penisHediff.Severity), true), false, "Penis", "Penis"); bodyPartPath = cachedPathAndSize.pathWithSizeIndex; if (bodyPartPath != null) { if (cachedPathAndSize.isUnsupportedHumanlikePath) { if (SizedApparelSettings.UnsupportedRaceToUseHumanlike && pawn.RaceProps.Humanlike) penisGraphicHorny = GraphicDatabase.Get(bodyPartPath); } else penisGraphicHorny = GraphicDatabase.Get(bodyPartPath); } //if (penisGraphicHorny == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) //{ // bodyPartPath = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, pawn.story?.bodyType.defName, penisHediff.def.defName, "Penis", SizedApparelUtility.PrivatePartSeverityInt(penisHediff.Severity), true), false, "Penis", "Penis", "Humanlike").pathWithSizeIndex; // if (bodyPartPath != null) // penisGraphicHorny = GraphicDatabase.Get(bodyPartPath); //} //balls are no need horny graphic. it wiil share sametime //Graphic ballGraphic = SizedApparelUtility.GetBodyPartGraphic(pawn, penisHediff, false, "Penis/Balls", "Penis", false); //if (ballGraphic == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) // ballGraphic = SizedApparelUtility.GetBodyPartGraphic(pawn, penisHediff, false, "Penis/Balls", "Penis", false, true, "Humanlike"); Graphic ballGraphic = null; bodyPartPath = null; cachedPathAndSize = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, bodyTypeDefName, "Penis/Balls", penisHediff.def.defName, SizedApparelUtility.PrivatePartSeverityInt(penisHediff.Severity), false), false, "Penis/Balls", "Penis"); bodyPartPath = cachedPathAndSize.pathWithSizeIndex; if (bodyPartPath != null) { if (cachedPathAndSize.isUnsupportedHumanlikePath) { if (SizedApparelSettings.UnsupportedRaceToUseHumanlike && pawn.RaceProps.Humanlike) ballGraphic = GraphicDatabase.Get(bodyPartPath); } else ballGraphic = GraphicDatabase.Get(bodyPartPath); } //if (ballGraphic == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) //{ // bodyPartPath = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, pawn.story?.bodyType.defName, "Penis/Balls", penisHediff.def.defName, SizedApparelUtility.PrivatePartSeverityInt(penisHediff.Severity), false), false, "Penis/Balls", "Penis", "Humanlike").pathWithSizeIndex; // if (bodyPartPath != null) // ballGraphic = GraphicDatabase.Get(bodyPartPath); //} if (true)//penisGraphic != null { graphicPenises.Add(penisGraphic); graphicPenises_horny.Add(penisGraphicHorny); graphicBallsOfPenises.Add(ballGraphic); } */ } } } else { bodyPartPenises.Clear(); bodyPartBalls.Clear(); } if (SizedApparelSettings.drawAnus) { /* graphicAnus = SizedApparelUtility.GetBodyPartGraphic(pawn, anusHediff, false, "Anus", "Anus"); if (graphicAnus == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) graphicAnus = SizedApparelUtility.GetBodyPartGraphic(pawn, anusHediff, false, "Anus", "Anus", false, true, "Humanlike"); graphicAnus_horny = SizedApparelUtility.GetBodyPartGraphic(pawn, anusHediff, false, "Anus", "Anus", true); if (graphicAnus_horny == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) graphicAnus_horny = SizedApparelUtility.GetBodyPartGraphic(pawn, anusHediff, false, "Anus", "Anus", true, true, "Humanlike"); */ if (anusHediff != null) { var anusVar = anusHediff.TryGetComp(); bodyPartAnus.SetHediffData(anusHediff.def.defName, SizedApparelUtility.PrivatePartSeverityInt(anusHediff.Severity), 1000, anusVar?.variation); bodyPartAnus.UpdateGraphic(); /* bodyPartPath = null; cachedPathAndSize = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, bodyTypeDefName, anusHediff.def.defName, "Anus", SizedApparelUtility.PrivatePartSeverityInt(anusHediff.Severity), false), false, "Anus", "Anus"); bodyPartPath = cachedPathAndSize.pathWithSizeIndex; if (bodyPartPath != null) { if (cachedPathAndSize.isUnsupportedHumanlikePath) { if (SizedApparelSettings.UnsupportedRaceToUseHumanlike && pawn.RaceProps.Humanlike) graphicAnus = GraphicDatabase.Get(bodyPartPath); } else graphicAnus = GraphicDatabase.Get(bodyPartPath); } //if (graphicAnus == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) //{ // bodyPartPath = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, pawn.story?.bodyType.defName, anusHediff.def.defName, "Anus", SizedApparelUtility.PrivatePartSeverityInt(anusHediff.Severity), false), false, "Anus", "Anus", "Humanlike").pathWithSizeIndex; // if (bodyPartPath != null) // graphicAnus = GraphicDatabase.Get(bodyPartPath); //} bodyPartPath = null; cachedPathAndSize = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, bodyTypeDefName, anusHediff.def.defName, "Anus", SizedApparelUtility.PrivatePartSeverityInt(anusHediff.Severity), true), false, "Anus", "Anus"); bodyPartPath = cachedPathAndSize.pathWithSizeIndex; if (bodyPartPath != null) { if (cachedPathAndSize.isUnsupportedHumanlikePath) { if (SizedApparelSettings.UnsupportedRaceToUseHumanlike && pawn.RaceProps.Humanlike) graphicAnus_horny = GraphicDatabase.Get(bodyPartPath); } else graphicAnus_horny = GraphicDatabase.Get(bodyPartPath); } //if (graphicAnus_horny == null && pawn.RaceProps.Humanlike && SizedApparelSettings.UnsupportedRaceToUseHumanlike) //{ // bodyPartPath = SizedApparelsDatabase.GetSupportedBodyPartPath(new SizedApparelsDatabase.BodyPartDatabaseKey(pawn.def.defName, pawn.story?.bodyType.defName, anusHediff.def.defName, "Anus", SizedApparelUtility.PrivatePartSeverityInt(anusHediff.Severity), true), false, "Anus", "Anus", "Humanlike").pathWithSizeIndex; // if (bodyPartPath != null) // graphicAnus_horny = GraphicDatabase.Get(bodyPartPath); //}*/ } else bodyPartAnus.SetHediffData(null, -1); } } hasGraphicUpdatedBefore = true; } if(CheckApparel) cachedApparelGraphicRecord = pawnRenderer.apparelGraphics.ToList(); else cachedApparelGraphicRecord = new List(); hasUpdateBeforeSuccess = true; } //public bool hasUnsupportedApparel => Props.hasUnsupportedApparel; //public bool hasUpdateBefore => Props.hasUpdateBefore; /* public void SetHasUnsupportedApparel(bool _hasUnsupportedApparel) { if(Props !=null) Props.hasUnsupportedApparel = _hasUnsupportedApparel; this.hasUnsupportedApparel = _hasUnsupportedApparel; } public void SetHasUpdateBefore(bool _hasUpdateBefore) { if (Props != null) Props.hasUpdateBefore = _hasUpdateBefore; this.hasUpdateBefore = _hasUpdateBefore; }*/ public IEnumerable GetAllSizedApparelBodyPart() // can return null bodyparts { yield return bodyPartBreasts; yield return bodyPartNipple; /* foreach (SizedApparelBodyPart bp in bodyPartBreasts) { yield return bp; } foreach (SizedApparelBodyPart bp in bodyPartNipple) { yield return bp; }*/ foreach (SizedApparelBodyPart bp in bodyPartPenises) { yield return bp; } foreach (SizedApparelBodyPart bp in bodyPartBalls) { yield return bp; } yield return bodyPartVagina; yield return bodyPartAnus; yield return bodyPartBelly; yield return bodyPartMuscleOverlay;//TODO yield return bodyPartUdder; yield return bodyPartPubicHair; //TODO yield return bodyPartHips; foreach (SizedApparelBodyPart bp in bodyPartThighs) { yield return bp; } foreach (SizedApparelBodyPart bp in bodyPartHands) { yield return bp; } foreach (SizedApparelBodyPart bp in bodyPartFeet) { yield return bp; } } public IEnumerable GetSizedApparelBodyParts(SizedApparelBodyPartOf targetPartOf, bool returnNullPart = false) { foreach(SizedApparelBodyPart bp in GetAllSizedApparelBodyPart()) { if (bp == null) { if (returnNullPart) yield return bp; else continue; } if (bp.bodyPartOf.IsPartOf(targetPartOf)) yield return bp; } } public void SetPoseFromPoseSet(string poseSetName, bool autoUpdate = true, bool autoSetPawnGraphicDirty = false) { if (poseSetName.NullOrEmpty()) { ClearAllPose(autoUpdate, autoSetPawnGraphicDirty); return; } var poseSetDef = DefDatabase.GetNamed(poseSetName,false); if (poseSetDef == null) return; if (poseSetDef.poses.NullOrEmpty()) return; foreach (SizedApparelPose pose in poseSetDef.poses) { var bodyParts = GetSizedApparelBodyParts(pose.targetBodyPart); //if (bodyParts == null) // continue; if (bodyParts.EnumerableNullOrEmpty()) continue; foreach (SizedApparelBodyPart bp in bodyParts.ToList()) { if(bp != null) bp.SetCustomPose(poseSetName, autoUpdate, autoSetPawnGraphicDirty); } } } public void ClearAllPose(bool autoUpdate = true, bool autoSetPawnGraphicDirty = false) { foreach (SizedApparelBodyPart bp in GetAllSizedApparelBodyPart()) { if(bp != null) bp.SetCustomPose(null, autoUpdate, autoSetPawnGraphicDirty); } } public void ClearPose(SizedApparelBodyPartOf targetPartOf , bool autoUpdate = true, bool autoSetPawnGraphicDirty = false) { foreach (SizedApparelBodyPart bp in GetSizedApparelBodyParts(targetPartOf)) { if(bp != null) bp.SetCustomPose(null, autoUpdate, autoSetPawnGraphicDirty); } } } [StaticConstructorOnStartup] public class ApparelRecorderCompProperties : CompProperties { public bool hasUnsupportedApparel = false; public bool hasUpdateBefore = false; public ApparelRecorderCompProperties() { this.compClass = typeof(ApparelRecorderComp); } public ApparelRecorderCompProperties(Type compClass) : base(compClass) { this.compClass = compClass; } } }