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

220 lines
10 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Verse;
using RimWorld;
using HarmonyLib;
using Rimworld_Animations;
namespace Rimworld_Animations_Patch
{
public static class HandAnimationUtility
{
public static BodyPartDef handDef;
public static bool BodyPartIsBeingTouched(Pawn pawn, string bodypartFilePath, out List<HandAnimationData> handAnimationData)
{
handAnimationData = new List<HandAnimationData>();
ActorAnimationData actorAnimationData = pawn.GetAnimationData();
HandAnimationDef handAnimationDef = DefDatabase<HandAnimationDef>.AllDefs.FirstOrDefault(x => x.animationDefName == actorAnimationData.animationDef.defName);
if (handAnimationDef == null)
{ return false; }
foreach (HandAnimationData datum in handAnimationDef.handAnimationData)
{
if (datum.stageID != actorAnimationData.currentStage || datum.actorID != actorAnimationData.actorID)
{ continue; }
if (datum.bodySide.NullOrEmpty() == false && bodypartFilePath.ToLower().Contains(datum.bodySide) == false)
{ continue; }
if (datum.targetBodyPart.NullOrEmpty() == false && bodypartFilePath.ToLower().Contains(datum.targetBodyPart.ToLower()))
{ handAnimationData.Add(datum); }
else if (datum.targetBodyParts.Any(x => bodypartFilePath.ToLower().Contains(x.ToLower())))
{ handAnimationData.Add(datum); }
}
return handAnimationData.NullOrEmpty() == false;
}
public static Vector3 GetHandPosition(Pawn pawn, HandAnimationData handAnimationData, Vector3 basePosition, float baseAngle)
{
var methodInfo = AccessTools.Method(typeof(HandAnimationUtility), handAnimationData.motion, null, null);
if (methodInfo == null)
{
Debug.LogWarning("Hand anaimation motion '" + handAnimationData.motion + "' was not found");
return default;
}
Vector3 handPosition = (Vector3)methodInfo.Invoke(null, new object[] { pawn, handAnimationData, baseAngle });
return handPosition * pawn.RaceProps.baseBodySize + basePosition;
}
public static float GetGenitalSize(Pawn pawn, string genitalName)
{
switch(genitalName.ToLower())
{
case "penis": return pawn.health.hediffSet.hediffs.First(x => x.def.defName.ToLower().Contains("penis")).Severity;
case "breasts": return pawn.health.hediffSet.hediffs.First(x => x.def.defName.ToLower().Contains("breasts")).Severity;
case "vagina": return 0.1f;
case "anus": return 0.1f;
}
return 0.1f;
}
public static Vector3 Motion_StrokeGenitalsUpAndDownShort_FacingNS(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float p = (Mathf.PingPong(data.stageTicks, handAnimationData.cycleTime) / handAnimationData.cycleTime);
float length = 0.035f;
handPosition.x = 0;
handPosition.z = length * p;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
public static Vector3 Motion_StrokeGenitalsUpAndDown_FacingNS(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float p = (Mathf.PingPong(data.stageTicks, handAnimationData.cycleTime) / handAnimationData.cycleTime);
float size = GetGenitalSize(pawn, handAnimationData.targetBodyPart) * 0.2f;
float m = (data.actorFacing == Rot4.North ? -1f : 1f) * (handAnimationData.mirror ? -1f : 1f) * (pawn.TryGetComp<CompBodyAnimator>().Mirror ? -1f : 1f);
handPosition.x = 0.025f * m;
handPosition.z = size * p;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
public static Vector3 Motion_StrokeGenitalsUpAndDown_FacingEW(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float p = Mathf.PingPong(data.stageTicks, handAnimationData.cycleTime) / handAnimationData.cycleTime;
float size = GetGenitalSize(pawn, handAnimationData.targetBodyPart) * 0.2f;
float m = (data.actorFacing == Rot4.West ? -1f : 1f) * (handAnimationData.mirror ? -1f : 1f);
handPosition.x = Mathf.Sin(m * (baseAngle + 45f) / 180f * Mathf.PI) * size * p;
handPosition.z = Mathf.Cos(m * (baseAngle + 45f) / 180f * Mathf.PI) * size * p;
return handPosition;
}
public static Vector3 Motion_RubGenitals_FacingNS(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float a = ((float)data.stageTicks % (float)handAnimationData.cycleTime) / (float)handAnimationData.cycleTime * 360f;
float m = (data.actorFacing == Rot4.North ? 1f : -1f) * (handAnimationData.mirror ? -1f : 1f) * (pawn.TryGetComp<CompBodyAnimator>().Mirror ? -1f : 1f);
handPosition.x = (Mathf.Sin(a / 180f * Mathf.PI) * 0.05f - 0.025f) * m;
handPosition.z = Mathf.Cos(a / 180f * Mathf.PI) * 0.015f + 0.03f;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
public static Vector3 Motion_RubGenitals_FacingEW(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float a = ((float)data.stageTicks % (float)handAnimationData.cycleTime) / (float)handAnimationData.cycleTime * 360f;
float m = (data.actorFacing == Rot4.West ? 1f : -1f) * (handAnimationData.mirror ? -1f : 1f);
handPosition.x = (Mathf.Sin(a / 180f * Mathf.PI) * 0.005f - 0.05f) * m;
handPosition.z = Mathf.Cos(a / 180f * Mathf.PI) * 0.015f;
//handPosition.y = -0.1f;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
public static Vector3 Motion_RubBreasts_FacingNS(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float a = ((float)data.stageTicks % (float)handAnimationData.cycleTime) / (float)handAnimationData.cycleTime * 360f;
float m = (data.actorFacing == Rot4.North ? -1f : 1f) * (handAnimationData.mirror ? -1f : 1f) * (pawn.TryGetComp<CompBodyAnimator>().Mirror ? -1f : 1f);
float size = GetGenitalSize(pawn, "breasts");
handPosition.x = (Mathf.Sin(a / 180f * Mathf.PI) * 0.05f * size - size * 0.25f) * m;
handPosition.z = Mathf.Cos(a / 180f * Mathf.PI) * 0.015f - size * 0.125f;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
public static Vector3 Motion_RubBreasts_FacingEW(Pawn pawn, HandAnimationData handAnimationData, float baseAngle)
{
Vector3 handPosition = new Vector3();
ActorAnimationData data = pawn.GetAnimationData();
float a = ((float)data.stageTicks % (float)handAnimationData.cycleTime) / (float)handAnimationData.cycleTime * 360f;
float m = (data.actorFacing == Rot4.West ? 1f : -1f) * (handAnimationData.mirror ? -1f : 1f);
float size = GetGenitalSize(pawn, "breasts");
handPosition.x = (Mathf.Sin(a / 180f * Mathf.PI) * 0.005f - size * 0.25f) * m;
handPosition.z = Mathf.Cos(a / 180f * Mathf.PI) * 0.015f - size * 0.125f;
handPosition = handPosition.RotatedBy(baseAngle);
return handPosition;
}
public static Graphic GetHandGraphic(Pawn touchingPawn, string touchedBodyAddonName, HandAnimationData handAnimationData)
{
string handGraphicPath = "Hands/HandClean";
Color skinColour = touchingPawn.story.SkinColor;
float handSize = 0.6667f * touchingPawn.RaceProps.baseBodySize;
return GraphicDatabase.Get<Graphic_Single>(handGraphicPath, ShaderDatabase.Cutout, new Vector2(handSize, handSize), skinColour);
}
public static bool TryToDrawHand(Pawn pawn, string bodyAddonName, Vector3 bodyAddonPosition, float bodyAddonAngle, Rot4 bodyAddonRotation, PawnRenderFlags renderFlags)
{
if (pawn.TryGetComp<CompBodyAnimator>() != null && pawn.TryGetComp<CompBodyAnimator>().isAnimating && BodyPartIsBeingTouched(pawn, bodyAddonName, out List<HandAnimationData> handAnimationData))
{
foreach (HandAnimationData datum in handAnimationData)
{
Pawn touchingPawn = datum.touchingActorID >= 0 && pawn.GetAllSexParticipants().Count > datum.touchingActorID ? pawn.GetAllSexParticipants()[datum.touchingActorID] : pawn;
Graphic handgraphic = GetHandGraphic(touchingPawn, bodyAddonName, datum);
Vector3 handPosition = GetHandPosition(pawn, datum, bodyAddonPosition, bodyAddonAngle);
GenDraw.DrawMeshNowOrLater(mesh: handgraphic.MeshAt(rot: bodyAddonRotation),
loc: handPosition + new Vector3(0f, 0.022f, 0f),
quat: Quaternion.identity,
mat: handgraphic.MatAt(rot: bodyAddonRotation), renderFlags.FlagSet(PawnRenderFlags.DrawNow));
return true;
}
}
return false;
}
}
}