182 lines
6.8 KiB
C#
182 lines
6.8 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Verse;
|
|
using RimWorld;
|
|
using Rimworld_Animations;
|
|
using UnityEngine;
|
|
using AlienRace;
|
|
using rjw;
|
|
|
|
namespace Rimworld_Animations_Patch
|
|
{
|
|
public static class ApparelAnimationUtility
|
|
{
|
|
public static float apparelScale = 0.75f;
|
|
|
|
public static void TryToDrawApparelOnFloor(Pawn pawn)
|
|
{
|
|
if (pawn?.apparel?.WornApparel != null)
|
|
{
|
|
CompBodyAnimator compBodyAnimator = pawn.TryGetComp<CompBodyAnimator>();
|
|
|
|
if (ApparelSettings.clothesThrownOnGround == false || Find.CurrentMap != pawn.Map || compBodyAnimator == null || compBodyAnimator.isAnimating == false)
|
|
{ return; }
|
|
|
|
foreach (Apparel apparel in pawn.apparel.WornApparel)
|
|
{
|
|
CompApparelVisibility compApparelVisibility = apparel.TryGetComp<CompApparelVisibility>();
|
|
|
|
if (compApparelVisibility != null && compApparelVisibility.position != default && compApparelVisibility.isBeingWorn == false)
|
|
{
|
|
Graphic apparelGraphic = apparel.Graphic;
|
|
apparelGraphic.drawSize.x *= apparelScale;
|
|
apparelGraphic.drawSize.y *= apparelScale;
|
|
|
|
GenDraw.DrawMeshNowOrLater(mesh: apparelGraphic.MeshAt(rot: apparel.Rotation),
|
|
loc: compApparelVisibility.position,
|
|
quat: Quaternion.AngleAxis(angle: compApparelVisibility.rotation, axis: Vector3.up),
|
|
mat: apparelGraphic.MatAt(rot: apparel.Rotation),
|
|
false);
|
|
|
|
apparelGraphic.drawSize.x *= 1f / apparelScale;
|
|
apparelGraphic.drawSize.y *= 1f / apparelScale;
|
|
|
|
//DebugMode.Message("Drawing " + apparel.def.defName + " on ground");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static bool PrivatePartCoveredByApparel(Apparel apparel, string bodyPart)
|
|
{
|
|
CompApparelVisibility comp = apparel.TryGetComp<CompApparelVisibility>();
|
|
|
|
if (comp == null || comp.rimNudeDataStatus == RimNudeDataStatus.Unavailable)
|
|
{ return false; }
|
|
|
|
if (comp.rimNudeDataStatus == RimNudeDataStatus.NotLoaded)
|
|
{
|
|
RimNudeData rimNudeData = ApparelSettings.GetRimNudeData(apparel);
|
|
|
|
if (rimNudeData == null)
|
|
{
|
|
comp.rimNudeDataStatus = RimNudeDataStatus.Unavailable;
|
|
return false;
|
|
}
|
|
|
|
comp.coversBelly = rimNudeData.coversBelly;
|
|
comp.coversChest = rimNudeData.coversChest;
|
|
comp.coversGroin = rimNudeData.coversGroin;
|
|
|
|
comp.rimNudeDataStatus = RimNudeDataStatus.Loaded;
|
|
}
|
|
|
|
if (comp.isBeingWorn == false)
|
|
{ return false; }
|
|
|
|
if (bodyPart == "Genitals")
|
|
{ return comp.coversGroin; }
|
|
|
|
if (bodyPart == "Chest")
|
|
{ return comp.coversChest; }
|
|
|
|
if (bodyPart == "Torso")
|
|
{ return comp.coversBelly; }
|
|
|
|
return false;
|
|
}
|
|
|
|
public static void DetermineApparelToKeepOn(Pawn pawn)
|
|
{
|
|
JobDriver_Sex jobdriver = pawn.jobs.curDriver as JobDriver_Sex;
|
|
|
|
if (pawn.RaceProps.Humanlike == false || pawn?.apparel?.WornApparel == null || jobdriver == null)
|
|
{ return; }
|
|
|
|
foreach (Apparel apparel in pawn.apparel.WornApparel)
|
|
{
|
|
CompApparelVisibility comp = apparel.TryGetComp<CompApparelVisibility>();
|
|
|
|
if (comp != null)
|
|
{ comp.isBeingWorn = true; }
|
|
}
|
|
|
|
ActorAnimationData animData = pawn.GetAnimationData();
|
|
|
|
if (animData == null)
|
|
{ return; }
|
|
|
|
AnimationDef anim = animData.animationDef;
|
|
int actorID = animData.actorID;
|
|
|
|
var clothingPreference = pawn.IsInBed(out Building bed) ? RJWPreferenceSettings.sex_wear : ApparelSettings.apparelWornForQuickies;
|
|
|
|
if (xxx.has_quirk(pawn, "Endytophile"))
|
|
{ clothingPreference = RJWPreferenceSettings.Clothing.Clothed; }
|
|
|
|
// Determine any obstructing apparel that must be removed
|
|
foreach (Apparel apparel in pawn.apparel.WornApparel)
|
|
{
|
|
CompApparelVisibility comp = apparel.TryGetComp<CompApparelVisibility>();
|
|
|
|
if (comp == null)
|
|
{ continue; }
|
|
|
|
if (apparel.def is bondage_gear_def)
|
|
{ continue; }
|
|
|
|
if (ApparelSettings.GetRimNudeData(apparel) != null && ApparelSettings.GetRimNudeData(apparel).sexWear)
|
|
{ continue; }
|
|
|
|
if (clothingPreference == RJWPreferenceSettings.Clothing.Nude)
|
|
{
|
|
comp.isBeingWorn = false;
|
|
continue;
|
|
}
|
|
|
|
bool isHat = apparel.def.apparel.bodyPartGroups.NullOrEmpty() == false && (apparel.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.FullHead) || apparel.def.apparel.bodyPartGroups.Contains(BodyPartGroupDefOf.UpperHead));
|
|
|
|
if (clothingPreference == RJWPreferenceSettings.Clothing.Headgear && isHat == false)
|
|
{
|
|
comp.isBeingWorn = false;
|
|
continue;
|
|
}
|
|
|
|
if (ApparelCoversPawnRequiredBodyParts(pawn, apparel, anim, actorID))
|
|
{
|
|
comp.isBeingWorn = false;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static bool ApparelCoversPawnRequiredBodyParts(Pawn pawn, Apparel apparel, AnimationDef anim, int actorID)
|
|
{
|
|
bool bodyPartCovered = false;
|
|
|
|
IEnumerable<BodyPartRecord> bodyParts = pawn.RaceProps.body.AllParts;
|
|
|
|
var requiredGenitals = anim.actors[actorID].requiredGenitals;
|
|
|
|
if (requiredGenitals.NullOrEmpty())
|
|
{ requiredGenitals = new List<string>(); }
|
|
|
|
if (anim.actors[actorID].isFucking || requiredGenitals.Contains("Penis"))
|
|
{ bodyPartCovered = bodyPartCovered || PrivatePartCoveredByApparel(apparel, "Genitals"); }
|
|
|
|
if (anim.actors[actorID].isFucked || requiredGenitals.Contains("Vagina"))
|
|
{ bodyPartCovered = bodyPartCovered || PrivatePartCoveredByApparel(apparel, "Genitals"); }
|
|
|
|
if (anim.actors[actorID].isFucked || requiredGenitals.Contains("Anus"))
|
|
{ bodyPartCovered = bodyPartCovered || PrivatePartCoveredByApparel(apparel, "Genitals"); }
|
|
|
|
if (requiredGenitals.Contains("Breasts"))
|
|
{ bodyPartCovered = bodyPartCovered || PrivatePartCoveredByApparel(apparel, "Chest"); }
|
|
|
|
if (requiredGenitals.Contains("Mouth"))
|
|
{ bodyPartCovered = bodyPartCovered || apparel.def.apparel.CoversBodyPart(bodyParts.FirstOrDefault(x => x.def.defName.ToLower().ContainsAny("mouth", "teeth", "jaw", "beak"))); }
|
|
|
|
return bodyPartCovered;
|
|
}
|
|
}
|
|
}
|