rimworld-animations-patch_m.../Source/Scripts/Defs/BodyAddonData.cs

211 lines
9.1 KiB
C#
Raw Normal View History

2022-09-30 23:34:08 +00:00
using System;
using System.Collections.Generic;
using System.Linq;
using Verse;
using RimWorld;
using AlienRace;
using Rimworld_Animations;
using UnityEngine;
using HarmonyLib;
namespace Rimworld_Animations_Patch
{
public class BodyAddonData
{
public AlienPartGenerator.BodyAddon bodyAddon;
public BodyPartRecord bodyPartRecord;
public List<Vector3> bodyAddonOffsets = new List<Vector3>();
public bool alignsWithHead = false;
2023-02-04 07:13:57 +00:00
2022-09-30 23:34:08 +00:00
private Pawn pawn;
private string bodyType;
private PawnRenderFlags renderFlags;
private bool canDraw = false;
2022-10-01 03:51:09 +00:00
private bool bodyPartMissing = false;
2023-02-06 00:41:57 +00:00
2022-09-30 23:34:08 +00:00
public BodyAddonData(Pawn pawn, AlienPartGenerator.BodyAddon bodyAddon, bool isPortrait = false)
{
this.pawn = pawn;
this.bodyAddon = bodyAddon;
2023-02-06 00:41:57 +00:00
2022-09-30 23:34:08 +00:00
if (isPortrait)
{ renderFlags |= PawnRenderFlags.Portrait; }
2022-10-02 02:14:35 +00:00
2023-02-04 07:13:57 +00:00
bodyPartRecord = pawn.def?.race?.body?.AllParts?.FirstOrDefault(x => x.def == bodyAddon?.bodyPart);
2022-09-30 23:34:08 +00:00
alignsWithHead = bodyAddon.alignWithHead || (bodyPartRecord != null && bodyPartRecord.IsInGroup(BodyPartGroupDefOf.FullHead));
2022-10-02 02:14:35 +00:00
2022-09-30 23:34:08 +00:00
GenerateOffsets();
UpdateVisibility();
}
public void GenerateOffsets()
{
bodyType = pawn.story.bodyType.defName;
bodyAddonOffsets.Clear();
2023-02-06 00:41:57 +00:00
2023-02-04 07:13:57 +00:00
int bodyAddonIndex = (pawn.def as ThingDef_AlienRace).alienRace.generalSettings.alienPartGenerator.bodyAddons.IndexOf(bodyAddon);
2022-09-30 23:34:08 +00:00
AlienPartGenerator.AlienComp alienComp = pawn.GetComp<AlienPartGenerator.AlienComp>();
Graphic addonGraphic = alienComp.addonGraphics[bodyAddonIndex];
2023-02-06 00:41:57 +00:00
2022-09-30 23:34:08 +00:00
for (int i = 0; i < 4; i++)
{
Rot4 apparentRotation = new Rot4(i);
// Get basic offset for body addon
AlienPartGenerator.RotationOffset defaultOffsets = bodyAddon.defaultOffsets.GetOffset(apparentRotation);
2023-02-04 07:13:57 +00:00
Vector3 bodyTypeOffset = (defaultOffsets != null) ? defaultOffsets.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, pawn.story.headType) : Vector3.zero;
2023-02-06 00:41:57 +00:00
AlienPartGenerator.RotationOffset rotationOffsets = bodyAddon.offsets.GetOffset(apparentRotation);
2023-02-04 07:13:57 +00:00
Vector3 bodyAddonOffset = bodyTypeOffset + ((rotationOffsets != null) ? rotationOffsets.GetOffset(renderFlags.FlagSet(PawnRenderFlags.Portrait), pawn.story.bodyType, pawn.story.headType) : Vector3.zero);
2022-09-30 23:34:08 +00:00
// Offset private parts so that they render over tattoos but under apparel (rendering under tatoos looks weird)
2023-02-04 07:13:57 +00:00
if (bodyAddon.bodyPart == PatchBodyPartDefOf.Genitals || bodyAddon.bodyPart == PatchBodyPartDefOf.Chest || bodyAddon.bodyPart == PatchBodyPartDefOf.Anus || addonGraphic.path.Contains("belly") || addonGraphic.path.Contains("Belly"))
2022-09-30 23:34:08 +00:00
{
bodyAddonOffset.y = (bodyAddonOffset.y + 0.40f) / 1000f + 0.012f;
// Erected penises should be drawn over apparel
if (pawn.RaceProps.Humanlike &&
2023-02-06 00:41:57 +00:00
addonGraphic.path.Contains("penis", StringComparison.OrdinalIgnoreCase) &&
(addonGraphic.path.Contains("flaccid", StringComparison.OrdinalIgnoreCase) == false) &&
2022-09-30 23:34:08 +00:00
apparentRotation == Rot4.South)
{ bodyAddonOffset.y += 0.010f; }
}
// Otherwise use the standard offsets
else
{ bodyAddonOffset.y = 0.3f + bodyAddonOffset.y; }
2023-02-06 00:41:57 +00:00
2022-09-30 23:34:08 +00:00
// Draw addons infront of body
if (!bodyAddon.inFrontOfBody)
{ bodyAddonOffset.y *= -1f; }
2023-02-06 00:41:57 +00:00
2022-09-30 23:34:08 +00:00
// Adjust for facing
if (apparentRotation == Rot4.North)
{
if (bodyAddon.layerInvert)
{ bodyAddonOffset.y = -bodyAddonOffset.y; }
}
2023-02-06 00:41:57 +00:00
2022-09-30 23:34:08 +00:00
if (apparentRotation == Rot4.East)
{ bodyAddonOffset.x = -bodyAddonOffset.x; }
2023-02-06 00:41:57 +00:00
2022-09-30 23:34:08 +00:00
// Adjustment for body addons attached to the head that are not marked as such
if (alignsWithHead && bodyAddon.alignWithHead == false)
{ bodyAddonOffset -= pawn.Drawer.renderer.BaseHeadOffsetAt(apparentRotation); }
// Done
bodyAddonOffsets.Add(bodyAddonOffset);
}
}
public Vector3 GetOffset(Rot4 facing)
{
if (pawn.story.bodyType.defName != bodyType)
{ GenerateOffsets(); }
2023-02-06 00:41:57 +00:00
2022-09-30 23:34:08 +00:00
return bodyAddonOffsets[facing.AsInt];
2023-02-06 00:41:57 +00:00
}
2022-09-30 23:34:08 +00:00
public bool CanDraw()
{
2022-10-01 03:51:09 +00:00
return bodyPartMissing == false && SitutationalVisibiltyCheck() && (pawn.Drawer.renderer.graphics.apparelGraphics.Any() == false || canDraw);
2022-09-30 23:34:08 +00:00
}
2022-10-01 03:51:09 +00:00
public bool SitutationalVisibiltyCheck()
{
if (pawn == null || bodyAddon == null) return false;
2022-09-30 23:34:08 +00:00
2022-10-02 02:14:35 +00:00
if (renderFlags.FlagSet(PawnRenderFlags.Portrait) == false && pawn.CurrentBed()?.def.building.bed_showSleeperBody == false && bodyAddon.drawnInBed == false)
{ return false; }
if (renderFlags.FlagSet(PawnRenderFlags.Portrait) == false && (pawn.GetPosture() == PawnPosture.LayingOnGroundNormal || pawn.GetPosture() == PawnPosture.LayingOnGroundFaceUp) && bodyAddon.drawnOnGround == false)
2022-10-01 03:51:09 +00:00
{ return false; }
2022-09-30 23:34:08 +00:00
2023-02-04 07:13:57 +00:00
if (bodyAddon.backstoryRequirement != null && pawn.story?.AllBackstories?.Any((BackstoryDef x) => x == bodyAddon.backstoryRequirement) == false)
2022-10-01 03:51:09 +00:00
{ return false; }
2022-09-30 23:34:08 +00:00
2022-10-01 03:51:09 +00:00
if (bodyAddon.drawnDesiccated == false && pawn.Corpse?.GetRotStage() == RotStage.Dessicated)
{ return false; }
2022-09-30 23:34:08 +00:00
if (pawn.gender == Gender.Female && bodyAddon.drawForFemale == false || pawn.gender == Gender.Male && bodyAddon.drawForMale == false)
2022-10-01 03:51:09 +00:00
{ return false; }
2022-09-30 23:34:08 +00:00
2023-02-04 07:13:57 +00:00
if (bodyAddon.bodyTypeRequirement != null && pawn.story?.bodyType != bodyAddon.bodyTypeRequirement)
2022-10-01 03:51:09 +00:00
{ return false; }
2022-09-30 23:34:08 +00:00
2022-10-01 03:51:09 +00:00
return true;
}
public void UpdateVisibility()
{
canDraw = true;
if (pawn == null || bodyAddon == null || bodyPartRecord == null) return;
2022-10-01 03:51:09 +00:00
if (pawn.health?.hediffSet?.GetNotMissingParts()?.Contains(bodyPartRecord) == false)
{ bodyPartMissing = true; return; }
2022-09-30 23:34:08 +00:00
2022-10-02 02:14:35 +00:00
if (pawn?.apparel?.WornApparel == null || pawn.apparel.WornApparel.NullOrEmpty())
{ return; }
2023-02-06 00:41:57 +00:00
2022-09-30 23:34:08 +00:00
foreach (Apparel apparel in pawn.apparel.WornApparel)
{
2022-10-01 03:51:09 +00:00
CompApparelVisibility comp = apparel?.TryGetComp<CompApparelVisibility>();
if (comp == null) continue;
2022-09-30 23:34:08 +00:00
LoadRimNudeData(comp);
if (comp.isBeingWorn == false) continue;
2023-02-06 00:41:57 +00:00
if (bodyAddon.bodyPart == PatchBodyPartDefOf.Genitals ||
bodyAddon.bodyPart == PatchBodyPartDefOf.Anus ||
bodyAddon.bodyPart == PatchBodyPartDefOf.Chest ||
bodyAddon.hediffGraphics?.Any(x => x.path.NullOrEmpty() == false && x.path.Contains("belly", StringComparison.OrdinalIgnoreCase)) == true)
2022-09-30 23:34:08 +00:00
{
2023-02-04 07:13:57 +00:00
if ((bodyAddon.bodyPart == PatchBodyPartDefOf.Genitals || bodyAddon.bodyPart == PatchBodyPartDefOf.Anus) && comp.coversGroin)
2022-09-30 23:34:08 +00:00
{ canDraw = false; return; };
2023-02-04 07:13:57 +00:00
if (bodyAddon.bodyPart == PatchBodyPartDefOf.Chest && comp.coversChest)
2022-09-30 23:34:08 +00:00
{ canDraw = false; return; };
if (bodyAddon.hediffGraphics?.Any(x => x.path.NullOrEmpty() == false && x.path.Contains("belly", StringComparison.OrdinalIgnoreCase)) == true && comp.coversBelly)
2022-09-30 23:34:08 +00:00
{ canDraw = false; return; }
}
else if (apparel.def.apparel.hatRenderedFrontOfFace || apparel.def.apparel.hatRenderedAboveBody || apparel.def.apparel.hatRenderedBehindHead)
{ return; }
2022-09-30 23:34:08 +00:00
else
{
if (bodyAddon.hiddenUnderApparelFor?.Any(x => apparel.def.apparel.bodyPartGroups?.Contains(x) == true) == true)
2022-09-30 23:34:08 +00:00
{ canDraw = false; return; };
if (bodyAddon.hiddenUnderApparelTag?.Any(x => apparel.def.apparel.tags?.Contains(x) == true) == true)
2022-09-30 23:34:08 +00:00
{ canDraw = false; return; };
}
}
}
public void LoadRimNudeData(CompApparelVisibility comp)
{
2022-10-01 03:51:09 +00:00
if (comp?.rimNudeDataStatus == RimNudeDataStatus.Unavailable)
2022-09-30 23:34:08 +00:00
{ return; }
2022-10-01 03:51:09 +00:00
if (comp?.rimNudeDataStatus == RimNudeDataStatus.NotLoaded)
2022-09-30 23:34:08 +00:00
{
RimNudeData rimNudeData = ApparelSettingsUtility.GetRimNudeData(comp?.apparel);
2022-09-30 23:34:08 +00:00
if (rimNudeData == null)
{
comp.rimNudeDataStatus = RimNudeDataStatus.Unavailable;
return;
}
comp.coversBelly = rimNudeData.coversBelly;
comp.coversChest = rimNudeData.coversChest;
comp.coversGroin = rimNudeData.coversGroin;
comp.rimNudeDataStatus = RimNudeDataStatus.Loaded;
}
}
}
2023-02-06 00:41:57 +00:00
}