diff --git a/Assets/maps/nunu.vmap b/Assets/maps/nunu.vmap index fd17948..37cbf4f 100644 Binary files a/Assets/maps/nunu.vmap and b/Assets/maps/nunu.vmap differ diff --git a/Assets/maps/nunu.vmap.meta b/Assets/maps/nunu.vmap.meta index 67a5b26..3d27c61 100644 --- a/Assets/maps/nunu.vmap.meta +++ b/Assets/maps/nunu.vmap.meta @@ -13,7 +13,8 @@ "EditorReferences": [], "IsWhitelistDisabled": false, "Metadata": { - "SingleAssetSource": "maps/nunu.vmap" + "SingleAssetSource": "maps/nunu.vmap", + "ParentPackage": "koptilnya.kakozuzo_2" } } } diff --git a/Assets/maps/test.vmap b/Assets/maps/test.vmap index 394b865..102d908 100644 Binary files a/Assets/maps/test.vmap and b/Assets/maps/test.vmap differ diff --git a/Assets/prefabs/player.prefab b/Assets/prefabs/player.prefab index 3040cb5..6ddace0 100644 --- a/Assets/prefabs/player.prefab +++ b/Assets/prefabs/player.prefab @@ -48,7 +48,11 @@ "_type": "gameobject", "go": "b99ceffc-a173-4a6e-a239-6d3c1612c09f" }, - "CamOffsetX": 200, + "CameraPivot": { + "_type": "gameobject", + "go": "b5ef1b0b-0e22-426c-9b22-e648a23e8504" + }, + "CamOffsetX": 115, "CamOffsetZ": 61, "DuckSpeed": 50, "JumpStrength": 350, @@ -69,6 +73,24 @@ "component_type": "SkinnedModelRenderer" } }, + { + "__type": "RagdollController", + "__guid": "5433b29f-ed75-4581-acfc-d99dda4ff64b", + "bodyPhysics": { + "_type": "component", + "component_id": "262154b8-438c-451e-b2c7-4d23d5c73120", + "go": "9ab6bf36-8cdf-4834-bd2a-238fc0cbf804", + "component_type": "ModelPhysics" + }, + "bodyRenderer": { + "_type": "component", + "component_id": "4fd8c36d-180b-41af-8439-6b975ca1c7b3", + "go": "b99ceffc-a173-4a6e-a239-6d3c1612c09f", + "component_type": "SkinnedModelRenderer" + }, + "impaledPhysicsBodyIndex": 0, + "isLocked": false + }, { "__type": "FootSteps", "__guid": "f6ee40f5-5541-4a85-bc06-259b451d0891", @@ -78,6 +100,31 @@ "go": "b99ceffc-a173-4a6e-a239-6d3c1612c09f", "component_type": "SkinnedModelRenderer" } + }, + { + "__type": "PlayerDresser", + "__guid": "cc66fd84-f698-4cf4-a1ac-e038245e37fd", + "BodyRenderer": { + "_type": "component", + "component_id": "4fd8c36d-180b-41af-8439-6b975ca1c7b3", + "go": "b99ceffc-a173-4a6e-a239-6d3c1612c09f", + "component_type": "SkinnedModelRenderer" + } + }, + { + "__type": "Sandbox.ModelPhysics", + "__guid": "262154b8-438c-451e-b2c7-4d23d5c73120", + "__enabled": false, + "Locking": {}, + "Model": "models/citizen/citizen.vmdl", + "MotionEnabled": true, + "Renderer": { + "_type": "component", + "component_id": "4fd8c36d-180b-41af-8439-6b975ca1c7b3", + "go": "b99ceffc-a173-4a6e-a239-6d3c1612c09f", + "component_type": "SkinnedModelRenderer" + }, + "RigidbodyFlags": 0 } ], "Children": [ @@ -951,6 +998,13 @@ "Enabled": true } ] + }, + { + "__guid": "b5ef1b0b-0e22-426c-9b22-e648a23e8504", + "Flags": 0, + "Name": "CameraPivot", + "Position": "2,0,50", + "Enabled": true } ] } diff --git a/Assets/scenes/minimal.scene b/Assets/scenes/minimal.scene index ce6d681..ff37dd1 100644 --- a/Assets/scenes/minimal.scene +++ b/Assets/scenes/minimal.scene @@ -336,6 +336,7 @@ "__guid": "cf125021-fa85-46d4-9ad8-6ea4ac3cc1e9", "Flags": 0, "Name": "mmm", + "Position": "0,0,-300", "Enabled": true, "Components": [ { diff --git a/Code/Kal.cs b/Code/Kal.cs index da55389..4ae97bb 100644 --- a/Code/Kal.cs +++ b/Code/Kal.cs @@ -1,3 +1,4 @@ +using System; using Sandbox.Citizen; using Sandbox.Network; using ShrimpleCharacterController; @@ -8,6 +9,7 @@ public sealed class Kal : Component [RequireComponent] private AnimationHelper AnimationHelper { get; set; } public SkinnedModelRenderer Renderer { get; set; } [Property] public GameObject Body { get; set; } + [Property] public GameObject CameraPivot { get; set; } public GameObject Camera { get; set; } [Property] [Range(1f, 200f, 1f)] public float CamOffsetX { get; set; } @@ -41,7 +43,7 @@ public sealed class Kal : Component protected override void OnFixedUpdate() { base.OnFixedUpdate(); - + if ( Network.IsOwner ) { var wishDirection = Input.AnalogMove.Normal * Rotation.FromYaw( EyeAngles.yaw ); @@ -51,7 +53,7 @@ public sealed class Kal : Component IsRunning ? RunSpeed : WalkSpeed; Controller.WishVelocity = wishDirection * wishSpeed; - + Controller.Move(); if ( Input.Pressed( "Jump" ) && Controller.IsOnGround ) @@ -59,14 +61,12 @@ public sealed class Kal : Component Controller.Punch( Vector3.Up * JumpStrength ); AnimationHelper.TriggerJump(); } - + if ( !AnimationHelper.IsValid() ) return; - + AnimationHelper.DuckLevel = IsDucking ? 1f : 0f; } - - Log.Info( AnimationHelper.HeadWeight ); - + AnimationHelper.WithWishVelocity(Controller.WishVelocity); AnimationHelper.WithVelocity(Controller.Velocity); AnimationHelper.IsGrounded = Controller.IsOnGround; @@ -80,11 +80,14 @@ public sealed class Kal : Component { EyeAngles += Input.AnalogLook; EyeAngles = EyeAngles.WithPitch(MathX.Clamp(EyeAngles.pitch, -90f, 70f)); - // Renderer.WorldRotation = Rotation.Slerp(Renderer.WorldRotation, Rotation.FromYaw(EyeAngles.yaw), Time.Delta * 5f); - var cameraOffset = Vector3.Up * CamOffsetZ + Vector3.Backward * CamOffsetX; - Camera.WorldRotation = EyeAngles.ToRotation(); - Camera.LocalPosition = cameraOffset * Camera.WorldRotation; + //Vector3.Up * (CamOffsetZ - Math.Abs(EyeAngles.pitch * .5f) ) + + cameraOffset * EyeAngles.ToRotation() + + var cameraOffset = Vector3.Backward * (CamOffsetX + EyeAngles.pitch * .5f) - Vector3.Left * 20f; + + + Camera.WorldPosition = CameraPivot.WorldPosition + cameraOffset * EyeAngles.ToRotation(); + Camera.WorldRotation = EyeAngles.ToRotation(); } RotateBody(); diff --git a/Code/RagdollController.cs b/Code/RagdollController.cs new file mode 100644 index 0000000..7262449 --- /dev/null +++ b/Code/RagdollController.cs @@ -0,0 +1,130 @@ +using Sandbox.Utils; +public sealed class RagdollController : Component +{ + [Group("Setup"), Order(-100), Property] public ModelPhysics bodyPhysics { get; set; } + [Group("Setup"), Order(-100), Property] public SkinnedModelRenderer bodyRenderer { get; set; } + + [Group("Config"), Order(0), Property, Range(0, 15)] public int impaledPhysicsBodyIndex { get; set; } + [Group("Config"), Order(0), Property] public bool isLocked { get; set; } + [Group("Runtime"), Order(100), Property] public PhysicsBody impaledPhysicsBody { get; set; } + + // Sensible Indexes + // 3 - HEad + + public void Toggle() + { + bool enable = !bodyPhysics.Enabled; + bodyPhysics.Enabled = enable; + bodyPhysics.MotionEnabled = enable; + bodyRenderer.UseAnimGraph = !enable; + } + + public void EnableRagdoll() + { + bool enable = true; + bodyPhysics.Enabled = enable; + bodyPhysics.MotionEnabled = enable; + bodyRenderer.UseAnimGraph = !enable; + } + + public void DisableRagdoll() + { + bool enable = false; + } + + void UpdateBody() + { + //impaledPhysicsBodyIndexRemapped = GetClosestSafeIndex(impaledPhysicsBodyIndex); + + var bodyLock = new PhysicsLock(); + bodyLock.Pitch = isLocked; + bodyLock.Yaw = isLocked; + bodyLock.Roll = isLocked; + bodyLock.X = isLocked; + bodyLock.Y = isLocked; + bodyLock.Z = isLocked; + + bodyPhysics.Locking = bodyLock; + bodyPhysics.MotionEnabled = !isLocked; + + if (isLocked) + { + return; + } + + if (!bodyPhysics.Enabled) + { + return; + } + + impaledPhysicsBody = bodyPhysics.PhysicsGroup.Bodies.ElementAt(impaledPhysicsBodyIndex); + + var followToPos = GameObject.Transform.World.Position;// - (GameObject.Transform.World.Forward * 30.0f); + + // If this was + if (impaledPhysicsBodyIndex == Bones.Terry.spine_0) + { + followToPos += Vector3.Up * 10.0f; + } + + //hitPhysicsBody.Position = followToPos; + var delta = Vector3.Direction(impaledPhysicsBody.Position, followToPos); + + impaledPhysicsBody.Velocity = delta * 500.0f; + //impaledPhysicsBody.Velocity = Vector3.Zero; + //impaledPhysicsBody.Position = MathY.MoveTowards(impaledPhysicsBody.Position, followToPos, Time.Delta * 100.0f); + //Log.Info($"delta.Length: {delta.Length}, impaledByHarpoonSpear.isInFlight: {impaledByHarpoonSpear.isInFlight}"); + + bool useOriginalMethod = true; + if (useOriginalMethod) //delta.Length < 15.0f)// && !impaledByHarpoonSpear.isInFlight) + { + impaledPhysicsBody.Velocity = delta * 1000.0f; + impaledPhysicsBody.Velocity = Vector3.Zero; + impaledPhysicsBody.AngularVelocity = MathY.MoveTowards(impaledPhysicsBody.AngularVelocity, Vector3.Zero, Time.Delta * 15.0f); + impaledPhysicsBody.AngularVelocity = Vector3.Zero; + impaledPhysicsBody.Position = followToPos; + + + + //impaledPhysicsBody.Velocity = delta * 100.0f; + //impaledPhysicsBody.Position = MathY.MoveTowards(impaledPhysicsBody.Position, followToPos, Time.Delta * 1000.0f); + } + else + { + float smoothRate = 0.075f; + smoothRate = 0.0001f; + + float smoothRateRot = 0.075f; + //smoothRateRot = 0.0001f; + + + var velocity = impaledPhysicsBody.Velocity; + Vector3.SmoothDamp(impaledPhysicsBody.Position, WorldPosition, ref velocity, smoothRate, Time.Delta); + impaledPhysicsBody.Velocity = velocity; + + var angularVelocity = impaledPhysicsBody.AngularVelocity; + Rotation.SmoothDamp(impaledPhysicsBody.Rotation, WorldRotation, ref angularVelocity, smoothRateRot, Time.Delta); + impaledPhysicsBody.AngularVelocity = angularVelocity; + + //impaledPhysicsBody.AngularVelocity = Vector3.Zero; + } + } + + protected override void OnUpdate() + { + if ( Network.IsOwner ) + { + if(Input.Pressed( "Ragdoll" )) + { + Toggle(); + } + } + + UpdateBody(); + } + + protected override void OnFixedUpdate() + { + + } +} diff --git a/Code/Utils/Bones.cs b/Code/Utils/Bones.cs new file mode 100644 index 0000000..aa793ff --- /dev/null +++ b/Code/Utils/Bones.cs @@ -0,0 +1,23 @@ +namespace Sandbox.Utils; +public static partial class Bones +{ + public static class Terry + { + public const int pelvis = 0; + public const int spine_0 = 1; + public const int spine_2 = 2; + public const int head = 3; + public const int arm_upper_R = 4; + public const int arm_lower_R = 5; + public const int hand_R = 6; + public const int arm_upper_L = 7; + public const int arm_lower_L = 8; + public const int hand_L = 9; + public const int leg_upper_R = 10; + public const int leg_lower_R = 11; + public const int ankle_R = 12; + public const int leg_upper_L = 13; + public const int leg_lower_L = 14; + public const int ankle_L = 15; + } +} diff --git a/Code/Utils/MathY.cs b/Code/Utils/MathY.cs new file mode 100644 index 0000000..774b4ea --- /dev/null +++ b/Code/Utils/MathY.cs @@ -0,0 +1,182 @@ +using System.Numerics; +namespace Sandbox.Utils; + +public static class MathY +{ + public const float inchToMeter = 0.0254f; + + public static Vector3 MoveTowards(Vector3 current, Vector3 target, float maxDistanceDelta) + { + Vector3 direction = target - current; + + float distance = direction.Length; + + if (distance <= maxDistanceDelta) + { + return target; + } + else + { + + Vector3 scaledDirection = direction.Normal * maxDistanceDelta; + + Vector3 newPosition = current + scaledDirection; + + return newPosition; + } + } + + public static float MoveTowards(float current, float target, float maxDelta) + { + if (System.Math.Abs(target - current) <= maxDelta) + { + return target; + } + + return current + System.Math.Sign(target - current) * maxDelta; + } + + public static Vector3 GetRandomizedDirection(Vector3 originalDirection, float maxAngle) + { + float pitch = Game.Random.Float(-maxAngle, maxAngle); + float yaw = Game.Random.Float(-maxAngle, maxAngle); + float roll = Game.Random.Float(-maxAngle, maxAngle); + + Rotation randomRotation = Rotation.From(pitch, yaw, roll); + Vector3 randomizedDirection = randomRotation * originalDirection; + + return randomizedDirection.Normal; + } + + public static float RandomRange(this Vector2 inst) + { + return Game.Random.Float(inst.x, inst.y); + } + + public static float Clamp(float value, float min, float max) + { + if (value < min) + value = min; + else if (value > max) + value = max; + return value; + } + + public static int Clamp(int value, int min, int max) + { + if (value < min) + value = min; + else if (value > max) + value = max; + return value; + } + + public static float Clamp01(float value) + { + if (value < 0F) + return 0F; + else if (value > 1F) + return 1F; + else + return value; + } + + public static float Lerp(float a, float b, float t) + { + return a + (b - a) * Clamp01(t); + } + + public static float LerpUnclamped(float a, float b, float t) + { + return a + (b - a) * t; + } + + public static float InverseLerp(float a, float b, float v) + { + if (a != b) + return Clamp01((v - a) / (b - a)); + else + return 0.0f; + } + + public static float InverseLerpUnclamped(float a, float b, float v) + { + return (v - a) / (b - a); + } + + public static float InverseLerpUnclamped(float max, float v) + { + return v / max; + } + + public static float InverseLerpUnclamped(Vector2 range, float v) + { + return (v - range.x) / (range.y - range.x); + } + + public static float Lerp(this Vector2 vector, float t) + { + return MathX.Lerp(vector.x, vector.y, t); + } + + public static float InverseLerp(this Vector2 vector, float t) + { + return MathX.LerpInverse(t, vector.x, vector.y); + } + + public static int Min(int a, int b) + { + return (a < b) ? a : b; + } + + public static int Max(int a, int b) + { + return (a > b) ? a : b; + } + + public static float Min(float a, float b) + { + return (a < b) ? a : b; + } + + public static float Max(float a, float b) + { + return (a > b) ? a : b; + } +} + +public class Remap +{ + [KeyProperty] public Vector2 fromRange { get; set; } + [KeyProperty] public Vector2 toRange { get; set; } + [KeyProperty] public Curve remapCurve { get; set; } + + public Remap() + { + fromRange = new Vector2(0.0f, 1.0f); + toRange = new Vector2(0.0f, 1.0f); + remapCurve = new Curve(new Curve.Frame(0.0f, 0.0f, 0.0f, 1.0f), new Curve.Frame(1.0f, 1.0f, -1.0f, 0.0f)); + } + + public Remap(float minFromRange, float maxFromRange) + { + fromRange = new Vector2(minFromRange, maxFromRange); + toRange = new Vector2(0.0f, 1.0f); + remapCurve = new Curve(new Curve.Frame(0.0f, 0.0f, 0.0f, 1.0f), new Curve.Frame(1.0f, 1.0f, -1.0f, 0.0f)); + } + + public Remap(float minFromRange, float maxFromRange, float minToRange, float maxToRange) + { + fromRange = new Vector2(minFromRange, maxFromRange); + toRange = new Vector2(minToRange, maxToRange); + remapCurve = new Curve(new Curve.Frame(0.0f, 0.0f, 0.0f, 1.0f), new Curve.Frame(1.0f, 1.0f, -1.0f, 0.0f)); + } + + public float Evaluate(float value) + { + float result = MathX.LerpInverse(value, fromRange.x, fromRange.y); + result = remapCurve.Evaluate(result); + result = MathX.Lerp(toRange.x, toRange.y, result); + return result; + } +} diff --git a/ProjectSettings/Input.config b/ProjectSettings/Input.config index 0c213d6..0e96e3d 100644 --- a/ProjectSettings/Input.config +++ b/ProjectSettings/Input.config @@ -134,7 +134,7 @@ }, { "Name": "SlotPrev", - "KeyboardCode": "mouse4", + "KeyboardCode": "MOUSE4", "GamepadCode": "SwitchLeftBumper", "GroupName": "Inventory" }, @@ -185,6 +185,12 @@ "KeyboardCode": "enter", "GamepadCode": "None", "GroupName": "Other" + }, + { + "Name": "Ragdoll", + "KeyboardCode": "mouse4", + "GamepadCode": "None", + "GroupName": "Other" } ], "__guid": "0227f25a-537a-4f15-a72a-90f6af33742f", diff --git a/kakozuzo_2.sbproj b/kakozuzo_2.sbproj index 4ccb791..4054e16 100644 --- a/kakozuzo_2.sbproj +++ b/kakozuzo_2.sbproj @@ -25,6 +25,7 @@ "StartupScene": "scenes/minimal.scene", "MapStartupScene": "scenes/minimal.scene", "LaunchMode": "Normal", - "DedicatedServerStartupScene": "scenes/minimal.scene" + "DedicatedServerStartupScene": "scenes/minimal.scene", + "ControlModes": {} } } \ No newline at end of file diff --git a/kakozuzo_2.sln.DotSettings.user b/kakozuzo_2.sln.DotSettings.user index b69930c..ca5de4c 100644 --- a/kakozuzo_2.sln.DotSettings.user +++ b/kakozuzo_2.sln.DotSettings.user @@ -1,6 +1,8 @@  True True + ForceIncluded + ForceIncluded ForceIncluded ForceIncluded \ No newline at end of file