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

198 lines
7.7 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(compApparelVisibility.rotation.ToString());
//DebugMode.Message("Drawing " + apparel.def.defName + " on ground");
}
}
}
}
public static bool BodyAddonCoveredByApparel(Apparel apparel, AlienPartGenerator.BodyAddon bodyAddon)
{
CompApparelVisibility comp = apparel.TryGetComp<CompApparelVisibility>();
if (comp != null && comp.isBeingWorn == false)
{ return false; }
RimNudeData rimNudeData = ApparelSettings.GetRimNudeData(apparel);
if (rimNudeData != null && bodyAddon?.bodyPart != null)
{
if (bodyAddon.bodyPart == "Genitals" && rimNudeData.coversGroin == false)
{ return false; }
if (bodyAddon.bodyPart == "Chest" && rimNudeData.coversChest == false)
{ return false; }
if (bodyAddon.bodyPart == "Torso" && rimNudeData.coversBelly == false)
{ return false; }
}
if (apparel.def.apparel.bodyPartGroups.Any(x => bodyAddon.hiddenUnderApparelFor.Contains(x)) ||
apparel.def.apparel.tags.Any(x => bodyAddon.hiddenUnderApparelTag.Contains(x)))
{ return true; }
return false;
}
public static bool BodyPartCoveredByApparel(Apparel apparel, BodyPartRecord bodyPart)
{
CompApparelVisibility comp = apparel.TryGetComp<CompApparelVisibility>();
if (comp != null && comp.isBeingWorn == false)
{ return false; }
RimNudeData rimNudeData = ApparelSettings.GetRimNudeData(apparel);
if (rimNudeData != null)
{
if (bodyPart.def.defName == "Genitals" && rimNudeData.coversGroin == false)
{ return false; }
if (bodyPart.def.defName == "Chest" && rimNudeData.coversChest == false)
{ return false; }
if (bodyPart.def.defName == "Torso" && rimNudeData.coversBelly == false)
{ return false; }
}
if (apparel.def.apparel.CoversBodyPart(bodyPart))
{ return true; }
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 || BodyPartCoveredByApparel(apparel, bodyParts.FirstOrDefault(x => x.def == xxx.genitalsDef)); }
if (anim.actors[actorID].isFucked || requiredGenitals.Contains("Vagina"))
{ bodyPartCovered = bodyPartCovered || BodyPartCoveredByApparel(apparel, bodyParts.FirstOrDefault(x => x.def == xxx.genitalsDef)); }
if (anim.actors[actorID].isFucked || requiredGenitals.Contains("Anus"))
{ bodyPartCovered = bodyPartCovered || BodyPartCoveredByApparel(apparel, bodyParts.FirstOrDefault(x => x.def == xxx.anusDef)); }
if (requiredGenitals.Contains("Breasts"))
{ bodyPartCovered = bodyPartCovered || BodyPartCoveredByApparel(apparel, bodyParts.FirstOrDefault(x => x.def == xxx.breastsDef)); }
if (requiredGenitals.Contains("Mouth"))
{ bodyPartCovered = bodyPartCovered || BodyPartCoveredByApparel(apparel, bodyParts.FirstOrDefault(x => x.def.defName.ToLower().ContainsAny("mouth", "teeth", "jaw", "beak"))); }
return bodyPartCovered;
}
}
}