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

171 lines
5.1 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using RimWorld;
using UnityEngine;
using HarmonyLib;
using Verse;
using Rimworld_Animations;
using rjw;
namespace Rimworld_Animations_Patch
{
public static class AnimationPatchUtility
{
public static int FindTrueAnimationLength(Pawn pawn, out int orgasmTick)
{
orgasmTick = int.MaxValue;
ActorAnimationData actorAnimationData = pawn.GetAnimationData();
CompBodyAnimator compBodyAnimator = pawn.TryGetComp<CompBodyAnimator>();
// No data
if (actorAnimationData == null || compBodyAnimator == null)
{
DebugMode.Message("There is no actor animation data for " + pawn.NameShortColored);
orgasmTick = 1500 + (int)(Rand.Value * 1000f);
return orgasmTick;
}
AnimationDef anim = actorAnimationData.animationDef;
int actorId = actorAnimationData.actorID;
bool isQuickie = compBodyAnimator.fastAnimForQuickie;
int ticks = 0;
foreach (AnimationStage animStage in anim.animationStages)
{
// Legacy: skip the first stage of quickies if there's no playTimeTicksQuick values declared
if (anim.animationStages.IndexOf(animStage) == 0 && isQuickie && anim.animationStages.Any(x => x.playTimeTicksQuick >= 0) == false)
{ continue; }
int curr_tick = 0;
foreach (PawnKeyframe keyframe in (animStage.animationClips[actorId] as PawnAnimationClip).keyframes)
{
curr_tick += keyframe.tickDuration;
if (keyframe.soundEffect != null && keyframe.soundEffect == "Cum" && orgasmTick > (ticks + curr_tick))
{ orgasmTick = ticks + curr_tick; }
if (isQuickie && animStage.playTimeTicksQuick > 0 && curr_tick >= animStage.playTimeTicksQuick)
{ break; }
}
ticks += isQuickie && animStage.playTimeTicksQuick > 0 && animStage.playTimeTicksQuick < animStage.playTimeTicks ? animStage.playTimeTicksQuick : animStage.playTimeTicks;
}
// Orgasm tick not found
if (orgasmTick > ticks)
{
// Safeguard for penial, vaginal and anal sex
if (anim.actors[actorId].isFucked || anim.actors[actorId].isFucking || anim.actors[actorId].requiredGenitals.Any(x => x.ToLower().ContainsAny("penis", "vagina", "anus")))
{ orgasmTick = Mathf.Clamp(ticks - 5, 0, int.MaxValue); }
// Actor does not orgasm
else
{ orgasmTick = (int)(ticks * (2f + Rand.Value)); }
}
return ticks;
}
// Extended version of PawnHeadRotInAnimation (prevents pawn hair from getting messed up when draw in portraits)
public static Rot4 PawnHeadRotInAnimation(Pawn pawn, Rot4 regularPos, PawnRenderFlags renderFlags)
{
if (!renderFlags.FlagSet(PawnRenderFlags.Portrait) && pawn?.TryGetComp<CompBodyAnimator>() != null && pawn.TryGetComp<CompBodyAnimator>().isAnimating)
{
return pawn.TryGetComp<CompBodyAnimator>().headFacing;
}
return regularPos;
}
public static BodyPartRecord GetBodyPartRecord(Pawn pawn, string bodyPart)
{
if (bodyPart.NullOrEmpty())
{ return null; }
return pawn.health.hediffSet.GetNotMissingParts(BodyPartHeight.Undefined, BodyPartDepth.Undefined, null, null).FirstOrDefault(x => x.untranslatedCustomLabel == bodyPart || x.def.defName == bodyPart);
}
public static Vector3 GetAnchorPosition(Pawn pawn, Thing thing = null)
{
Vector3 anchor;
if (thing == null)
{ return pawn.Position.ToVector3Shifted(); }
int numOfSleepingSlots = 0;
if (thing is Building_Bed)
{ numOfSleepingSlots = BedUtility.GetSleepingSlotsCount(thing.def.size); }
// Anchor to the pawn's sleeping slot when masturbating in own bed
if (thing is Building_Bed && (pawn.ownership.OwnedBed == thing || pawn.CurrentBed() == thing) && pawn.IsMasturbating())
{
anchor = RestUtility.GetBedSleepingSlotPosFor(pawn, thing as Building_Bed).ToVector3();
if (thing.Rotation.AsInt == 0)
{
anchor.x += 0.5f;
anchor.z += 1f;
}
else if (thing.Rotation.AsInt == 1)
{
anchor.x += 1f;
anchor.z += 0.5f;
}
else if (thing.Rotation.AsInt == 2)
{
anchor.x += 0.5f;
anchor.z += 0.5f;
}
else if (thing.Rotation.AsInt == 3)
{
anchor.x += 0f;
anchor.z += 0.5f;
}
}
// Anchor to the center of the bed (should work for beds of any size?)
else if (thing is Building_Bed && numOfSleepingSlots > 0)
{
anchor = thing.Position.ToVector3();
float halfSlots = numOfSleepingSlots / 2f;
if (thing.Rotation.AsInt == 0)
{
anchor.x += halfSlots;
anchor.z += 1f;
}
else if (thing.Rotation.AsInt == 1)
{
anchor.x += 1f;
anchor.z += (1.0f - halfSlots);
}
else if (thing.Rotation.AsInt == 2)
{
anchor.x += (1f - halfSlots);
anchor.z += 0f;
}
else if (thing.Rotation.AsInt == 3)
{
anchor.x += 0f;
anchor.z += halfSlots;
}
}
// Anchor to the centre of the thing
else
{
anchor = thing.Position.ToVector3Shifted();
}
return anchor;
}
}
}