3 using Microsoft.Xna.Framework;
5 using System.Collections.Generic;
43 get {
return _isActive; }
48 expirationTimer = expirationTime;
53 private bool _isActive;
54 private float expirationTimer;
55 private const float expirationTime = 0.1f;
67 expirationTimer -= deltaTime;
68 if (expirationTimer <= 0)
75 protected readonly Dictionary<AnimationType, AnimSwap>
tempAnimations =
new Dictionary<AnimationType, AnimSwap>();
110 return humanAnimController.HumanCrouchParams;
172 anims.Add(humanAnimController.HumanCrouchParams);
183 public enum Animation {
None, Climbing, UsingItem, Struggle, CPR, UsingItemWhileClimbing };
204 if (p ==
null) {
return null; }
205 if (v ==
null) {
return null; }
206 if (!MathUtils.IsValid(v.Value)) {
return null; }
211 if (p ==
null) {
return null; }
229 UpdateTemporaryAnimations(deltaTime);
245 DebugConsole.ThrowError($
"{character.SpeciesName} cannot walk!");
253 DebugConsole.ThrowError($
"{character.SpeciesName} cannot run!");
263 throw new NotImplementedException(type.ToString());
314 return humanAnimController.HumanCrouchParams;
318 DebugConsole.ThrowError($
"Animation params of type {type} not implemented for non-humanoids!");
354 if (sqrDist > MathUtils.Pow(ConvertUnits.ToDisplayUnits(
upperArmLength + forearmLength), 2))
362 if (distX > ConvertUnits.ToDisplayUnits(
upperArmLength + forearmLength))
367 Vector2 GetTargetMovement(Vector2
dir)
375 Vector2 handSimPos = ConvertUnits.ToSimUnits(handWorldPos);
382 Vector2 diff = handSimPos - refPos;
383 float dist = diff.Length();
387 handSimPos = refPos + diff / dist * maxDist;
391 if (leftHand !=
null)
393 leftHand.Disabled =
true;
394 leftHand.PullJointEnabled =
true;
395 leftHand.PullJointWorldAnchorB = handSimPos;
399 if (rightHand !=
null)
401 rightHand.Disabled =
true;
402 rightHand.PullJointEnabled =
true;
403 rightHand.PullJointWorldAnchorB = handSimPos;
411 humanoidAnimController.Crouching =
true;
412 humanoidAnimController.ForceSelectAnimationType =
AnimationType.Crouch;
417 public void Grab(Vector2 rightHandPos, Vector2 leftHandPos)
419 for (
int i = 0; i < 2; i++)
432 private readonly Vector2[] transformedHandlePos =
new Vector2[2];
434 public void HoldItem(
float deltaTime,
Item item, Vector2[] handlePos, Vector2 itemPos,
bool aim,
float holdAngle,
float itemAngleRelativeToHoldAngle = 0.0f,
bool aimMelee =
false, Vector2? targetPos =
null)
443 Matrix itemTransform = Matrix.CreateRotationZ(item.
body.
Rotation);
444 transformedHandlePos[0] = Vector2.Transform(handlePos[0], itemTransform);
445 transformedHandlePos[1] = Vector2.Transform(handlePos[1], itemTransform);
452 bool usingController = controller is { AllowAiming:
false };
453 if (!usingController)
456 usingController = controller is { AllowAiming:
false };
461 float torsoRotation = torso.
Rotation;
464 bool equippedInRightHand = rightHandItem == item && rightHand is { IsSevered:
false };
466 bool equippedInLeftHand = leftHandItem == item && leftHand is { IsSevered:
false };
471 Vector2 diff = holdable.
Aimable ?
473 MathUtils.RotatePoint(Vector2.UnitX, torsoRotation);
475 holdAngle = MathUtils.VectorToAngle(
new Vector2(diff.X, diff.Y *
Dir)) - torsoRotation *
Dir;
476 holdAngle += GetAimWobble(rightHand, leftHand, item);
477 itemAngle = torsoRotation + holdAngle *
Dir;
482 bool anotherItemControlsPose = equippedInLeftHand && rightHandItem != item && (rightHandItem?.GetComponent<
Holdable>()?.ControlPose ??
false);
495 if (equippedInRightHand)
499 else if (equippedInLeftHand)
505 itemAngle = torsoRotation + holdAngle *
Dir;
510 itemAngle = torsoRotation + holdAngle *
Dir;
516 if (itemPos == Vector2.Zero || isClimbing || usingController)
518 if (equippedInRightHand)
521 itemAngle = rightHand.
Rotation + (holdAngle - rightHand.
Params.GetSpriteOrientation() + MathHelper.PiOver2) *
Dir;
523 else if (equippedInLeftHand)
526 itemAngle = leftHand.
Rotation + (holdAngle - leftHand.
Params.GetSpriteOrientation() + MathHelper.PiOver2) *
Dir;
531 if (equippedInRightHand)
536 if (equippedInLeftHand)
538 if (leftShoulder ==
null) {
return; }
543 transformedHoldPos += Vector2.Transform(itemPos, Matrix.CreateRotationZ(itemAngle));
548 Vector2 currItemPos = equippedInRightHand ?
552 if (!MathUtils.IsValid(currItemPos))
554 string errorMsg =
"Attempted to move the item \"" + item +
"\" to an invalid position in HumanidAnimController.HoldItem: " +
556 ", handlePos[0]: " + handlePos[0] +
", handlePos[1]: " + handlePos[1] +
557 ", transformedHandlePos[0]: " + transformedHandlePos[0] +
", transformedHandlePos[1]:" + transformedHandlePos[1] +
558 ", item pos: " + item.
SimPosition +
", itemAngle: " + itemAngle +
560 DebugConsole.Log(errorMsg);
561 GameAnalyticsManager.AddErrorEventOnce(
563 GameAnalyticsManager.ErrorSeverity.Error,
569 float targetAngle = MathUtils.WrapAngleTwoPi(itemAngle + itemAngleRelativeToHoldAngle *
Dir);
570 float currentRotation = MathUtils.WrapAngleTwoPi(item.
body.
Rotation);
571 float itemRotation = MathHelper.SmoothStep(currentRotation, targetAngle, deltaTime * 25);
572 if (previousDirection !=
dir || Math.Abs(targetAngle - currentRotation) > MathHelper.Pi)
574 itemRotation = targetAngle;
576 item.
SetTransform(currItemPos, itemRotation, setPrevTransform:
false);
577 previousDirection =
dir;
579 if (holdable.
Pusher !=
null)
604 for (
int i = 0; i < 2; i++)
608 if (handlePos[i].LengthSquared() >
ArmLength)
610 DebugConsole.AddWarning($
"Aim position for the item {item.Name} may be incorrect (further than the length of the character's arm)",
615 i == 0 ? rightHand : leftHand, transformedHoldPos + transformedHandlePos[i],
618 maxAngularVelocity: 15.0f);
623 private float GetAimWobble(
Limb rightHand,
Limb leftHand,
Item heldItem)
625 float wobbleStrength = 0.0f;
634 if (wobbleStrength <= 0.1f) {
return 0.0f; }
635 wobbleStrength = (float)Math.Min(wobbleStrength, 1.0f);
637 float lowFreqNoise = PerlinNoise.GetPerlin((
float)Timing.TotalTime / 320.0f, (float)Timing.TotalTime / 240.0f) - 0.5f;
638 float highFreqNoise = PerlinNoise.GetPerlin((
float)Timing.TotalTime / 40.0f, (float)Timing.TotalTime / 50.0f) - 0.5f;
640 return (lowFreqNoise * 1.0f + highFreqNoise * 0.1f) * wobbleStrength;
643 public void HandIK(
Limb hand, Vector2 pos,
float armTorque = 1.0f,
float handTorque = 1.0f,
float maxAngularVelocity =
float.PositiveInfinity)
650 if (leftShoulder ==
null) {
return; }
664 if (arm ==
null) {
return; }
667 float c = Vector2.Distance(pos, shoulderPos);
670 float armAngle = MathUtils.VectorToAngle(pos - shoulderPos) + arm.
Params.GetSpriteOrientation() - MathHelper.PiOver2;
671 float upperArmAngle = MathUtils.SolveTriangleSSS(forearmLength,
upperArmLength, c) *
Dir;
672 float lowerArmAngle = MathUtils.SolveTriangleSSS(
upperArmLength, forearmLength, c) *
Dir;
675 while (arm.
Rotation - armAngle > MathHelper.Pi)
677 armAngle += MathHelper.TwoPi;
679 while (arm.
Rotation - armAngle < -MathHelper.Pi)
681 armAngle -= MathHelper.TwoPi;
686 arm.
body.
SmoothRotate(armAngle - upperArmAngle, 100.0f * armTorque * arm.
Mass, wrapAngle:
false);
688 float forearmAngle = armAngle + lowerArmAngle;
695 float handAngle = forearm !=
null ? forearmAngle : armAngle;
700 public void ApplyPose(Vector2 leftHandPos, Vector2 rightHandPos, Vector2 leftFootPos, Vector2 rightFootPos,
float footMoveForce = 10)
705 if (waist ==
null) {
return; }
706 Vector2 midPos = waist.SimPosition;
707 if (leftHand !=
null)
709 leftHand.Disabled =
true;
710 leftHandPos.X *=
Dir;
711 leftHandPos += midPos;
712 HandIK(leftHand, leftHandPos);
714 if (rightHand !=
null)
716 rightHand.Disabled =
true;
717 rightHandPos.X *=
Dir;
718 rightHandPos += midPos;
719 HandIK(rightHand, rightHandPos);
722 if (leftFoot !=
null)
724 leftFoot.Disabled =
true;
725 leftFootPos =
new Vector2(waist.SimPosition.X + leftFootPos.X *
Dir,
GetColliderBottom().Y + leftFootPos.Y);
726 MoveLimb(leftFoot, leftFootPos, Math.Abs(leftFoot.SimPosition.X - leftFootPos.X) * footMoveForce * leftFoot.Mass,
true);
729 if (rightFoot !=
null)
731 rightFoot.Disabled =
true;
732 rightFootPos =
new Vector2(waist.SimPosition.X + rightFootPos.X *
Dir,
GetColliderBottom().Y + rightFootPos.Y);
733 MoveLimb(rightFoot, rightFootPos, Math.Abs(rightFoot.SimPosition.X - rightFootPos.X) * footMoveForce * rightFoot.Mass,
true);
743 new Vector2(-0.75f, -0.2f),
744 new Vector2(0.75f, -0.2f),
755 if (rightHand ==
null) {
return; }
760 Vector2 localAnchorShoulder = Vector2.Zero;
761 Vector2 localAnchorElbow = Vector2.Zero;
766 LimbJoint rightElbow = rightForearm ==
null ?
769 if (rightElbow !=
null)
773 upperArmLength = Vector2.Distance(localAnchorShoulder, localAnchorElbow);
774 if (rightElbow !=
null)
776 if (rightForearm ==
null)
778 forearmLength = Vector2.Distance(
785 if (rightWrist !=
null)
787 forearmLength = Vector2.Distance(
791 forearmLength += Vector2.Distance(
802 (lj.LimbA.type == limbTypeA && lj.LimbB.type == limbTypeB) ||
803 (lj.LimbB.type == limbTypeA && lj.LimbA.type == limbTypeB));
809 lj.LimbA.type == matchingType && ignoredTypes.None(t => lj.LimbB.type == t) ||
810 lj.LimbB.type == matchingType && ignoredTypes.None(t => lj.LimbB.type == t));
815 base.Recreate(ragdollParams);
822 private void StartAnimation(
Animation animation)
828 else if (animation ==
Animation.Climbing)
838 private void StopAnimation(
Animation animation)
844 else if (animation ==
Animation.Climbing)
862 private readonly Dictionary<AnimationType, AnimationParams> defaultAnimations =
new Dictionary<AnimationType, AnimationParams>();
873 if (animLoadInfo.File.TryGet(out
string fileName) && animSwap.TemporaryAnimation.FileNameWithoutExtension.Equals(fileName, StringComparison.OrdinalIgnoreCase))
876 animSwap.IsActive =
true;
879 else if (animLoadInfo.File.TryGet(out
ContentPath contentPath) && animSwap.TemporaryAnimation.Path == contentPath)
882 animSwap.IsActive =
true;
887 if (animSwap.Priority >= animLoadInfo.Priority)
901 if (defaultAnimation ==
null) {
return false; }
904 defaultAnimations.TryAdd(animType, defaultAnimation);
909 private void UpdateTemporaryAnimations(
float deltaTime)
914 if (!animSwap.IsActive)
916 if (defaultAnimations.TryGetValue(animSwap.AnimationType, out AnimationParams defaultAnimation))
923 DebugConsole.ThrowError($
"[AnimController] Failed to find the default animation parameters of type {animSwap.AnimationType}. Cannot swap back the default animations!");
935 animSwap.Update(deltaTime);
947 switch (animationType)
951 animParams = humanAnimController.WalkParams;
955 animParams = humanAnimController.RunParams;
959 animParams = humanAnimController.HumanCrouchParams;
963 animParams = humanAnimController.SwimSlowParams;
967 animParams = humanAnimController.SwimFastParams;
970 DebugConsole.ThrowError($
"[AnimController] Animation of type {animationType} not implemented!");
976 switch (animationType)
1001 DebugConsole.ThrowError($
"[AnimController] Animation of type {animationType} not implemented!");
1006 bool success = animParams !=
null;
1007 if (!file.TryGet(out
string fileName))
1011 fileName = contentPath.Value;
1014 success = contentPath == animParams.
Path;
1022 success = animParams.FileNameWithoutExtension.
Equals(fileName, StringComparison.OrdinalIgnoreCase);
1027 DebugConsole.NewMessage($
"Animation {fileName} successfully loaded for {character.DisplayName}", Color.LightGreen, debugOnly:
true);
1029 else if (throwErrors)
1031 DebugConsole.ThrowError($
"Animation {fileName} for {character.DisplayName} could not be loaded!");
1044 switch (animationType)
1049 humanAnimController.WalkParams = newWalkParams;
1055 humanAnimController.HumanRunParams = newRunParams;
1061 humanAnimController.HumanCrouchParams = newCrouchParams;
1067 humanAnimController.HumanSwimSlowParams = newSwimSlowParams;
1073 humanAnimController.HumanSwimFastParams = newSwimFastParams;
1077 DebugConsole.ThrowError($
"[AnimController] Animation of type {animationType} not implemented!");
1083 switch (animationType)
1110 DebugConsole.ThrowError($
"[AnimController] Animation of type {animationType} not implemented!");
AfflictionPrefab is a prefab that defines a type of affliction that can be applied to a character....
static readonly Identifier DamageType
readonly AnimationType AnimationType
AnimSwap(AnimationParams temporaryAnimation, float priority)
void Update(float deltaTime)
readonly AnimationParams TemporaryAnimation
List< AnimationParams > AllAnimParams
Note: creates a new list every time, because the params might have changed. If there is a need to acc...
void CalculateArmLengths()
void HandIK(Limb hand, Vector2 pos, float armTorque=1.0f, float handTorque=1.0f, float maxAngularVelocity=float.PositiveInfinity)
AnimationType ForceSelectAnimationType
abstract void UpdateAnim(float deltaTime)
Vector2? GetValidOrNull(AnimationParams p, Vector2 v)
override? float HeadPosition
float? GetValidOrNull(AnimationParams p, float? v)
virtual ? Vector2 StepSize
float GetCurrentSpeed(bool useMaxSpeed)
override void Recreate(RagdollParams ragdollParams=null)
Call this to create the ragdoll from the RagdollParams.
AnimationParams? CurrentAnimationParams
override? float TorsoAngle
GroundedMovementParams? CurrentGroundedParams
abstract void DragCharacter(Character target, float deltaTime)
readonly Dictionary< AnimationType, AnimSwap > tempAnimations
SwimParams? CurrentSwimParams
abstract SwimParams SwimFastParams
bool TrySwapAnimParams(AnimationParams newParams)
Simply swaps existing animation parameters as current parameters.
void UpdateAnimations(float deltaTime)
readonly HashSet< AnimationType > expiredAnimations
abstract GroundedMovementParams RunParams
bool TryLoadAnimation(AnimationType animationType, Either< string, ContentPath > file, out AnimationParams animParams, bool throwErrors)
Loads animations. Non-permanent (= resets on load).
float GetHeightFromFloor()
AnimationParams GetAnimationParamsFromType(AnimationType type)
Vector2 AimSourceWorldPos
void HoldItem(float deltaTime, Item item, Vector2[] handlePos, Vector2 itemPos, bool aim, float holdAngle, float itemAngleRelativeToHoldAngle=0.0f, bool aimMelee=false, Vector2? targetPos=null)
bool TryLoadTemporaryAnimation(StatusEffect.AnimLoadInfo animLoadInfo, bool throwErrors)
Loads an animation (variation) that automatically resets in 0.1s, unless triggered again....
LimbJoint GetJoint(LimbType matchingType, IEnumerable< LimbType > ignoredTypes)
AnimController(Character character, string seed, RagdollParams ragdollParams=null)
virtual Vector2 AimSourceSimPos
LimbJoint GetJointBetweenLimbs(LimbType limbTypeA, LimbType limbTypeB)
override? float TorsoPosition
void UpdateUseItem(bool allowMovement, Vector2 handWorldPos)
void LockFlipping(float time=0.2f)
abstract GroundedMovementParams WalkParams
override? float HeadAngle
bool IsMovingFast
Note: Presupposes that the slow speed is lower than the high speed. Otherwise will give invalid resul...
abstract SwimParams SwimSlowParams
void ApplyPose(Vector2 leftHandPos, Vector2 rightHandPos, Vector2 leftFootPos, Vector2 rightFootPos, float footMoveForce=10)
virtual float GetSpeed(AnimationType type)
void Grab(Vector2 rightHandPos, Vector2 leftHandPos)
virtual AnimationType AnimationType
float GetLimbDamage(Limb limb, Identifier afflictionType)
readonly CharacterParams Params
void SetInput(InputType inputType, bool hit, bool held)
CharacterHealth CharacterHealth
override Vector2? SimPosition
Item????????? SelectedItem
The primary selected item. It can be any device that character interacts with. This excludes items li...
Vector2 SmoothedCursorPosition
float SpeedMultiplier
Can be used to modify the character's speed via StatusEffects
CharacterInventory Inventory
Item SelectedSecondaryItem
The secondary selected item. It's an item other than a device (see SelectedItem), e....
bool IsKeyDown(InputType inputType)
readonly AnimController AnimController
Item GetItemInLimbSlot(InvSlotType limbSlot)
bool IsInLimbSlot(Item item, InvSlotType limbSlot)
bool Equals(ContentPath other)
virtual Vector2 WorldPosition
static FishRunParams GetAnimParams(Character character, Either< string, ContentPath > file, bool throwErrors=true)
static FishSwimFastParams GetAnimParams(Character character, Either< string, ContentPath > file, bool throwErrors=true)
static FishSwimSlowParams GetAnimParams(Character character, Either< string, ContentPath > file, bool throwErrors=true)
static FishWalkParams GetAnimParams(Character character, Either< string, ContentPath > file, bool throwErrors=true)
float BackwardsMovementMultiplier
static HumanCrouchParams GetAnimParams(Character character, Either< string, ContentPath > file, bool throwErrors=true)
static HumanRunParams GetAnimParams(Character character, Either< string, ContentPath > file, bool throwErrors=true)
static HumanSwimFastParams GetAnimParams(Character character, Either< string, ContentPath > file, bool throwErrors=true)
static HumanSwimSlowParams GetAnimParams(Character character, Either< string, ContentPath > file, bool throwErrors=true)
static HumanWalkParams GetAnimParams(Character character, Either< string, ContentPath > file, bool throwErrors=true)
override Vector2? SimPosition
void SetTransform(Vector2 simPosition, float rotation, bool findNewHull=true, bool setPrevTransform=true)
override string Name
Note that this is not a LocalizedString instance, just the current name of the item as a string....
bool UseHandRotationForHoldAngle
readonly LimbParams Params
Vector2 PullJointWorldAnchorB
Vector2 PullJointWorldAnchorA
Vector2 PullJointLocalAnchorA
void MoveToTargetPosition(bool lerp=true)
void ApplyForce(Vector2 force, float maxVelocity=NetConfig.MaxPhysicsBodyVelocity)
bool SetTransform(Vector2 simPosition, float rotation, bool setPrevTransform=true)
void SmoothRotate(float targetRotation, float force=10.0f, bool wrapAngle=true)
Rotate the body towards the target rotation in the "shortest direction", taking into account the curr...
ContentPackage? ContentPackage
Vector2 GetColliderBottom()
Limb GetLimb(LimbType limbType, bool excludeSevered=true)
Note that if there are multiple limbs of the same type, only the first (valid) limb is returned.
void MoveLimb(Limb limb, Vector2 pos, float amount, bool pullFromCenter=false)
if false, force is applied to the position of pullJoint
StatusEffects can be used to execute various kinds of effects: modifying the state of some entity in ...
readonly record struct AnimLoadInfo(AnimationType Type, Either< string, ContentPath > File, float Priority, ImmutableArray< Identifier > ExpectedSpeciesNames)
override Vector2 SimPosition
override Vector2? Position