zxc
This commit is contained in:
parent
90084e82d5
commit
3255886197
@ -56,12 +56,12 @@
|
||||
"WalkSpeed": 100
|
||||
},
|
||||
{
|
||||
"__type": "Sandbox.Citizen.CitizenAnimationHelper",
|
||||
"__guid": "640af9e4-02ed-4391-95ea-e45fba51fa42",
|
||||
"BodyWeight": 1,
|
||||
"EyesWeight": 1,
|
||||
"__type": "AnimationHelper",
|
||||
"__guid": "536068a6-fe5d-4f45-af74-9522ebf7e663",
|
||||
"BodyWeight": 0,
|
||||
"EyesWeight": 0,
|
||||
"HeadWeight": 1,
|
||||
"LookAtEnabled": false,
|
||||
"LookAtEnabled": true,
|
||||
"Target": {
|
||||
"_type": "component",
|
||||
"component_id": "4fd8c36d-180b-41af-8439-6b975ca1c7b3",
|
||||
|
@ -6,7 +6,6 @@
|
||||
"Flags": 0,
|
||||
"Name": "NetworkManager",
|
||||
"Enabled": true,
|
||||
"NetworkMode": 0,
|
||||
"Components": [
|
||||
{
|
||||
"__type": "Sandbox.SceneInformation",
|
||||
@ -17,13 +16,13 @@
|
||||
},
|
||||
{
|
||||
"__type": "Sandbox.KPTLConnect",
|
||||
"__guid": "79db0a43-3cee-44bf-86db-fa70ca72f62c",
|
||||
"__guid": "895b0f93-287e-4607-808e-6ce5bdbb5c05",
|
||||
"PlayerPrefab": {
|
||||
"_type": "gameobject",
|
||||
"prefab": "prefabs/player.prefab"
|
||||
},
|
||||
"SpawnPoints": [],
|
||||
"StartServer": false
|
||||
"StartServer": true
|
||||
}
|
||||
]
|
||||
},
|
||||
|
429
Code/AnimationHelper.cs
Normal file
429
Code/AnimationHelper.cs
Normal file
@ -0,0 +1,429 @@
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Used to control the Citizen animation state. You don't have to use this to animate your citizen avatar, but our
|
||||
/// aim is to put everything you need in this class, so you can easily see what variables are available.
|
||||
/// </summary>
|
||||
[Title( "Animation Helper" )]
|
||||
[Category( "KPTL" )]
|
||||
[Icon( "directions_run" )]
|
||||
public sealed class AnimationHelper : Component, Component.ExecuteInEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// The skinned model renderer that we'll apply all parameters to.
|
||||
/// </summary>
|
||||
[Property] public SkinnedModelRenderer Target { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Where are the eyes of our character?
|
||||
/// </summary>
|
||||
[Property] public GameObject EyeSource { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How tall are we?
|
||||
/// </summary>
|
||||
[Property, Range( 0.5f, 1.5f ), Title( "Avatar Height Scale" )] public float? Height { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Are we looking at something? Useful for stuff like cutscenes, where you want an NPC to stare at you.
|
||||
/// </summary>
|
||||
[Property, ToggleGroup( "LookAtEnabled", Label = "Look At" )]
|
||||
public bool LookAtEnabled { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Which GameObject should we be looking at?
|
||||
/// </summary>
|
||||
[Property, ToggleGroup( "LookAtEnabled" )] public GameObject LookAt { get; set; }
|
||||
|
||||
[Property, ToggleGroup( "LookAtEnabled" ), Range( 0, 1 )] public float EyesWeight { get; set; } = 1.0f;
|
||||
[Property, ToggleGroup( "LookAtEnabled" ), Range( 0, 1 )] public float HeadWeight { get; set; } = 1.0f;
|
||||
[Property, ToggleGroup( "LookAtEnabled" ), Range( 0, 1 )] public float BodyWeight { get; set; } = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// IK will try to place the limb where this GameObject is in the world.
|
||||
/// </summary>
|
||||
[Property, Group( "Inverse kinematics" ), Title( "Left Hand" )] public GameObject IkLeftHand { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IkLeftHand"/>
|
||||
[Property, Group( "Inverse kinematics" ), Title( "Right Hand" )] public GameObject IkRightHand { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IkLeftHand"/>
|
||||
[Property, Group( "Inverse kinematics" ), Title( "Left Foot" )] public GameObject IkLeftFoot { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IkLeftHand"/>
|
||||
[Property, Group( "Inverse kinematics" ), Title( "Right Foot" )] public GameObject IkRightFoot { get; set; }
|
||||
|
||||
[Sync] private Vector3 LookDir { get; set; }
|
||||
|
||||
protected override void OnUpdate()
|
||||
{
|
||||
if ( !Target.IsValid() )
|
||||
return;
|
||||
|
||||
AimBodyWeight = 0f;
|
||||
AimEyesWeight = 0f;
|
||||
AimHeadWeight = 1f;
|
||||
|
||||
|
||||
if ( LookAtEnabled )
|
||||
{
|
||||
if ( Network.IsOwner )
|
||||
{
|
||||
LookDir = Scene.Camera.GameObject.WorldRotation.Forward;
|
||||
}
|
||||
WithLook( LookDir, EyesWeight, HeadWeight, BodyWeight );
|
||||
}
|
||||
|
||||
if ( Height.HasValue )
|
||||
{
|
||||
Target.Set( "scale_height", Height.Value );
|
||||
}
|
||||
|
||||
if ( IkLeftHand.IsValid() && IkLeftHand.Active ) Target.SetIk( "hand_left", IkLeftHand.Transform.World );
|
||||
else Target.ClearIk( "hand_left" );
|
||||
|
||||
if ( IkRightHand.IsValid() && IkRightHand.Active ) Target.SetIk( "hand_right", IkRightHand.Transform.World );
|
||||
else Target.ClearIk( "hand_right" );
|
||||
|
||||
if ( IkLeftFoot.IsValid() && IkLeftFoot.Active ) Target.SetIk( "foot_left", IkLeftFoot.Transform.World );
|
||||
else Target.ClearIk( "foot_left" );
|
||||
|
||||
if ( IkRightFoot.IsValid() && IkRightFoot.Active ) Target.SetIk( "foot_right", IkRightFoot.Transform.World );
|
||||
else Target.ClearIk( "foot_right" );
|
||||
}
|
||||
|
||||
public void ProceduralHitReaction( DamageInfo info, float damageScale = 1.0f, Vector3 force = default )
|
||||
{
|
||||
var boneId = info.Hitbox?.Bone?.Index ?? 0;
|
||||
var bone = Target.GetBoneObject( boneId );
|
||||
|
||||
var localToBone = bone.LocalPosition;
|
||||
if ( localToBone == Vector3.Zero ) localToBone = Vector3.One;
|
||||
|
||||
Target.Set( "hit", true );
|
||||
Target.Set( "hit_bone", boneId );
|
||||
Target.Set( "hit_offset", localToBone );
|
||||
Target.Set( "hit_direction", force.Normal );
|
||||
Target.Set( "hit_strength", (force.Length / 1000.0f) * damageScale );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The transform of the eyes, in world space. This is worked out from EyeSource is it's set.
|
||||
/// </summary>
|
||||
public Transform EyeWorldTransform
|
||||
{
|
||||
get
|
||||
{
|
||||
if ( EyeSource.IsValid() ) return EyeSource.Transform.World;
|
||||
|
||||
return Transform.World;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Have the player look at this point in the world
|
||||
/// </summary>
|
||||
public void WithLook( Vector3 lookDirection, float eyesWeight = 1.0f, float headWeight = 1.0f, float bodyWeight = 1.0f )
|
||||
{
|
||||
// Target.SetLookDirection( "aim_eyes", lookDirection, eyesWeight );
|
||||
Target.SetLookDirection( "aim_head", lookDirection, headWeight );
|
||||
// Target.SetLookDirection( "aim_body", lookDirection, bodyWeight );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Have the player animate moving with a set velocity (this doesn't move them! Your character controller is responsible for that)
|
||||
/// </summary>
|
||||
/// <param name="Velocity"></param>
|
||||
public void WithVelocity( Vector3 Velocity )
|
||||
{
|
||||
var dir = Velocity;
|
||||
var forward = Target.WorldRotation.Forward.Dot( dir );
|
||||
var sideward = Target.WorldRotation.Right.Dot( dir );
|
||||
|
||||
var angle = MathF.Atan2( sideward, forward ).RadianToDegree().NormalizeDegrees();
|
||||
|
||||
Target.Set( "move_direction", angle );
|
||||
Target.Set( "move_speed", Velocity.Length );
|
||||
Target.Set( "move_groundspeed", Velocity.WithZ( 0 ).Length );
|
||||
Target.Set( "move_y", sideward );
|
||||
Target.Set( "move_x", forward );
|
||||
Target.Set( "move_z", Velocity.z );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Animates the wish for the character to move in a certain direction. For example, when in the air, your character will swing their arms in that direction.
|
||||
/// </summary>
|
||||
/// <param name="Velocity"></param>
|
||||
public void WithWishVelocity( Vector3 Velocity )
|
||||
{
|
||||
var dir = Velocity;
|
||||
var forward = Target.WorldRotation.Forward.Dot( dir );
|
||||
var sideward = Target.WorldRotation.Right.Dot( dir );
|
||||
|
||||
var angle = MathF.Atan2( sideward, forward ).RadianToDegree().NormalizeDegrees();
|
||||
|
||||
Target.Set( "wish_direction", angle );
|
||||
Target.Set( "wish_speed", Velocity.Length );
|
||||
Target.Set( "wish_groundspeed", Velocity.WithZ( 0 ).Length );
|
||||
Target.Set( "wish_y", sideward );
|
||||
Target.Set( "wish_x", forward );
|
||||
Target.Set( "wish_z", Velocity.z );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Where are we aiming?
|
||||
/// </summary>
|
||||
public Rotation AimAngle
|
||||
{
|
||||
set
|
||||
{
|
||||
value = Target.WorldRotation.Inverse * value;
|
||||
var ang = value.Angles();
|
||||
|
||||
Target.Set( "aim_body_pitch", ang.pitch );
|
||||
Target.Set( "aim_body_yaw", ang.yaw );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The weight of the aim angle, but specifically for the Citizen's eyes.
|
||||
/// </summary>
|
||||
public float AimEyesWeight
|
||||
{
|
||||
get => Target.GetFloat( "aim_eyes_weight" );
|
||||
set => Target.Set( "aim_eyes_weight", value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The weight of the aim angle, but specifically for the Citizen's head.
|
||||
/// </summary>
|
||||
public float AimHeadWeight
|
||||
{
|
||||
get => Target.GetFloat( "aim_head_weight" );
|
||||
set => Target.Set( "aim_head_weight", value );
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The weight of the aim angle, but specifically for the Citizen's body.
|
||||
/// </summary>
|
||||
public float AimBodyWeight
|
||||
{
|
||||
get => Target.GetFloat( "aim_body_weight" );
|
||||
set => Target.Set( "aim_body_weight", value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How much the character is rotating in degrees per second, this controls feet shuffling.
|
||||
/// If rotating clockwise this should be positive, if rotating counter-clockwise this should be negative.
|
||||
/// </summary>
|
||||
public float MoveRotationSpeed
|
||||
{
|
||||
get => Target.GetFloat( "move_rotationspeed" );
|
||||
set => Target.Set( "move_rotationspeed", value );
|
||||
}
|
||||
|
||||
[Obsolete( "Use MoveRotationSpeed" )]
|
||||
public float FootShuffle
|
||||
{
|
||||
get => Target.GetFloat( "move_shuffle" );
|
||||
set => Target.Set( "move_shuffle", value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The scale of being ducked (crouched) (0 - 1)
|
||||
/// </summary>
|
||||
[Sync] public float DuckLevel
|
||||
{
|
||||
get => Target.GetFloat( "duck" );
|
||||
set => Target.Set( "duck", value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How loud are we talking?
|
||||
/// </summary>
|
||||
public float VoiceLevel
|
||||
{
|
||||
get => Target.GetFloat( "voice" );
|
||||
set => Target.Set( "voice", value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Are we sitting down?
|
||||
/// </summary>
|
||||
public bool IsSitting
|
||||
{
|
||||
get => Target.GetBool( "b_sit" );
|
||||
set => Target.Set( "b_sit", value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Are we on the ground?
|
||||
/// </summary>
|
||||
public bool IsGrounded
|
||||
{
|
||||
get => Target.GetBool( "b_grounded" );
|
||||
set => Target.Set( "b_grounded", value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Are we swimming?
|
||||
/// </summary>
|
||||
public bool IsSwimming
|
||||
{
|
||||
get => Target.GetBool( "b_swim" );
|
||||
set => Target.Set( "b_swim", value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Are we climbing?
|
||||
/// </summary>
|
||||
public bool IsClimbing
|
||||
{
|
||||
get => Target.GetBool( "b_climbing" );
|
||||
set => Target.Set( "b_climbing", value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Are we noclipping?
|
||||
/// </summary>
|
||||
public bool IsNoclipping
|
||||
{
|
||||
get => Target.GetBool( "b_noclip" );
|
||||
set => Target.Set( "b_noclip", value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is the weapon lowered? By default, this'll happen when the character hasn't been shooting for a while.
|
||||
/// </summary>
|
||||
public bool IsWeaponLowered
|
||||
{
|
||||
get => Target.GetBool( "b_weapon_lower" );
|
||||
set => Target.Set( "b_weapon_lower", value );
|
||||
}
|
||||
|
||||
public enum HoldTypes
|
||||
{
|
||||
None,
|
||||
Pistol,
|
||||
Rifle,
|
||||
Shotgun,
|
||||
HoldItem,
|
||||
Punch,
|
||||
Swing,
|
||||
RPG
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// What kind of weapon are we holding?
|
||||
/// </summary>
|
||||
public HoldTypes HoldType
|
||||
{
|
||||
get => (HoldTypes)Target.GetInt( "holdtype" );
|
||||
set => Target.Set( "holdtype", (int)value );
|
||||
}
|
||||
|
||||
public enum Hand
|
||||
{
|
||||
Both,
|
||||
Right,
|
||||
Left
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// What's the handedness of our weapon? Left handed, right handed, or both hands? This is only supported by some holdtypes, like Pistol, HoldItem.
|
||||
/// </summary>
|
||||
public Hand Handedness
|
||||
{
|
||||
get => (Hand)Target.GetInt( "holdtype_handedness" );
|
||||
set => Target.Set( "holdtype_handedness", (int)value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers a jump animation
|
||||
/// </summary>
|
||||
[Broadcast] public void TriggerJump()
|
||||
{
|
||||
Target.Set( "b_jump", true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers a weapon deploy animation
|
||||
/// </summary>
|
||||
public void TriggerDeploy()
|
||||
{
|
||||
Target.Set( "b_deploy", true );
|
||||
}
|
||||
|
||||
public enum MoveStyles
|
||||
{
|
||||
Auto,
|
||||
Walk,
|
||||
Run
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We can force the model to walk or run, or let it decide based on the speed.
|
||||
/// </summary>
|
||||
public MoveStyles MoveStyle
|
||||
{
|
||||
get => (MoveStyles)Target.GetInt( "move_style" );
|
||||
set => Target.Set( "move_style", (int)value );
|
||||
}
|
||||
|
||||
public enum SpecialMoveStyle
|
||||
{
|
||||
None,
|
||||
LedgeGrab,
|
||||
Roll,
|
||||
Slide
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We can force the model to have a specific movement state, instead of just running around.
|
||||
/// <see cref="SpecialMoveStyle.LedgeGrab"/> is good for shimmying across a ledge.
|
||||
/// <see cref="SpecialMoveStyle.Roll"/> is good for a platformer game where the character is rolling around continuously.
|
||||
/// <see cref="SpecialMoveStyle.Slide"/> is good for a shooter game or a platformer where the character is sliding.
|
||||
/// </summary>
|
||||
public SpecialMoveStyle SpecialMove
|
||||
{
|
||||
get => (SpecialMoveStyle)Target.GetInt( "special_movement_states" );
|
||||
set => Target.Set( "special_movement_states", (int)value );
|
||||
}
|
||||
|
||||
//Sitting
|
||||
public enum SittingStyle
|
||||
{
|
||||
None,
|
||||
Chair,
|
||||
Floor
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How are we sitting down?
|
||||
/// </summary>
|
||||
public SittingStyle Sitting
|
||||
{
|
||||
get => (SittingStyle)Target.GetInt( "sit" );
|
||||
set => Target.Set( "sit", (int)value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How far up are we sitting down from the floor?
|
||||
/// </summary>
|
||||
public float SittingOffsetHeight
|
||||
{
|
||||
get => Target.GetFloat( "sit_offset_height" );
|
||||
set => Target.Set( "sit_offset_height", value );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// From 0-1, how much are we actually sitting down.
|
||||
/// </summary>
|
||||
public float SittingPose
|
||||
{
|
||||
get => Target.GetFloat( "sit_pose" );
|
||||
set => Target.Set( "sit_pose", value );
|
||||
}
|
||||
}
|
33
Code/Kal.cs
33
Code/Kal.cs
@ -4,8 +4,8 @@ using ShrimpleCharacterController;
|
||||
|
||||
public sealed class Kal : Component
|
||||
{
|
||||
[RequireComponent] public ShrimpleCharacterController.ShrimpleCharacterController Controller { get; set; }
|
||||
[RequireComponent] public CitizenAnimationHelper AnimationHelper { get; set; }
|
||||
[RequireComponent] private ShrimpleCharacterController.ShrimpleCharacterController Controller { get; set; }
|
||||
[RequireComponent] private AnimationHelper AnimationHelper { get; set; }
|
||||
public SkinnedModelRenderer Renderer { get; set; }
|
||||
[Property] public GameObject Body { get; set; }
|
||||
public GameObject Camera { get; set; }
|
||||
@ -16,18 +16,23 @@ public sealed class Kal : Component
|
||||
[Property] [Range(100f, 500f, 20f)] public float RunSpeed { get; set; } = 300f;
|
||||
[Property] [Range(25f, 100f, 5f)] public float DuckSpeed { get; set; } = 50f;
|
||||
[Property] [Range(200f, 500f, 20f)] public float JumpStrength { get; set; } = 350f;
|
||||
|
||||
[Sync] public Angles EyeAngles { get; set; }
|
||||
[Sync] public bool isDucking { get; set; } = false;
|
||||
[Sync] public bool isRunning { get; set; } = false;
|
||||
// [Sync] public bool IsDucking { get; set; }
|
||||
// [Sync] public bool IsRunning { get; set; }
|
||||
|
||||
protected override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
|
||||
Controller = Components.Get<ShrimpleCharacterController.ShrimpleCharacterController>();
|
||||
AnimationHelper = Components.Get<AnimationHelper>();
|
||||
|
||||
if ( !Network.IsOwner ) return;
|
||||
|
||||
Renderer = Components.Get<SkinnedModelRenderer>(FindMode.EverythingInSelfAndDescendants);
|
||||
Camera = new GameObject(true, "Camera");
|
||||
Camera = Scene.Camera.GameObject;
|
||||
|
||||
Camera.SetParent(GameObject);
|
||||
var cameraComponent = Camera.Components.Create<CameraComponent>();
|
||||
cameraComponent.ZFar = 32768f;
|
||||
@ -40,10 +45,10 @@ public sealed class Kal : Component
|
||||
if ( Network.IsOwner )
|
||||
{
|
||||
var wishDirection = Input.AnalogMove.Normal * Rotation.FromYaw( EyeAngles.yaw );
|
||||
isDucking = Input.Down( "Duck" );
|
||||
isRunning = Input.Down( "Run" );
|
||||
var wishSpeed = isDucking ? DuckSpeed :
|
||||
isRunning ? RunSpeed : WalkSpeed;
|
||||
var IsDucking = Input.Down( "Duck" );
|
||||
var IsRunning = Input.Down( "Run" );
|
||||
var wishSpeed = IsDucking ? DuckSpeed :
|
||||
IsRunning ? RunSpeed : WalkSpeed;
|
||||
|
||||
Controller.WishVelocity = wishDirection * wishSpeed;
|
||||
|
||||
@ -52,23 +57,19 @@ public sealed class Kal : Component
|
||||
if ( Input.Pressed( "Jump" ) && Controller.IsOnGround )
|
||||
{
|
||||
Controller.Punch( Vector3.Up * JumpStrength * 2f );
|
||||
AnimationHelper?.TriggerJump();
|
||||
AnimationHelper.TriggerJump();
|
||||
}
|
||||
|
||||
if ( !AnimationHelper.IsValid() ) return;
|
||||
|
||||
AnimationHelper.DuckLevel = IsDucking ? 1f : 0f;
|
||||
}
|
||||
|
||||
UpdateAnimations();
|
||||
Log.Info( AnimationHelper.HeadWeight );
|
||||
|
||||
}
|
||||
|
||||
void UpdateAnimations()
|
||||
{
|
||||
AnimationHelper.WithWishVelocity(Controller.WishVelocity);
|
||||
AnimationHelper.WithVelocity(Controller.Velocity);
|
||||
AnimationHelper.IsGrounded = Controller.IsOnGround;
|
||||
AnimationHelper.DuckLevel = isDucking ? 1f : 0f;
|
||||
}
|
||||
|
||||
protected override void OnUpdate()
|
||||
|
Loading…
x
Reference in New Issue
Block a user