quantum-space-buddies/QSB/Animation/NPC/Patches/CharacterAnimationPatches.cs

118 lines
3.9 KiB
C#
Raw Normal View History

using HarmonyLib;
using OWML.Common;
2021-04-29 17:30:45 +00:00
using QSB.Animation.NPC.WorldObjects;
using QSB.ConversationSync;
2021-12-23 21:49:04 +00:00
using QSB.Messaging;
2021-04-26 13:30:21 +00:00
using QSB.Patches;
using QSB.Player;
2022-01-13 04:58:38 +00:00
using QSB.TriggerSync.WorldObjects;
2021-04-26 13:30:21 +00:00
using QSB.Utility;
using QSB.WorldSync;
2021-04-29 17:30:45 +00:00
using System.Linq;
2021-04-26 13:30:21 +00:00
using UnityEngine;
2022-03-03 03:46:33 +00:00
namespace QSB.Animation.NPC.Patches;
[HarmonyPatch]
public class CharacterAnimationPatches : QSBPatch
2021-04-26 13:30:21 +00:00
{
2022-03-03 03:46:33 +00:00
public override QSBPatchTypes Type => QSBPatchTypes.OnClientConnect;
2022-03-03 03:46:33 +00:00
[HarmonyPrefix]
[HarmonyPatch(typeof(CharacterAnimController), nameof(CharacterAnimController.OnAnimatorIK))]
public static bool AnimatorIKReplacement(
CharacterAnimController __instance)
{
if (!QSBWorldSync.AllObjectsReady || ConversationManager.Instance == null)
2021-04-26 13:30:21 +00:00
{
2022-03-03 03:46:33 +00:00
return true;
}
2021-04-26 13:30:21 +00:00
2022-03-03 03:46:33 +00:00
var playerId = ConversationManager.Instance.GetPlayerTalkingToTree(__instance._dialogueTree);
var player = QSBPlayerManager.GetPlayer(playerId);
2022-03-03 03:46:33 +00:00
if (__instance.playerTrackingZone == null)
{
return true;
}
2022-09-07 20:24:31 +00:00
var qsbObj = __instance.playerTrackingZone.GetWorldObject<QSBCharacterTrigger>();
2021-04-26 13:30:21 +00:00
2022-03-03 03:46:33 +00:00
PlayerInfo playerToUse = null;
if (__instance._inConversation)
{
if (playerId == uint.MaxValue)
2021-04-26 13:30:21 +00:00
{
2022-03-03 03:46:33 +00:00
DebugLog.ToConsole($"Error - {__instance.name} is in conversation with a null player! Defaulting to active camera.", MessageType.Error);
playerToUse = QSBPlayerManager.LocalPlayer;
}
2022-03-03 03:46:33 +00:00
else
{
2022-03-03 03:46:33 +00:00
playerToUse = player.CameraBody == null
? QSBPlayerManager.LocalPlayer
: player;
2021-04-26 13:30:21 +00:00
}
2022-03-03 03:46:33 +00:00
}
else if (!__instance.lookOnlyWhenTalking && qsbObj.Occupants.Count != 0) // IDEA : maybe this would be more fun if characters looked between players at random times? :P
{
playerToUse = QSBPlayerManager.GetClosestPlayerToWorldPoint(qsbObj.Occupants, __instance.transform.position);
}
else if (QSBPlayerManager.PlayerList.Count != 0)
{
playerToUse = QSBPlayerManager.GetClosestPlayerToWorldPoint(__instance.transform.position, true);
}
2021-04-26 13:30:21 +00:00
2022-03-03 03:46:33 +00:00
var localPosition = playerToUse != null
? __instance._animator.transform.InverseTransformPoint(playerToUse.CameraBody.transform.position)
: Vector3.zero;
2021-04-26 13:30:21 +00:00
2022-03-03 03:46:33 +00:00
var targetWeight = __instance.headTrackingWeight;
if (__instance.lookOnlyWhenTalking)
{
if (!__instance._inConversation
|| qsbObj.Occupants.Count == 0
|| !qsbObj.Occupants.Contains(playerToUse))
2021-04-29 17:30:45 +00:00
{
2022-03-03 03:46:33 +00:00
targetWeight *= 0;
2021-04-29 17:30:45 +00:00
}
}
2022-03-03 03:46:33 +00:00
else
{
2022-03-03 03:46:33 +00:00
if (qsbObj.Occupants.Count == 0
|| !qsbObj.Occupants.Contains(playerToUse))
{
2022-03-03 03:46:33 +00:00
targetWeight *= 0;
}
2022-03-03 03:46:33 +00:00
}
2021-04-29 17:30:45 +00:00
2022-03-03 03:46:33 +00:00
__instance._currentLookWeight = Mathf.Lerp(__instance._currentLookWeight, targetWeight, Time.deltaTime * 2f);
__instance._currentLookTarget = __instance.lookSpring.Update(__instance._currentLookTarget, localPosition, Time.deltaTime);
__instance._animator.SetLookAtPosition(__instance._animator.transform.TransformPoint(__instance._currentLookTarget));
__instance._animator.SetLookAtWeight(__instance._currentLookWeight);
return false;
2022-03-03 03:46:33 +00:00
}
2021-06-18 21:38:32 +00:00
2022-03-03 03:46:33 +00:00
[HarmonyPrefix]
[HarmonyPatch(typeof(FacePlayerWhenTalking), nameof(FacePlayerWhenTalking.OnStartConversation))]
public static bool OnStartConversation(FacePlayerWhenTalking __instance)
{
var playerId = ConversationManager.Instance.GetPlayerTalkingToTree(__instance._dialogueTree);
if (playerId == uint.MaxValue)
{
DebugLog.ToConsole($"Error - No player talking to {__instance._dialogueTree.name}!", MessageType.Error);
return false;
}
2022-03-03 03:46:33 +00:00
var player = QSBPlayerManager.GetPlayer(playerId);
var distance = player.Body.transform.position - __instance.transform.position;
var vector2 = distance - Vector3.Project(distance, __instance.transform.up);
var angle = Vector3.Angle(__instance.transform.forward, vector2) * Mathf.Sign(Vector3.Dot(vector2, __instance.transform.right));
var axis = __instance.transform.parent.InverseTransformDirection(__instance.transform.up);
var lhs = Quaternion.AngleAxis(angle, axis);
__instance.FaceLocalRotation(lhs * __instance.transform.localRotation);
2022-03-03 03:46:33 +00:00
return false;
}
2021-04-26 13:30:21 +00:00
}