mirror of
https://gitgud.io/AbstractConcept/rimworld-animations-patch.git
synced 2024-08-15 00:43:27 +00:00
161 lines
6.3 KiB
C#
161 lines
6.3 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 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 = pawn.IsInBed(out Building bed) ? RJWPreferenceSettings.sex_wear : ApparelSettings.apparelWornForQuickies;
|
|
|
|
if (xxx.has_quirk(pawn, "Endytophile"))
|
|
{ clothingPreference = RJWPreferenceSettings.Clothing.Clothed; }
|
|
|
|
// 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 (ApparelSettings.GetRimNudeData(apparel) != null && ApparelSettings.GetRimNudeData(apparel).sexWear)
|
|
{ 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.ToLower().ContainsAny("mouth", "teeth", "jaw", "beak"))); }
|
|
|
|
return bodyPartCovered;
|
|
}
|
|
}
|
|
}
|