2023-04-04 01:47:48 +00:00
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
{
2023-04-04 01:48:55 +00:00
Pawn pawn ; // Parent Cache
public bool recentClothFlag = true ;
2023-04-04 01:47:48 +00:00
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 ;
2023-04-04 01:48:55 +00:00
public bool isHediffDirty = true ;
public bool isApparelDirty = true ;
public bool isSkeletonDirty = true ;
public bool isBodyAddonDirty = true ; // reset all body addon graphics.
2023-04-04 01:47:48 +00:00
public bool hasUnsupportedApparel = true ;
public bool havingSex = false ; //Obsolete
public bool hasUpdateForSex = false ; //Obsolete
2023-04-04 01:48:55 +00:00
string cachedBodytype ;
2023-04-04 01:47:48 +00:00
public List < ApparelGraphicRecord > cachedApparelGraphicRecord = new List < ApparelGraphicRecord > ( ) ;
2023-04-04 01:48:55 +00:00
public Hediff breastHediff = null ;
2023-04-04 01:47:48 +00:00
public Hediff vaginaHediff = null ;
public List < Hediff > 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.
2023-04-04 01:48:55 +00:00
public Color ? nippleColor ; //for menstruation cycles Mod
//TODO Optimize Update Hediff Filter
private bool hasBreastsAddon = false ;
private bool hasVaginaAddon = false ;
private bool hasPenisAddon = false ;
private bool hasAnusAddon = false ;
private bool hasUdderAddon = false ;
private bool hasPubicHairAddon = false ;
2023-04-04 01:47:48 +00:00
public float breastSeverity = - 1 ;
public float BreastSeverityCache = 0 ;
//public float BiggestBreastSeverityInAvailableTextures = 0;
//for breasts animation or something.
2023-04-04 01:48:55 +00:00
public bool ForceUpdateTickAnimation = false ;
public bool ForceBlockTickAnimation = false ; // useful when you have make fixed pose
public bool PrePositionCache ;
2023-04-04 01:47:48 +00:00
public Vector3 ? prePositionCache ;
public float? preAngleCache ;
public int? preTickCache ;
2023-04-04 01:48:55 +00:00
public Vector3 preVelocity = Vector3 . zero ;
public float preRotation = 0 ;
public Dictionary < string , int > tickCache = new Dictionary < string , int > ( ) ;
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
public BodyDef bodyDef = null ;
public List < SizedApparelBodyPart > bodyAddons = new List < SizedApparelBodyPart > ( ) ; // BodyParts Added form Defs
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
public SkeletonDef skeletonDef ; // for rebuild Skeleton
public Skeleton skeleton ;
public bool skipSkeleton = false ;
//native BodyParts
2023-04-04 01:47:48 +00:00
public SizedApparelBodyPart bodyPartBreasts ; //TODO: Make this as List
public SizedApparelBodyPart bodyPartNipple ; //TODO
public List < SizedApparelBodyPart > bodyPartPenises = new List < SizedApparelBodyPart > ( ) ;
public List < SizedApparelBodyPart > bodyPartBalls = new List < SizedApparelBodyPart > ( ) ;
public SizedApparelBodyPart bodyPartVagina ;
public SizedApparelBodyPart bodyPartAnus ;
public SizedApparelBodyPart bodyPartBelly ;
public SizedApparelBodyPart bodyPartMuscleOverlay ; //TODO
public SizedApparelBodyPart bodyPartUdder ;
2023-04-04 01:48:55 +00:00
2023-04-04 01:47:48 +00:00
public SizedApparelBodyPart bodyPartHips ;
public List < SizedApparelBodyPart > bodyPartThighs = new List < SizedApparelBodyPart > ( ) ;
public List < SizedApparelBodyPart > bodyPartHands = new List < SizedApparelBodyPart > ( ) ;
public List < SizedApparelBodyPart > bodyPartFeet = new List < SizedApparelBodyPart > ( ) ;
2023-04-04 01:48:55 +00:00
public PubicHairDef pubicHairDef = null ;
public PubicHairDef initialPubicHairDef = null ; // For StyleStaitionWork
public PubicHairDef nextPubicHairDef = null ; // For StyleStaitionWork
public SizedApparelBodyPart bodyPartPubicHair ;
2023-04-04 01:47:48 +00:00
public Graphic graphicSourceNaked = null ; //original Graphic
public Graphic graphicSourceRotten = null ; //original Graphic
2023-04-04 01:48:55 +00:00
public Graphic graphicSourceFurCovered = null ; //original Graphic
2023-04-04 01:47:48 +00:00
public Graphic graphicbaseBodyNaked = null ;
2023-04-04 01:48:55 +00:00
public SizedApparelTexturePointDef baseBodyNakedPoints ;
public Graphic graphicbaseBodyCorpse = null ;
public SizedApparelTexturePointDef baseBodyCorpsePoints ;
2023-04-04 01:47:48 +00:00
public Graphic graphicbaseBodyRotten = null ;
2023-04-04 01:48:55 +00:00
public SizedApparelTexturePointDef baseBodyRottenPoints ;
public Graphic graphicbaseBodyFurCovered = null ;
public SizedApparelTexturePointDef baseBodyFurCoveredPoints ;
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
public AlienRaceSetting raceSetting = null ;
2023-04-04 01:47:48 +00:00
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
2023-04-04 01:48:55 +00:00
//this may reset skeleton animation. also little have process
public void InitSkeleton ( )
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
skeletonDef = DefDatabase < SkeletonDef > . GetNamedSilentFail ( pawn . def . defName ) ;
if ( skeletonDef = = null )
{
if ( raceSetting ! = null & & raceSetting . asHuman = = true ) //old: !SizedApparelSettings.UnsupportedRaceToUseHumanlike
{
skeletonDef = DefDatabase < SkeletonDef > . GetNamedSilentFail ( "Human" ) ;
}
}
if ( skeletonDef ! = null )
{
if ( this . pawn . story = = null | | this . pawn . story . bodyType = = null )
{
foreach ( Skeleton s in skeletonDef . skeletons )
{
if ( s . bodyType = = null )
{
this . skeleton = new Skeleton ( s ) ;
if ( SizedApparelSettings . Debug )
Log . Message ( "[SizedApparel] Apply SkeletonDef: pawn withouth bodytype " + pawn . Name ) ;
return ;
}
}
}
else
{
//Setting Up Skeleton
foreach ( Skeleton s in skeletonDef . skeletons )
{
if ( s . bodyType = = this . pawn . story . bodyType . defName )
{
this . skeleton = new Skeleton ( s ) ;
if ( SizedApparelSettings . Debug )
Log . Message ( "[SizedApparel] Apply SkeletonDef: pawn with bodytype " + pawn . Name + " with SkeletonDef : " + this . pawn . story . bodyType . defName ) ;
return ;
}
}
}
this . skeleton = null ;
}
if ( SizedApparelSettings . Debug )
Log . Message ( "[SizedApparel] Apply SkeletonDef: No Skeleton Found for " + pawn . Name ) ;
isSkeletonDirty = false ;
}
public void InitBodyAddons ( )
{
bodyAddons . Clear ( ) ;
//TODO
//bodyDef = DefDatabase<SizedApparelBodyDef>.GetNamed(pawn.def.defName);
bodyDef = DefDatabase < BodyDef > . GetNamedSilentFail ( pawn . def . defName ) ;
//bodyDef can be null
if ( bodyDef = = null )
{
if ( raceSetting ! = null & & raceSetting . asHuman ) //old: !SizedApparelSettings.UnsupportedRaceToUseHumanlike
{
bodyDef = DefDatabase < BodyDef > . GetNamedSilentFail ( "Human" ) ;
}
}
if ( bodyDef ! = null & & bodyDef . bodies ! = null )
{
if ( pawn . story ? . bodyType = = null )
{
if ( SizedApparelSettings . Debug )
Log . Message ( "[SizedApparel] Apply BodyDef: pawn has no bodytype " + pawn . Name ) ;
BodyWithBodyType body = null ;
if ( ! bodyDef . bodies . NullOrEmpty ( ) )
body = bodyDef . bodies [ 0 ] ;
if ( body ! = null & & body . Addons ! = null )
{
foreach ( var bodyaddon in body . Addons )
{
if ( bodyaddon = = null )
continue ;
var a = new SizedApparelBodyPart ( pawn , this , bodyaddon . partName , bodyaddon . bodyPartOf , bodyaddon . defaultHediffName , bodyaddon . isBreasts , false , bodyaddon . customPath , bodyaddon . colorType , bodyaddon . mustHaveBone ) ;
a . SetDepthOffsets ( bodyaddon . depthOffset . south , bodyaddon . depthOffset . north , bodyaddon . depthOffset . east , bodyaddon . depthOffset . west ) ;
//a.SetDepthOffsets(bodyaddon.depthOffset);
a . SetCenteredTexture ( bodyaddon . centeredTexture ) ;
bodyAddons . Add ( a ) ;
break ;
}
}
}
else
{
foreach ( BodyWithBodyType body in bodyDef . bodies )
{
if ( body . bodyType ! = null & & body . bodyType = = this . pawn . story . bodyType . defName )
{
if ( SizedApparelSettings . Debug )
Log . Message ( "[SizedApparel] Apply BodyDef: matched BodyTyped Body for " + pawn . Name ) ;
if ( body ! = null & & body . Addons ! = null )
{
foreach ( var bodyaddon in body . Addons )
{
if ( bodyaddon = = null )
continue ;
var a = new SizedApparelBodyPart ( pawn , this , bodyaddon . partName , bodyaddon . bodyPartOf , bodyaddon . defaultHediffName , bodyaddon . isBreasts , false , bodyaddon . customPath , bodyaddon . colorType , bodyaddon . mustHaveBone ) ;
a . SetDepthOffsets ( bodyaddon . depthOffset . south , bodyaddon . depthOffset . north , bodyaddon . depthOffset . east , bodyaddon . depthOffset . west ) ;
//a.SetDepthOffsets(bodyaddon.depthOffset);
a . SetCenteredTexture ( bodyaddon . centeredTexture ) ;
bodyAddons . Add ( a ) ;
}
}
break ;
}
}
}
}
else
{
if ( SizedApparelSettings . Debug )
Log . Message ( "[SizedApparel] Cannot find BodyDef for " + pawn . def . defName ) ;
}
//bodyPartBreasts = new SizedApparelBodyPart(pawn, this, "Breasts", SizedApparelBodyPartOf.Breasts, "Breasts", true, false, null);
//bodyPartBreasts.SetDepthOffsets(0.0113f, 0.001f, 0.0113f, 0.0113f);
//bodyPartBreasts.SetPositionOffsets(Vector2.one, Vector2.one, Vector2.one, Vector2.one);
//bodyPartBreasts.scale = 2f;
//Nipple. should I separate from Breats?
//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);
2023-04-04 01:47:48 +00:00
//UdderNipple...?
//bodyPartUdder = new SizedApparelBodyPart(p, "Udder", SizedApparelBodyPartOf.Udder, "UdderBreasts", true, false);
2023-04-04 01:48:55 +00:00
//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);
//bodyPartPubicHair = new SizedApparelBodyPart(pawn, this, "PubicHair", SizedApparelBodyPartOf.PubicHair, "Default", false, false, null, ColorType.Hair);
//bodyPartPubicHair.SetDepthOffsets(0.0099f, 0.0099f, 0.0089f, 0.0089f);
}
public void ResetBodyAddonBoneLink ( )
{
string s ;
foreach ( var a in bodyAddons )
{
s = a . bone ? . name ;
if ( s = = null )
continue ;
a . SetBone ( skeleton . FindBone ( s ) ) ;
}
}
public override void Initialize ( CompProperties props )
{
base . Initialize ( props ) ;
this . pawn = this . parent as Pawn ;
}
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
public override void PostDeSpawn ( Map map )
{
base . PostDeSpawn ( map ) ;
}
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
public override void PostSpawnSetup ( bool respawningAfterLoad )
{
base . PostSpawnSetup ( respawningAfterLoad ) ;
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
UpdateRaceSettingData ( ) ; // include race Setting
InitSkeleton ( ) ;
InitBodyAddons ( ) ;
2023-04-04 01:47:48 +00:00
}
2023-04-04 01:48:55 +00:00
2023-04-04 01:47:48 +00:00
public override void PostExposeData ( )
{
base . PostExposeData ( ) ;
2023-04-04 01:48:55 +00:00
Scribe_Values . Look < string > ( ref customPose , "customPose" ) ; // save pawn's custom pose. Each bodyparts will not saved.
Scribe_Defs . Look < PubicHairDef > ( ref pubicHairDef , "PubicHairDef" ) ;
if ( pubicHairDef = = null )
{
pubicHairDef = SizedApparelUtility . GetRandomPubicHair ( ) ;
}
2023-04-04 01:47:48 +00:00
//Scribe_Values.Look<>(); //TODO: save pubic hair data
}
2023-04-04 01:48:55 +00:00
2023-04-04 01:47:48 +00:00
/ *
public override void CompTick ( )
{
2023-04-04 01:48:55 +00:00
if ( PrePositionCache )
{
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
}
base . CompTick ( ) ;
} * /
/ *
2023-04-04 01:47:48 +00:00
public override void CompTickRare ( )
{
base . CompTickRare ( ) ;
} * /
2023-04-04 01:48:55 +00:00
float penisAngle = 0 ;
public void SetPenisAngle ( float angle )
{
penisAngle = angle ;
if ( this . skeleton ! = null )
{
Bone penisBone = skeleton . FindBone ( "Penis" ) ;
if ( penisBone ! = null )
{
//Log.Message("SetPenisAngle : " + angle.ToString());
penisBone . SetAngle ( 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 ) ;
}
}
}
//do not call this in character creation from new game.
public void SetBreastJiggle ( bool jiggle , int cooltime = 5 , bool checkApparelForCanPose = false )
{
//SetJiggle has cooltime.
bool flag1 = true ;
//should set apparels pose?
//Use First BodyAddon which is partof Breasts
foreach ( var a in GetSizedApparelBodyParts ( SizedApparelBodyPartOf . Breasts ) )
{
if ( flag1 )
{
if ( Find . TickManager . TicksGame < a . lastPoseTick + cooltime )
return ;
flag1 = false ;
}
if ( jiggle )
{
bool flag2 = true ;
if ( flag2 & & checkApparelForCanPose )
{
if ( ! a . CheckCanPose ( "JiggleUp" , true , false , true , true , false ) )
return ;
flag2 = false ;
}
//may need to check apparels for aply pose
//bodyPartBreasts.CheckCanPose("JiggleUp",)
a . SetCustomPose ( "JiggleUp" ) ;
}
else
{
//SetPoseFromPoseSet(null);
a . SetCustomPose ( null ) ;
}
}
}
2023-04-04 01:47:48 +00:00
string [ ] testPose = { null , "JiggleUp" , "JiggleCenter" } ;
string [ ] testPose2 = { null , "PenisDown" } ;
2023-04-04 01:48:55 +00:00
public void UpdateTickAnim ( Vector3 rootLoc , float angle ) // call this in DrawPawnBody <- only called when it rendered
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
if ( ForceBlockTickAnimation ) // prevent breasts jiggle from other pose
return ;
if ( skeleton = = null )
return ;
if ( Find . CameraDriver = = null )
return ;
//do not calculate physics camera is far
if ( Find . CameraDriver . CurrentZoom > = CameraZoomRange . Furthest )
return ;
2023-04-04 01:47:48 +00:00
//int IdTick = parent.thingIDNumber * 20; //hint from yayo animation mod
2023-04-04 01:48:55 +00:00
if ( ! SizedApparelUtility . CanApplySizedApparel ( pawn ) )
return ;
if ( SizedApparelSettings . breastsPhysics | | ForceUpdateTickAnimation ) //SizedApparelSettings.autoJiggleBreasts
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
int tick ;
if ( this . preTickCache ! = null )
tick = Find . TickManager . TicksGame - this . preTickCache . Value ;
else
tick = Find . TickManager . TicksGame ;
//if tick is not updated, don't update animation.
if ( tick = = 0 )
return ;
2023-04-04 01:47:48 +00:00
Vector3 velocity ;
if ( this . prePositionCache ! = null )
2023-04-04 01:48:55 +00:00
velocity = ( rootLoc - this . prePositionCache . Value ) ; // /tick
2023-04-04 01:47:48 +00:00
else
velocity = Vector3 . zero ;
float rotation ;
2023-04-04 01:48:55 +00:00
2023-04-04 01:47:48 +00:00
if ( this . preAngleCache ! = null )
2023-04-04 01:48:55 +00:00
rotation = angle - this . preAngleCache . Value ;
2023-04-04 01:47:48 +00:00
else
rotation = 0 ;
2023-04-04 01:48:55 +00:00
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 ) ;
float velocityOffset = ( velocity - preVelocity ) . magnitude ;
//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());
//Log.Message("velocityOffset : " + velocityOffset.ToString());
//&& dotV > 0.4f
if ( ( ( preVelocity ! = Vector3 . zero & & velocityOffset > = 0.02 ) ) | | 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 , true ) ;
}
2023-04-04 01:47:48 +00:00
else
2023-04-04 01:48:55 +00:00
{
SetBreastJiggle ( false , 10 , false ) ;
}
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
//cache pre data
2023-04-04 01:47:48 +00:00
this . prePositionCache = rootLoc ;
this . preAngleCache = angle ;
2023-04-04 01:48:55 +00:00
this . preRotation = rotation ;
2023-04-04 01:47:48 +00:00
this . preTickCache = Find . TickManager . TicksGame ;
2023-04-04 01:48:55 +00:00
this . preVelocity = velocity ;
2023-04-04 01:47:48 +00:00
}
2023-04-04 01:48:55 +00:00
//SetPoseFromPoseSet(testPose2.RandomElement());
2023-04-04 01:47:48 +00:00
}
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 ;
}
2023-04-04 01:48:55 +00:00
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);
foreach ( var b in GetSizedApparelBodyParts ( SizedApparelBodyPartOf . Vagina ) )
{
b . DrawBodyPart ( rootLoc , angle , facing , bodyDrawType , flags , bodyMesh ) ;
}
}
if ( bodyDrawType ! = RotDrawMode . Dessicated & & SizedApparelSettings . drawAnus & & SizedApparelUtility . CanDrawAnus ( ___pawn , flags ) )
{
//if (this.bodyPartAnus != null)
// this.bodyPartAnus.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
foreach ( var b in GetSizedApparelBodyParts ( SizedApparelBodyPartOf . Anus ) )
{
b . DrawBodyPart ( rootLoc , angle , facing , bodyDrawType , flags , bodyMesh ) ;
}
}
if ( bodyDrawType ! = RotDrawMode . Dessicated & & SizedApparelSettings . drawBelly & & SizedApparelUtility . CanDrawBelly ( ___pawn , flags ) )
{
//if (this.bodyPartBelly != null)
// this.bodyPartBelly.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
foreach ( var b in GetSizedApparelBodyParts ( SizedApparelBodyPartOf . Belly ) )
{
b . DrawBodyPart ( rootLoc , angle , facing , bodyDrawType , flags , bodyMesh ) ;
}
}
//Draw Pubic Hair
if ( bodyDrawType ! = RotDrawMode . Dessicated & & SizedApparelSettings . drawPubicHair & & SizedApparelUtility . CanDrawPubicHair ( ___pawn , flags ) )
{
if ( this . bodyPartPubicHair ! = null )
this . bodyPartPubicHair . DrawBodyPart ( rootLoc , angle , facing , bodyDrawType , flags , bodyMesh ) ;
foreach ( var b in GetSizedApparelBodyParts ( SizedApparelBodyPartOf . PubicHair ) )
{
b . DrawBodyPart ( rootLoc , angle , facing , bodyDrawType , flags , bodyMesh ) ;
}
}
if ( bodyDrawType ! = RotDrawMode . Dessicated & & SizedApparelSettings . drawUdder & & SizedApparelUtility . CanDrawUdder ( ___pawn , flags ) )
{
//if (this.bodyPartUdder != null)
// this.bodyPartUdder.DrawBodyPart(rootLoc, angle, facing, bodyDrawType, flags, bodyMesh);
foreach ( var b in GetSizedApparelBodyParts ( SizedApparelBodyPartOf . Udder ) )
{
b . DrawBodyPart ( rootLoc , angle , facing , bodyDrawType , flags , bodyMesh ) ;
}
}
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);
foreach ( var b in GetSizedApparelBodyParts ( SizedApparelBodyPartOf . Breasts ) )
{
b . DrawBodyPart ( rootLoc , angle , facing , bodyDrawType , flags , bodyMesh ) ;
}
}
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 ( var b in GetSizedApparelBodyParts ( SizedApparelBodyPartOf . Balls ) )
{
b . DrawBodyPart ( rootLoc , angle , facing , bodyDrawType , flags , bodyMesh ) ;
}
}
/ *
foreach ( SizedApparelBodyPart p in this . bodyPartPenises )
{
p . DrawBodyPart ( rootLoc , angle , facing , bodyDrawType , flags , bodyMesh ) ;
} * /
foreach ( var b in GetSizedApparelBodyParts ( SizedApparelBodyPartOf . Penis ) )
{
b . DrawBodyPart ( rootLoc , angle , facing , bodyDrawType , flags , bodyMesh ) ;
}
} //Draw BodyParts
//Draw Modular Apparel Parts... TODO...? Is it passible?
if ( flags . FlagSet ( PawnRenderFlags . Clothes ) )
{
}
}
}
2023-04-04 01:47:48 +00:00
//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
{
}
* /
2023-04-04 01:48:55 +00:00
}
public void ClearHediffs ( )
2023-04-04 01:47:48 +00:00
{
breastHediff = null ;
vaginaHediff = null ;
if ( penisHediffs ! = null )
penisHediffs . Clear ( ) ;
anusHediff = null ;
udderHediff = null ;
}
public void ClearBreastCacheValue ( )
{
breastHediff = null ;
breastSeverity = - 1 ;
BreastSeverityCache = 0 ;
}
public void ClearPenisCacheValue ( )
{
//TODO
}
public void ClearCanDraw ( )
{
canDrawBreasts = false ;
canDrawPenis = false ;
canDrawTorsoParts = false ;
canDrawVaginaAndAnus = false ;
}
public void ClearGraphics ( bool clearBreasts = true )
{
2023-04-04 01:48:55 +00:00
//Since Injection of base body is now in Matarial. no need to keep
graphicSourceNaked = null ;
graphicSourceFurCovered = null ;
graphicSourceRotten = null ;
2023-04-04 01:47:48 +00:00
hasGraphicUpdatedBefore = false ;
graphicbaseBodyNaked = null ;
graphicbaseBodyRotten = null ;
2023-04-04 01:48:55 +00:00
graphicbaseBodyFurCovered = null ;
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
return ;
2023-04-04 01:47:48 +00:00
//Clear BodyParts
2023-04-04 01:48:55 +00:00
if ( clearBreasts & & bodyPartBreasts ! = null )
2023-04-04 01:47:48 +00:00
bodyPartBreasts . Clear ( ) ;
2023-04-04 01:48:55 +00:00
if ( bodyPartAnus ! = null )
bodyPartAnus . Clear ( ) ;
if ( bodyPartBelly ! = null )
bodyPartBelly . Clear ( ) ;
if ( bodyPartVagina ! = null )
bodyPartVagina . Clear ( ) ;
if ( bodyPartPubicHair ! = null )
bodyPartPubicHair . Clear ( ) ;
foreach ( var a in bodyAddons )
{
a . Clear ( ) ;
}
2023-04-04 01:47:48 +00:00
}
public void ClearAll ( bool clearGraphics = true )
{
ClearBreastCacheValue ( ) ;
if ( clearGraphics )
ClearGraphics ( ) ;
ClearHediffs ( ) ;
ClearCanDraw ( ) ;
hasUnsupportedApparel = false ;
hasUpdateBefore = false ;
hasUpdateBeforeSuccess = false ;
needToCheckApparelGraphicRecords = false ;
}
2023-04-04 01:48:55 +00:00
public void SetDirty ( bool clearPawnGraphicSet = false , bool dirtyHediff = true , bool dirtyApparel = true , bool dirtySkeleton = false , bool dirtyBodyAddons = false )
2023-04-04 01:47:48 +00:00
{
this . isDirty = true ;
2023-04-04 01:48:55 +00:00
this . isHediffDirty = dirtyHediff ;
this . isApparelDirty = dirtyApparel ;
this . isSkeletonDirty = dirtySkeleton ;
this . isBodyAddonDirty = dirtyBodyAddons ;
2023-04-04 01:47:48 +00:00
if ( clearPawnGraphicSet )
{
if ( pawn = = null )
return ;
if ( pawn . Drawer = = null )
return ;
if ( pawn . Drawer . renderer = = null )
return ;
pawn . Drawer . renderer . graphics . ClearCache ( ) ;
}
}
2023-04-04 01:48:55 +00:00
public void UpdateRaceSettingData ( )
2023-04-04 01:47:48 +00:00
{
if ( pawn = = null )
return ;
var loc_raceSetting = SizedApparelSettings . alienRaceSettings . FirstOrDefault ( ( AlienRaceSetting s ) = > s . raceName = = pawn . def . defName ) ;
2023-04-04 01:48:55 +00:00
if ( loc_raceSetting = = null )
2023-04-04 01:47:48 +00:00
return ;
raceSetting = loc_raceSetting ;
}
public void CheckAgeChanged ( )
{
if ( pawn = = null )
return ;
if ( pawn . ageTracker = = null )
return ;
//TODO. Cleanup
2023-04-04 01:48:55 +00:00
UpdateRaceSettingData ( ) ;
2023-04-04 01:47:48 +00:00
if ( raceSetting = = null )
return ;
if ( raceSetting . drawMinAge < 0 | | pawn . ageTracker . AgeBiologicalYearsFloat > = raceSetting . drawMinAge )
isDrawAge = true ;
else
isDrawAge = false ;
}
2023-04-04 01:48:55 +00:00
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 < Texture2D > . Get ( ( targetGraphicPath + baseBodyStringWithSex + "_south" ) , false ) ! = null )
{
//cachedSourceGraphic = sourceGraphic;
Shader shader = sourceGraphic . Shader ;
//if (!ShaderUtility.SupportsMaskTex(shader))
// shader = ShaderDatabase.CutoutSkinOverlay;
targetGraphicBaseBody = GraphicDatabase . Get < Graphic_Multi > ( targetGraphicPath + baseBodyStringWithSex , shader , sourceGraphic . drawSize , sourceGraphic . color , sourceGraphic . colorTwo , sourceGraphic . data ) ;
//sourceGraphic = targetGraphicBaseBody;
}
else if ( customPose ! = null )
{
targetGraphicPath = sourceGraphic . path ;
if ( ContentFinder < Texture2D > . Get ( ( targetGraphicPath + baseBodyStringWithSex + "_south" ) , false ) ! = null )
{
//cachedSourceGraphic = sourceGraphic;
Shader shader = sourceGraphic . Shader ;
//if (!ShaderUtility.SupportsMaskTex(shader))
// shader = ShaderDatabase.CutoutSkinOverlay;
targetGraphicBaseBody = GraphicDatabase . Get < Graphic_Multi > ( 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 < Texture2D > . Get ( ( targetGraphicPath + baseBodyString + "_south" ) , false ) ! = null )
{
// cachedSourceGraphic = sourceGraphic;
Shader shader = sourceGraphic . Shader ;
//if (!ShaderUtility.SupportsMaskTex(shader))
// shader = ShaderDatabase.CutoutSkinOverlay;
targetGraphicBaseBody = GraphicDatabase . Get < Graphic_Multi > ( targetGraphicPath + baseBodyString , shader , sourceGraphic . drawSize , sourceGraphic . color , sourceGraphic . colorTwo , sourceGraphic . data ) ;
//sourceGraphic = targetGraphicBaseBody;
}
else if ( customPose ! = null )
{
targetGraphicPath = sourceGraphic . path ;
if ( ContentFinder < Texture2D > . Get ( ( targetGraphicPath + baseBodyString + "_south" ) , false ) ! = null )
{
//cachedSourceGraphic = sourceGraphic;
Shader shader = sourceGraphic . Shader ;
//if (!ShaderUtility.SupportsMaskTex(shader))
// shader = ShaderDatabase.CutoutSkinOverlay;
targetGraphicBaseBody = GraphicDatabase . Get < Graphic_Multi > ( 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 ;
}
}
2023-04-04 01:47:48 +00:00
public void Update ( bool cache = true , bool fromGraphicRecord = true , bool updateGraphics = true , bool CheckApparel = true )
{
2023-04-04 01:48:55 +00:00
if ( cache )
recentClothFlag = CheckApparel ;
2023-04-04 01:47:48 +00:00
isDirty = false ;
bool flag = fromGraphicRecord ;
needToCheckApparelGraphicRecords = false ;
//flag = false; //TODO:fromGraphicRecord is forced not to do for a while. it will update later
2023-04-04 01:48:55 +00:00
UpdateRaceSettingData ( ) ;
if ( ! hasUpdateBefore )
{
InitSkeleton ( ) ;
InitBodyAddons ( ) ;
hasUpdateBefore = true ;
}
else
{
//check is bodytype changed
if ( cachedBodytype ! = pawn . story ? . bodyType ? . defName )
{
isSkeletonDirty = true ;
}
if ( isSkeletonDirty )
{
InitSkeleton ( ) ;
if ( isBodyAddonDirty )
InitBodyAddons ( ) ;
else
ResetBodyAddonBoneLink ( ) ;
}
else
{
if ( isBodyAddonDirty )
InitBodyAddons ( ) ;
}
}
if ( skeleton = = null )
{
if ( Find . CurrentMap ! = null )
return ;
}
if ( ! SizedApparelUtility . CanApplySizedApparel ( pawn ) )
2023-04-04 01:47:48 +00:00
return ;
2023-04-04 01:48:55 +00:00
if ( pubicHairDef = = null )
{
pubicHairDef = SizedApparelUtility . GetRandomPubicHair ( ) ;
}
2023-04-04 01:47:48 +00:00
if ( SizedApparelSettings . Debug )
Log . Message ( "[SizedApparel] Updating Component of " + pawn . Name ) ;
if ( updateGraphics )
{
ClearGraphics ( ) ;
2023-04-04 01:48:55 +00:00
//ClearHediffs();
}
//float breastSeverityCapped = 1000;
string bodyTypeDefName = null ;
if ( pawn . story ! = null )
bodyTypeDefName = pawn . story . bodyType ? . defName ;
float bellySeverity = 0 ;
if ( isHediffDirty ) //Update Hediff Data
{
2023-04-04 01:47:48 +00:00
ClearHediffs ( ) ;
2023-04-04 01:48:55 +00:00
if ( SizedApparelSettings . drawPenis | | SizedApparelSettings . drawVagina | | SizedApparelSettings . drawAnus )
{
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 ) ) ;
}
}
}
if ( SizedApparelSettings . drawBelly )
{
//EggImplement as Pregnant
//need to Optimize... TODO...
List < Hediff > pregnancies = pawn . health ? . hediffSet ? . hediffs ? . FindAll ( ( Hediff h ) = > SizedApparelUtility . isPragnencyHediff ( h ) | | SizedApparelUtility . isRJWEggHediff ( h ) ) ; //pregnancy and pregnant. has some issue with "pregnancy mood"
if ( ! pregnancies . NullOrEmpty ( ) )
{
foreach ( Hediff h in pregnancies )
{
//Set Labor Belly as Big Belly.
//Code for 1.4
/ *
if ( h . def = = HediffDefOf . PregnancyLabor | | h . def = = HediffDefOf . PregnancyLaborPushing )
bellySeverity = Math . Max ( bellySeverity , 1f ) ;
else
bellySeverity = Math . Max ( bellySeverity , h . Severity ) ;
* /
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 ;
}
}
2023-04-04 01:47:48 +00:00
}
2023-04-04 01:48:55 +00:00
2023-04-04 01:47:48 +00:00
CheckAgeChanged ( ) ;
2023-04-04 01:48:55 +00:00
if ( SizedApparelSettings . drawBreasts )
{
SizedApparelUtility . GetBreastSeverity ( pawn , out breastSeverity , out breastHediff ) ;
}
2023-04-04 01:47:48 +00:00
if ( breastHediff ! = null )
{
2023-04-04 01:48:55 +00:00
//get nipple color from Menstruation.
if ( SizedApparelPatch . MenstruationActive )
{
nippleColor = Patch_Menstruation . GetNippleColor ( breastHediff ) ;
}
if ( pawn . gender = = Gender . Male & & ! SizedApparelSettings . ApplyApparelPatchForMale )
{
CheckApparel = false ;
}
if ( CheckApparel | | this . isApparelDirty )
{
2023-04-04 01:47:48 +00:00
hasUnsupportedApparel = SizedApparelUtility . hasUnSupportedApparelFromWornData ( pawn , breastSeverity , breastHediff , true , flag ) ;
2023-04-04 01:48:55 +00:00
}
2023-04-04 01:47:48 +00:00
else
2023-04-04 01:48:55 +00:00
{
2023-04-04 01:47:48 +00:00
hasUnsupportedApparel = false ;
2023-04-04 01:48:55 +00:00
}
2023-04-04 01:47:48 +00:00
//float validBreastTextureSeverity = SizedApparelUtility.GetBreastSeverityValidTextures(pawn, breastHediff);
2023-04-04 01:48:55 +00:00
if ( SizedApparelSettings . useBreastSizeCapForApparels ) // && hasUnsupportedApparel
{
BreastSeverityCache = Math . Min ( BreastSeverityCache , breastSeverity ) ;
}
else
{
BreastSeverityCache = 1000 ;
}
//if (SizedApparelSettings.useBreastSizeCapForApparels) //SizedApparelSettings.useBreastSizeCapForApparels //wip
// breastSeverityCapped = Math.Min(BreastSeverityCache, breastSeverityCapped);
2023-04-04 01:47:48 +00:00
//float validBreastTextureSeverity = SizedApparelUtility.GetBreastSeverityValidTextures(pawn, breastHediff);
//breast cache forApparel brests Check. This ignore variation!
//SizedApparelMod.CheckAndLoadAlienRaces();
2023-04-04 01:48:55 +00:00
2023-04-04 01:47:48 +00:00
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 ) ;
2023-04-04 01:48:55 +00:00
//TODO? Remove ValidBreastsTextureCheck...
2023-04-04 01:47:48 +00:00
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.
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();
2023-04-04 01:48:55 +00:00
//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 ;
2023-04-04 01:47:48 +00:00
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 ) )
{
2023-04-04 01:48:55 +00:00
if ( SizedApparelSettings . useGenderSpecificTexture & pawn . gender ! = Gender . None )
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
if ( graphicbaseBodyNaked = = null )
2023-04-04 01:47:48 +00:00
{
if ( ContentFinder < Texture2D > . Get ( ( nakedGraphicPath + baseBodyStringWithSex + "_south" ) , false ) ! = null )
{
//graphicSourceNaked = pawnRenderer.nakedGraphic;
Shader shader = pawnRenderer . nakedGraphic . Shader ;
//if (!ShaderUtility.SupportsMaskTex(shader))
// shader = ShaderDatabase.CutoutSkinOverlay;
graphicbaseBodyNaked = GraphicDatabase . Get < Graphic_Multi > ( nakedGraphicPath + baseBodyStringWithSex , shader , pawnRenderer . nakedGraphic . drawSize , pawnRenderer . nakedGraphic . color , pawnRenderer . nakedGraphic . colorTwo , pawnRenderer . nakedGraphic . data ) ;
//pawnRenderer.nakedGraphic = graphicbaseBodyNaked;
}
2023-04-04 01:48:55 +00:00
else if ( customPose ! = null )
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
nakedGraphicPath = pawnRenderer . nakedGraphic . path ;
if ( ContentFinder < Texture2D > . Get ( ( nakedGraphicPath + baseBodyStringWithSex + "_south" ) , false ) ! = null )
{
//graphicSourceNaked = pawnRenderer.nakedGraphic;
Shader shader = pawnRenderer . nakedGraphic . Shader ;
//if (!ShaderUtility.SupportsMaskTex(shader))
// shader = ShaderDatabase.CutoutSkinOverlay;
graphicbaseBodyNaked = GraphicDatabase . Get < Graphic_Multi > ( 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" ) ;
}
2023-04-04 01:47:48 +00:00
}
}
}
if ( graphicbaseBodyNaked = = null )
{
if ( ContentFinder < Texture2D > . Get ( ( nakedGraphicPath + baseBodyString + "_south" ) , false ) ! = null )
{
// graphicSourceNaked = pawnRenderer.nakedGraphic;
Shader shader = pawnRenderer . nakedGraphic . Shader ;
//if (!ShaderUtility.SupportsMaskTex(shader))
// shader = ShaderDatabase.CutoutSkinOverlay;
graphicbaseBodyNaked = GraphicDatabase . Get < Graphic_Multi > ( 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 < Texture2D > . Get ( ( nakedGraphicPath + baseBodyString + "_south" ) , false ) ! = null )
{
//graphicSourceNaked = pawnRenderer.nakedGraphic;
Shader shader = pawnRenderer . nakedGraphic . Shader ;
//if (!ShaderUtility.SupportsMaskTex(shader))
// shader = ShaderDatabase.CutoutSkinOverlay;
graphicbaseBodyNaked = GraphicDatabase . Get < Graphic_Multi > ( 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 ;
}
2023-04-04 01:48:55 +00:00
//Finding Texture Points
if ( false & & graphicbaseBodyNaked ! = null )
{
SizedApparelTexturePointDef PointsDef = DefDatabase < SizedApparelTexturePointDef > . AllDefs . FirstOrDefault ( ( SizedApparelTexturePointDef s ) = > s . Path = = graphicbaseBodyNaked . path ) ;
if ( SizedApparelSettings . Debug & & PointsDef ! = null )
{
Log . Message ( "[SizedApparel] : NakedBaseBody Texture Points Def Found : " + PointsDef . defName ) ;
}
baseBodyNakedPoints = PointsDef ;
}
else
baseBodyNakedPoints = null ;
2023-04-04 01:47:48 +00:00
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 < Texture2D > . Get ( ( rottingGraphicPath + baseBodyStringWithSex + "_south" ) , false ) ! = null )
{
//graphicSourceRotten = pawnRenderer.rottingGraphic;
Shader shader = pawnRenderer . rottingGraphic . Shader ;
//if (!ShaderUtility.SupportsMaskTex(shader))
// shader = ShaderDatabase.CutoutSkinOverlay;
graphicbaseBodyRotten = GraphicDatabase . Get < Graphic_Multi > ( 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 < Texture2D > . Get ( ( rottingGraphicPath + baseBodyStringWithSex + "_south" ) , false ) ! = null )
{
graphicSourceRotten = pawnRenderer . rottingGraphic ;
Shader shader = pawnRenderer . rottingGraphic . Shader ;
//if (!ShaderUtility.SupportsMaskTex(shader))
// shader = ShaderDatabase.CutoutSkinOverlay;
graphicbaseBodyRotten = GraphicDatabase . Get < Graphic_Multi > ( rottingGraphicPath + baseBodyStringWithSex , shader , pawnRenderer . rottingGraphic . drawSize , pawnRenderer . rottingGraphic . color , pawnRenderer . rottingGraphic . colorTwo , pawnRenderer . rottingGraphic . data ) ;
//pawnRenderer.rottingGraphic = graphicbaseBodyRotten;
}
else
{
if ( SizedApparelSettings . Debug )
2023-04-04 01:48:55 +00:00
Log . Warning ( "[SizedApparel] Missing BaseBodyTexture for rotting Graphic: " + rottingGraphicPath + baseBodyStringWithSex + "_south" ) ;
2023-04-04 01:47:48 +00:00
}
}
if ( graphicbaseBodyRotten = = null )
{
if ( ContentFinder < Texture2D > . Get ( ( rottingGraphicPath + baseBodyString + "_south" ) , false ) ! = null )
{
//graphicSourceRotten = pawnRenderer.rottingGraphic;
Shader shader = pawnRenderer . rottingGraphic . Shader ;
//if (!ShaderUtility.SupportsMaskTex(shader))
// shader = ShaderDatabase.CutoutSkinOverlay;
graphicbaseBodyRotten = GraphicDatabase . Get < Graphic_Multi > ( 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 < Texture2D > . Get ( ( rottingGraphicPath + baseBodyString + "_south" ) , false ) ! = null )
{
graphicSourceRotten = pawnRenderer . rottingGraphic ;
Shader shader = pawnRenderer . rottingGraphic . Shader ;
//if (!ShaderUtility.SupportsMaskTex(shader))
// shader = ShaderDatabase.CutoutSkinOverlay;
graphicbaseBodyRotten = GraphicDatabase . Get < Graphic_Multi > ( rottingGraphicPath + baseBodyString , shader , pawnRenderer . rottingGraphic . drawSize , pawnRenderer . rottingGraphic . color , pawnRenderer . rottingGraphic . colorTwo , pawnRenderer . rottingGraphic . data ) ;
//pawnRenderer.rottingGraphic = graphicbaseBodyRotten;
}
else
{
if ( SizedApparelSettings . Debug )
2023-04-04 01:48:55 +00:00
Log . Warning ( "[SizedApparel] Missing BaseBodyTexture for rotting Graphic: " + rottingGraphicPath + baseBodyString + "_south" ) ;
2023-04-04 01:47:48 +00:00
}
}
}
}
}
else
graphicbaseBodyRotten = pawnRenderer . rottingGraphic ;
}
2023-04-04 01:48:55 +00:00
//Finding Texture Points
if ( false & & graphicbaseBodyRotten ! = null )
{
SizedApparelTexturePointDef PointsDef = DefDatabase < SizedApparelTexturePointDef > . AllDefs . FirstOrDefault ( ( SizedApparelTexturePointDef s ) = > s . Path = = graphicbaseBodyRotten . path ) ;
if ( SizedApparelSettings . Debug & & PointsDef ! = null )
{
Log . Message ( "[SizedApparel] : RottenBaseBody Texture Points Def Found : " + PointsDef . defName ) ;
}
baseBodyRottenPoints = PointsDef ;
}
else
baseBodyRottenPoints = null ;
string furCoveredGraphicPath = null ;
//Finding Texture Points
if ( false & & graphicbaseBodyFurCovered ! = null )
{
SizedApparelTexturePointDef PointsDef = DefDatabase < SizedApparelTexturePointDef > . AllDefs . FirstOrDefault ( ( SizedApparelTexturePointDef s ) = > s . Path = = graphicbaseBodyFurCovered . path ) ;
if ( SizedApparelSettings . Debug & & PointsDef ! = null )
{
Log . Message ( "[SizedApparel] : FurCoveredBaseBody Texture Points Def Found : " + PointsDef . defName ) ;
}
baseBodyFurCoveredPoints = PointsDef ;
}
else
baseBodyFurCoveredPoints = null ;
2023-04-04 01:47:48 +00:00
/ *
//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 < Texture2D > . Get ( ( nakedGraphicPath + breastSeverityStringCache + "_south" ) , false ) ! = null ) )
{
if ( SizedApparelSettings . matchBodyTextureToMinimumApparelSize ? SizedApparelUtility . BreastSizeIndexToSeverity ( currentBreastSizeIndex ) < = breastSeverityCapToDraw : true )
{
nakedGraphic = GraphicDatabase . Get < Graphic_Multi > ( 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 < Texture2D > . Get ( ( rottingGraphicPath + breastSeverityStringCache + "_south" ) , false ) ! = null ) )
{
if ( SizedApparelSettings . matchBodyTextureToMinimumApparelSize ? SizedApparelUtility . BreastSizeIndexToSeverity ( currentBreastSizeIndex ) < = breastSeverityCapToDraw : true )
{
rottingGraphic = GraphicDatabase . Get < Graphic_Multi > ( 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 < Texture2D > . Get ( ( nakedGraphicPath + breastSeverityStringCache + "_south" ) , false ) ! = null ) )
{
if ( SizedApparelSettings . matchBodyTextureToMinimumApparelSize ? SizedApparelUtility . BreastSizeIndexToSeverity ( currentBreastSizeIndex ) < = breastSeverityCapToDraw : true )
{
nakedGraphic = GraphicDatabase . Get < Graphic_Multi > ( 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 < Texture2D > . Get ( ( rottingGraphicPath + breastSeverityStringCache + "_south" ) , false ) ! = null ) )
{
if ( SizedApparelSettings . matchBodyTextureToMinimumApparelSize ? SizedApparelUtility . BreastSizeIndexToSeverity ( currentBreastSizeIndex ) < = breastSeverityCapToDraw : true )
{
rottingGraphic = GraphicDatabase . Get < Graphic_Multi > ( 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");
2023-04-04 01:48:55 +00:00
if ( SizedApparelSettings . drawBodyParts ) //body parts update
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
if ( SizedApparelSettings . drawBreasts )
{
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
if ( breastHediff ! = null )
{
var breastvar = breastHediff . TryGetComp < SizedApparelBodyPartDetail > ( ) ;
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
foreach ( var addon in bodyAddons )
{
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . Breasts )
{
addon . SetHediffData ( breastHediff . def . defName , SizedApparelUtility . BreastSeverityInt ( breastHediff . Severity ) , SizedApparelUtility . BreastSeverityInt ( BreastSeverityCache ) , breastvar ? . variation ) ;
addon . SetBone ( skeleton ? . FindBone ( "Breasts" ) ) ;
addon . UpdateGraphic ( ) ;
}
}
//bodyPartBreasts.SetHediffData(breastHediff.def.defName, SizedApparelUtility.BreastSeverityInt(breastHediff.Severity), SizedApparelUtility.BreastSeverityInt(breastSeverityCapped), breastvar?.variation);
//bodyPartBreasts.UpdateGraphic();
}
else
{
foreach ( var addon in bodyAddons )
{
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . Breasts )
{
addon . SetHediffData ( null , - 1 ) ;
}
}
}
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
}
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
if ( SizedApparelSettings . drawUdder )
{
if ( udderHediff ! = null )
{
var udderVar = udderHediff . TryGetComp < SizedApparelBodyPartDetail > ( ) ;
foreach ( var addon in bodyAddons )
{
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . Udder )
{
addon . SetHediffData ( udderHediff . def . defName , SizedApparelUtility . BreastSeverityInt ( udderHediff . Severity ) , 1000 , udderVar ? . variation ) ;
addon . SetBone ( skeleton ? . FindBone ( "Udder" ) ) ;
addon . UpdateGraphic ( ) ;
}
}
//bodyPartUdder.SetHediffData(udderHediff.def.defName, SizedApparelUtility.BreastSeverityInt(udderHediff.Severity), 1000, udderVar?.variation);
//bodyPartUdder.UpdateGraphic();
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
}
else
{
foreach ( var addon in bodyAddons )
{
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . Udder )
{
addon . SetHediffData ( null , - 1 ) ;
}
}
}
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
}
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
if ( SizedApparelSettings . drawBelly )
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
if ( bellySeverity > = 0 )
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
//var bellyVar = breastHediff.GetComp<SizedApparelBodyPartDetail>();
string BellyVar = null ;
foreach ( var addon in bodyAddons )
{
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . Belly )
{
addon . SetHediffData ( "BellyBulge" , SizedApparelUtility . PrivatePartSeverityInt ( bellySeverity ) , 1000 , BellyVar ) ;
addon . SetBone ( skeleton ? . FindBone ( "Belly" ) ) ;
addon . UpdateGraphic ( ) ;
}
}
//bodyPartBelly.SetHediffData("BellyBulge", SizedApparelUtility.PrivatePartSeverityInt(bellySeverity), 1000, BellyVar);
//bodyPartBelly.UpdateGraphic();
2023-04-04 01:47:48 +00:00
}
else
2023-04-04 01:48:55 +00:00
{
foreach ( var addon in bodyAddons )
{
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . Belly )
{
addon . SetHediffData ( null , - 1 ) ;
}
}
}
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
}
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
if ( SizedApparelSettings . drawVagina )
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
if ( vaginaHediff ! = null )
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
var vaginaVar = vaginaHediff . TryGetComp < SizedApparelBodyPartDetail > ( ) ;
foreach ( var addon in bodyAddons )
{
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . Vagina )
{
addon . SetHediffData ( vaginaHediff . def . defName , SizedApparelUtility . PrivatePartSeverityInt ( vaginaHediff . Severity ) , 1000 , vaginaVar ? . variation ) ;
addon . SetBone ( skeleton ? . FindBone ( "Vagina" ) ) ;
addon . UpdateGraphic ( ) ;
}
}
//bodyPartVagina.SetHediffData(vaginaHediff.def.defName, SizedApparelUtility.PrivatePartSeverityInt(vaginaHediff.Severity), 1000, vaginaVar?.variation);
//bodyPartVagina.UpdateGraphic();
2023-04-04 01:47:48 +00:00
}
else
{
2023-04-04 01:48:55 +00:00
foreach ( var addon in bodyAddons )
{
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . Vagina )
{
addon . SetHediffData ( null , - 1 ) ;
}
}
2023-04-04 01:47:48 +00:00
}
2023-04-04 01:48:55 +00:00
}
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
if ( SizedApparelSettings . drawPubicHair )
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
if ( pubicHairDef ! = null & & pubicHairDef . defName ! = "None" ) // pubicHairDef != null // for testing
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
foreach ( var addon in bodyAddons )
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . PubicHair )
{
addon . SetHediffData ( pubicHairDef . defName , 0 , 1000 , null ) ;
addon . SetBone ( skeleton ? . FindBone ( "PubicHair" ) ) ;
addon . UpdateGraphic ( ) ;
}
2023-04-04 01:47:48 +00:00
}
2023-04-04 01:48:55 +00:00
//bodyPartPubicHair.SetHediffData(pubicHairDef.defName, 0, 1000, null);
//bodyPartPubicHair.UpdateGraphic();
2023-04-04 01:47:48 +00:00
}
2023-04-04 01:48:55 +00:00
else
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
foreach ( var addon in bodyAddons )
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . PubicHair )
{
addon . SetHediffData ( null , - 1 ) ;
}
2023-04-04 01:47:48 +00:00
}
}
2023-04-04 01:48:55 +00:00
}
if ( SizedApparelSettings . drawPenis )
{
//TODO: Optimize.... memory leak issue?
//bodyPartPenises.Clear();
//bodyPartBalls.Clear();
if ( ! penisHediffs . NullOrEmpty ( ) )
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
var penisHediff = penisHediffs [ 0 ] ;
if ( penisHediff ! = null )
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
var penisVar = penisHediff . TryGetComp < SizedApparelBodyPartDetail > ( ) ;
foreach ( var addon in bodyAddons )
{
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . Penis )
{
addon . SetHediffData ( penisHediff . def . defName , SizedApparelUtility . PrivatePartSeverityInt ( penisHediff . Severity ) , 1000 , penisVar ? . variation ) ;
addon . SetBone ( skeleton ? . FindBone ( "Penis" ) ) ;
addon . UpdateGraphic ( ) ;
}
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . Balls )
{
addon . SetHediffData ( penisHediff . def . defName , SizedApparelUtility . PrivatePartSeverityInt ( penisHediff . Severity ) , 1000 , penisVar ? . variation ) ;
addon . SetBone ( skeleton ? . FindBone ( "Balls" ) ) ;
addon . UpdateGraphic ( ) ;
}
}
2023-04-04 01:47:48 +00:00
}
else
2023-04-04 01:48:55 +00:00
{
foreach ( var addon in bodyAddons )
{
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . Penis )
{
addon . SetHediffData ( null , - 1 ) ;
}
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . Balls )
{
addon . SetHediffData ( null , - 1 ) ;
}
}
}
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
// Multiple Penis Drawing. obsolte
/ *
for ( int i = 0 ; i < penisHediffs . Count ; i + + )
{
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 ;
Bone penisBone = null ;
Bone ballsBone = null ;
if ( skeleton ! = null )
{
penisBone = skeleton . FindBone ( "Penis" ) ;
ballsBone = skeleton . FindBone ( "Balls" ) ;
if ( ballsBone = = null )
ballsBone = penisBone ;
}
var penisVar = penisHediff . TryGetComp < SizedApparelBodyPartDetail > ( ) ;
SizedApparelBodyPart penis = new SizedApparelBodyPart ( pawn , this , "Penis" , SizedApparelBodyPartOf . Penis , "Penis" , false , false , null , ColorType . Skin , penisBone ) ;
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 . centeredTexture = true ; // Test Bone
penis . UpdateGraphic ( ) ;
bodyPartPenises . Add ( penis ) ;
SizedApparelBodyPart balls = new SizedApparelBodyPart ( pawn , this , "Balls" , SizedApparelBodyPartOf . Balls , "Penis" , false , false , "Penis/Balls" , ColorType . Skin , ballsBone ) ;
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 . centeredTexture = true ; // Test Bone
balls . UpdateGraphic ( ) ;
bodyPartBalls . Add ( balls ) ;
* /
2023-04-04 01:47:48 +00:00
}
}
2023-04-04 01:48:55 +00:00
else
{
bodyPartPenises . Clear ( ) ;
bodyPartBalls . Clear ( ) ;
}
2023-04-04 01:47:48 +00:00
2023-04-04 01:48:55 +00:00
if ( SizedApparelSettings . drawAnus )
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
/ *
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 )
2023-04-04 01:47:48 +00:00
{
2023-04-04 01:48:55 +00:00
var anusVar = anusHediff . TryGetComp < SizedApparelBodyPartDetail > ( ) ;
foreach ( var addon in bodyAddons )
{
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . Anus )
{
addon . SetHediffData ( anusHediff . def . defName , SizedApparelUtility . PrivatePartSeverityInt ( anusHediff . Severity ) , 1000 , anusVar ? . variation ) ;
addon . SetBone ( skeleton ? . FindBone ( "Anus" ) ) ;
addon . UpdateGraphic ( ) ;
}
}
2023-04-04 01:47:48 +00:00
}
else
{
2023-04-04 01:48:55 +00:00
foreach ( var addon in bodyAddons )
{
if ( addon . bodyPartOf = = SizedApparelBodyPartOf . Anus )
{
addon . SetHediffData ( null , - 1 ) ;
}
}
2023-04-04 01:47:48 +00:00
}
}
2023-04-04 01:48:55 +00:00
}
2023-04-04 01:47:48 +00:00
hasGraphicUpdatedBefore = true ;
}
if ( CheckApparel )
cachedApparelGraphicRecord = pawnRenderer . apparelGraphics . ToList ( ) ;
else
cachedApparelGraphicRecord = new List < ApparelGraphicRecord > ( ) ;
hasUpdateBeforeSuccess = true ;
2023-04-04 01:48:55 +00:00
this . isHediffDirty = false ;
this . isApparelDirty = false ;
this . isSkeletonDirty = false ;
2023-04-04 01:47:48 +00:00
}
//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 < SizedApparelBodyPart > 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 ;
}
2023-04-04 01:48:55 +00:00
foreach ( SizedApparelBodyPart bp in bodyAddons )
{
yield return bp ;
}
2023-04-04 01:47:48 +00:00
}
public IEnumerable < SizedApparelBodyPart > 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 )
{
2023-04-04 01:48:55 +00:00
if ( poseSetName . NullOrEmpty ( ) )
2023-04-04 01:47:48 +00:00
{
ClearAllPose ( autoUpdate , autoSetPawnGraphicDirty ) ;
return ;
}
var poseSetDef = DefDatabase < SizedApparelPoseSetDef > . 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 ;
}
}
}