rimworld-animations-patch_m.../Source/Scripts/Utilities/ApparelAnimationUtility.cs

161 lines
6.4 KiB
C#

using System.Collections.Generic;
using System.Linq;
using Verse;
using RimWorld;
using Verse.AI.Group;
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.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 RJWPreferenceSettings.Clothing GetClothingPreference(Pawn pawn)
{
var clothingPreference = pawn.IsInBed(out Building bed) ? RJWPreferenceSettings.sex_wear : ApparelSettings.apparelWornForQuickies;
if (xxx.has_quirk(pawn, "Endytophile"))
{ clothingPreference = RJWPreferenceSettings.Clothing.Clothed; }
return clothingPreference;
}
public static void DetermineApparelToKeepOn(Pawn pawn)
{
if (pawn?.apparel?.WornApparel == null) return;
foreach (Apparel apparel in pawn.apparel.WornApparel)
{
CompApparelVisibility comp = apparel.TryGetComp<CompApparelVisibility>();
if (comp != null) comp.isBeingWorn = true;
}
ActorAnimationData animData = pawn.GetAnimationData();
var clothingPreference = GetClothingPreference(pawn);
// Get naked for rituals and parties
bool undressForRitual = pawn.GetLord() != null && pawn.GetLord().LordJob is LordJob_Ritual;
bool undressForParty = pawn.GetLord() != null && pawn.GetLord().LordJob is LordJob_Joinable_Party;
// 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 (ApparelSettingsUtility.GetRimNudeData(apparel)?.sexWear == true) continue;
if (clothingPreference == RJWPreferenceSettings.Clothing.Nude || undressForRitual || undressForParty)
{
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 (animData != null && ApparelCoversPawnRequiredBodyParts(pawn, apparel, animData.animationDef, animData.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.ContainsAny("mouth", "teeth", "jaw", "beak", "Mouth", "Teeth", "Jaw", "Beak"))); }
return bodyPartCovered;
}
}
}