complete project reorganization
This commit is contained in:
21
scenes/player_controller/LICENSE
Normal file
21
scenes/player_controller/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 PolarBears studio
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
1133
scenes/player_controller/PlayerController.tscn
Normal file
1133
scenes/player_controller/PlayerController.tscn
Normal file
File diff suppressed because it is too large
Load Diff
73
scenes/player_controller/PlayerUi.cs
Normal file
73
scenes/player_controller/PlayerUi.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using Movementtests.interfaces;
|
||||
|
||||
[GlobalClass, Icon("res://assets/ui/IconGodotNode/control/icon_text_panel.png")]
|
||||
public partial class PlayerUi : Control
|
||||
{
|
||||
private TextureRect[] _dashIcons = new TextureRect[3];
|
||||
private TextureRect _enemyTarget;
|
||||
private Healthbar _healthbar;
|
||||
|
||||
public enum TargetState
|
||||
{
|
||||
NoTarget,
|
||||
TargetWouldNotKill,
|
||||
TargetWouldKill
|
||||
}
|
||||
|
||||
public record TargetProperties(TargetState State, Vector2 Position);
|
||||
|
||||
[Export]
|
||||
public Color WouldKillColor { get; set; } = new Color("009c8f");
|
||||
[Export]
|
||||
public Color WouldNotKillColor { get; set; } = new Color("fc001c");
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_dashIcons[0] = GetNode<TextureRect>("%Dash1");
|
||||
_dashIcons[1] = GetNode<TextureRect>("%Dash2");
|
||||
_dashIcons[2] = GetNode<TextureRect>("%Dash3");
|
||||
|
||||
_enemyTarget = GetNode<TextureRect>("%EnemyTarget");
|
||||
_healthbar = GetNode<Healthbar>("%Healthbar");
|
||||
}
|
||||
|
||||
public void Initialize(float initialHealth)
|
||||
{
|
||||
_healthbar.Initialize(initialHealth);
|
||||
}
|
||||
|
||||
public void SetEnemyTargetProperties(TargetProperties targetProperties)
|
||||
{
|
||||
var (state, position) = targetProperties;
|
||||
|
||||
var visible = state != TargetState.NoTarget;
|
||||
|
||||
var modulation = state switch
|
||||
{
|
||||
TargetState.TargetWouldNotKill => WouldNotKillColor,
|
||||
TargetState.TargetWouldKill => WouldKillColor,
|
||||
_ => WouldNotKillColor
|
||||
};
|
||||
_enemyTarget.SetVisible(visible);
|
||||
_enemyTarget.SetPosition(position - _enemyTarget.Size / 2);
|
||||
_enemyTarget.SetModulate(modulation);
|
||||
}
|
||||
|
||||
|
||||
public void SetNumberOfDashesLeft(int numberOfDashes)
|
||||
{
|
||||
int index = 1;
|
||||
foreach (var dashIcon in _dashIcons)
|
||||
{
|
||||
dashIcon.SetVisible(index <= numberOfDashes);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnHealthChanged(IHealthable healthable, HealthChangedRecord healthChanged)
|
||||
{
|
||||
_healthbar.CurrentHealth = healthChanged.CurrentHealth;
|
||||
}
|
||||
}
|
||||
1
scenes/player_controller/PlayerUi.cs.uid
Normal file
1
scenes/player_controller/PlayerUi.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bhuwv2nlcrunt
|
||||
119
scenes/player_controller/audio/InteractiveSFX.tres
Normal file
119
scenes/player_controller/audio/InteractiveSFX.tres
Normal file
@@ -0,0 +1,119 @@
|
||||
[gd_resource type="AudioStreamInteractive" format=3 uid="uid://clfggn87oeg1s"]
|
||||
|
||||
[ext_resource type="AudioStream" uid="uid://dedx5ronjavvh" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Footsteps/Dirt/Dirt Run 1.ogg" id="1_tkpjh"]
|
||||
[ext_resource type="AudioStream" uid="uid://gihwx3xm7qoq" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Footsteps/Dirt/Dirt Run 2.ogg" id="2_npc7y"]
|
||||
[ext_resource type="AudioStream" uid="uid://qr5qyql01rf5" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Footsteps/Dirt/Dirt Run 3.ogg" id="3_xfjxc"]
|
||||
[ext_resource type="AudioStream" uid="uid://blbvci0fvniy3" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Footsteps/Dirt/Dirt Run 4.ogg" id="4_ycvo6"]
|
||||
[ext_resource type="AudioStream" uid="uid://d01n6qtsadqvm" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Footsteps/Dirt/Dirt Run 5.ogg" id="5_5bvpy"]
|
||||
[ext_resource type="AudioStream" uid="uid://2joty7h4guqs" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Footsteps/Dirt/Dirt Jump.ogg" id="6_w27l5"]
|
||||
[ext_resource type="AudioStream" uid="uid://d0pwtd271fukd" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Footsteps/Dirt/Dirt Land.ogg" id="7_5j00h"]
|
||||
[ext_resource type="AudioStream" uid="uid://co335a0d00667" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Attacks/Sword Attacks Hits and Blocks/Sword Attack 1.ogg" id="8_r7v0u"]
|
||||
[ext_resource type="AudioStream" uid="uid://dtl4blkueud3n" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Attacks/Sword Attacks Hits and Blocks/Sword Attack 2.ogg" id="9_l756u"]
|
||||
[ext_resource type="AudioStream" uid="uid://bd8n4slwggxrq" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Attacks/Sword Attacks Hits and Blocks/Sword Attack 3.ogg" id="10_7b65l"]
|
||||
[ext_resource type="AudioStream" uid="uid://jwy682rlwm2v" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Attacks/Sword Attacks Hits and Blocks/Sword Impact Hit 1.ogg" id="11_447ch"]
|
||||
[ext_resource type="AudioStream" uid="uid://cn6j83octlmg1" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Attacks/Sword Attacks Hits and Blocks/Sword Impact Hit 2.ogg" id="12_1yt5p"]
|
||||
[ext_resource type="AudioStream" uid="uid://buqmqota12r4g" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Attacks/Sword Attacks Hits and Blocks/Sword Impact Hit 3.ogg" id="13_t5u7s"]
|
||||
[ext_resource type="AudioStream" uid="uid://cm4332loplxmb" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Attacks/Sword Attacks Hits and Blocks/Sword Blocked 1.ogg" id="14_qnngs"]
|
||||
[ext_resource type="AudioStream" uid="uid://dhw1imlbuu7nl" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Attacks/Sword Attacks Hits and Blocks/Sword Blocked 2.ogg" id="15_3j1dm"]
|
||||
[ext_resource type="AudioStream" uid="uid://bis0qp2jqrwl7" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Attacks/Sword Attacks Hits and Blocks/Sword Blocked 3.ogg" id="16_hln0b"]
|
||||
[ext_resource type="AudioStream" uid="uid://dka35ab4pudfn" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Footsteps/Dirt/Dirt Chain Jump.ogg" id="17_npc7y"]
|
||||
[ext_resource type="AudioStream" uid="uid://4rhskycj4qqp" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Spells/Fireball 1.ogg" id="18_ycvo6"]
|
||||
[ext_resource type="AudioStream" uid="uid://bk03bbt0bbdu4" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Waterfalls Rivers and Streams/Waterfall Loop.ogg" id="19_5bvpy"]
|
||||
[ext_resource type="AudioStream" uid="uid://dn04ssm4qonxs" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Spells/Fireball 2.ogg" id="19_5j00h"]
|
||||
[ext_resource type="AudioStream" uid="uid://bsb2crsm8gkmc" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Spells/Fireball 3.ogg" id="20_r7v0u"]
|
||||
[ext_resource type="AudioStream" uid="uid://4mx3c0ercvu1" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Spells/Rock Wall 1.ogg" id="21_r7v0u"]
|
||||
[ext_resource type="AudioStream" uid="uid://bg4ujtrihj1jl" path="res://assets/audio/sfx/Free Fantasy SFX Pack By TomMusic/OGG Files/SFX/Spells/Rock Wall 2.ogg" id="22_l756u"]
|
||||
|
||||
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_rs8q3"]
|
||||
random_pitch = 1.1
|
||||
streams_count = 5
|
||||
stream_0/stream = ExtResource("1_tkpjh")
|
||||
stream_1/stream = ExtResource("2_npc7y")
|
||||
stream_2/stream = ExtResource("3_xfjxc")
|
||||
stream_3/stream = ExtResource("4_ycvo6")
|
||||
stream_4/stream = ExtResource("5_5bvpy")
|
||||
|
||||
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_r7v0u"]
|
||||
random_pitch = 1.0999973
|
||||
streams_count = 3
|
||||
stream_0/stream = ExtResource("14_qnngs")
|
||||
stream_1/stream = ExtResource("15_3j1dm")
|
||||
stream_2/stream = ExtResource("16_hln0b")
|
||||
|
||||
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_i5yri"]
|
||||
random_pitch = 1.1
|
||||
streams_count = 3
|
||||
stream_0/stream = ExtResource("8_r7v0u")
|
||||
stream_1/stream = ExtResource("9_l756u")
|
||||
stream_2/stream = ExtResource("10_7b65l")
|
||||
|
||||
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_5cmm3"]
|
||||
random_pitch = 1.1
|
||||
streams_count = 3
|
||||
stream_0/stream = ExtResource("11_447ch")
|
||||
stream_1/stream = ExtResource("12_1yt5p")
|
||||
stream_2/stream = ExtResource("13_t5u7s")
|
||||
|
||||
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_jjm4g"]
|
||||
random_pitch = 1.1
|
||||
streams_count = 3
|
||||
stream_0/stream = ExtResource("14_qnngs")
|
||||
stream_1/stream = ExtResource("15_3j1dm")
|
||||
stream_2/stream = ExtResource("16_hln0b")
|
||||
|
||||
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_l756u"]
|
||||
random_pitch = 1.1
|
||||
streams_count = 3
|
||||
stream_0/stream = ExtResource("18_ycvo6")
|
||||
stream_1/stream = ExtResource("19_5j00h")
|
||||
stream_2/stream = ExtResource("20_r7v0u")
|
||||
|
||||
[sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_7b65l"]
|
||||
random_pitch = 1.1
|
||||
streams_count = 2
|
||||
stream_0/stream = ExtResource("21_r7v0u")
|
||||
stream_1/stream = ExtResource("22_l756u")
|
||||
|
||||
[resource]
|
||||
clip_count = 11
|
||||
clip_0/name = &"footsteps"
|
||||
clip_0/stream = SubResource("AudioStreamRandomizer_rs8q3")
|
||||
clip_0/auto_advance = 0
|
||||
clip_1/name = &"jump"
|
||||
clip_1/stream = ExtResource("6_w27l5")
|
||||
clip_1/auto_advance = 0
|
||||
clip_2/name = &"land"
|
||||
clip_2/stream = ExtResource("7_5j00h")
|
||||
clip_2/auto_advance = 0
|
||||
clip_3/name = &"mantle"
|
||||
clip_3/stream = ExtResource("17_npc7y")
|
||||
clip_3/auto_advance = 0
|
||||
clip_4/name = &"attacks"
|
||||
clip_4/stream = SubResource("AudioStreamRandomizer_i5yri")
|
||||
clip_4/auto_advance = 0
|
||||
clip_5/name = &"hits"
|
||||
clip_5/stream = SubResource("AudioStreamRandomizer_5cmm3")
|
||||
clip_5/auto_advance = 0
|
||||
clip_6/name = &"damage_taken"
|
||||
clip_6/stream = SubResource("AudioStreamRandomizer_jjm4g")
|
||||
clip_6/auto_advance = 0
|
||||
clip_7/name = &"dash"
|
||||
clip_7/stream = SubResource("AudioStreamRandomizer_l756u")
|
||||
clip_7/auto_advance = 0
|
||||
clip_8/name = &"slam"
|
||||
clip_8/stream = SubResource("AudioStreamRandomizer_7b65l")
|
||||
clip_8/auto_advance = 0
|
||||
clip_9/name = &"glide"
|
||||
clip_9/stream = ExtResource("19_5bvpy")
|
||||
clip_9/auto_advance = 0
|
||||
clip_10/name = &"parry"
|
||||
clip_10/stream = SubResource("AudioStreamRandomizer_r7v0u")
|
||||
clip_10/auto_advance = 0
|
||||
_transitions = {
|
||||
Vector2i(-1, -1): {
|
||||
"fade_beats": 1.0,
|
||||
"fade_mode": 4,
|
||||
"from_time": 0,
|
||||
"to_time": 1
|
||||
}
|
||||
}
|
||||
160
scenes/player_controller/components/dash/DashSystem.cs
Normal file
160
scenes/player_controller/components/dash/DashSystem.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
using Godot;
|
||||
using Movementtests.interfaces;
|
||||
|
||||
namespace Movementtests.systems;
|
||||
|
||||
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_wind.png")]
|
||||
public partial class DashSystem: Node3D
|
||||
{
|
||||
public record DashLocation(bool HasHit, Vector3 TargetLocation, Vector3 CollisionPoint, Vector3 CollisionNormal, GodotObject HitObject = null);
|
||||
|
||||
|
||||
[Export(PropertyHint.Range, "0,0.2,0.01,or_greater")]
|
||||
public float DashSpeed { get; set; } = 0.1f;
|
||||
[Export(PropertyHint.Range, "0,1000,1,or_greater")]
|
||||
public float PostDashSpeed { get; set; } = 0f;
|
||||
|
||||
public bool HasHit { get; set; }
|
||||
public bool CanDashThroughTarget { get; set; }
|
||||
public Vector3 TargetLocation { get; set; }
|
||||
public Vector3 CollisionPoint { get; set; }
|
||||
public Vector3 CollisionNormal { get; set; }
|
||||
public GodotObject CollidedObject { get; set; }
|
||||
public Vector3 PlannedLocation { get; set; }
|
||||
|
||||
public bool ShouldMantle { get; set; }
|
||||
public Vector3 PlannedMantleLocation { get; set; }
|
||||
public MantleSystem MantleSystem { get; set; }
|
||||
|
||||
private HeadSystem _head;
|
||||
public ShapeCast3D DashCast3D;
|
||||
private Camera3D _camera;
|
||||
private Vector3 _dashDirection = Vector3.Zero;
|
||||
|
||||
private ShapeCast3D _dashCastDrop;
|
||||
private MeshInstance3D _dashDropIndicator;
|
||||
private MeshInstance3D _dashDropLocationIndicator;
|
||||
|
||||
private MeshInstance3D _dashTarget;
|
||||
private CpuParticles3D _dashIndicator;
|
||||
private AnimationPlayer _dashIndicatorAnim;
|
||||
|
||||
[Export]
|
||||
public PackedScene DashIndicatorScene { get; set; }
|
||||
|
||||
[Signal]
|
||||
public delegate void DashStartedEventHandler();
|
||||
[Signal]
|
||||
public delegate void DashEndedEventHandler();
|
||||
[Signal]
|
||||
public delegate void DashProgressEventHandler(float progress);
|
||||
|
||||
private Vector3 _globalDashPosition = Vector3.Zero;
|
||||
|
||||
public float DashCastRadius { get; set; }
|
||||
|
||||
public void Init(HeadSystem head, Camera3D camera)
|
||||
{
|
||||
DashCast3D = GetNode<ShapeCast3D>("DashCast3D");
|
||||
var dashShape = DashCast3D.GetShape() as SphereShape3D;
|
||||
DashCastRadius = dashShape!.Radius;
|
||||
|
||||
_dashCastDrop = GetNode<ShapeCast3D>("DashCastDrop");
|
||||
_dashDropIndicator = GetNode<MeshInstance3D>("DashDropIndicator");
|
||||
_dashDropIndicator.Visible = false;
|
||||
_dashDropLocationIndicator = GetNode<MeshInstance3D>("DashDropLocationIndicator");
|
||||
_dashDropLocationIndicator.Visible = false;
|
||||
|
||||
_head = head;
|
||||
_camera = camera;
|
||||
|
||||
MantleSystem = GetNode<MantleSystem>("MantleSystem");
|
||||
MantleSystem.Init();
|
||||
|
||||
_dashTarget = GetNode<MeshInstance3D>("DashTarget");
|
||||
_dashTarget.SetVisible(false);
|
||||
_dashIndicator = GetNode<CpuParticles3D>("DashIndicator");
|
||||
_dashIndicatorAnim = GetNode<AnimationPlayer>("DashIndicator/AnimationPlayer");
|
||||
}
|
||||
|
||||
private DashLocation ComputeDashLocation()
|
||||
{
|
||||
var targetLocation = DashCast3D.ToGlobal(DashCast3D.TargetPosition);
|
||||
var hasHit = DashCast3D.IsColliding();
|
||||
if (!hasHit)
|
||||
{
|
||||
return new DashLocation(false, targetLocation, Vector3.Zero, Vector3.Zero);
|
||||
}
|
||||
|
||||
var collisionPoint = DashCast3D.GetCollisionPoint(0);
|
||||
var collisionNormal = DashCast3D.GetCollisionNormal(0);
|
||||
var collidedObject = DashCast3D.GetCollider(0);
|
||||
|
||||
var fraction = DashCast3D.GetClosestCollisionSafeFraction();
|
||||
var globalSweepPath = targetLocation - DashCast3D.GlobalPosition;
|
||||
var locationAlongPath = DashCast3D.GlobalPosition + globalSweepPath * fraction;
|
||||
return new DashLocation(true, locationAlongPath, collisionPoint, collisionNormal, collidedObject);
|
||||
}
|
||||
|
||||
public void PrepareDash()
|
||||
{
|
||||
DashCast3D.SetRotation(_head.GetGlobalLookRotation());
|
||||
|
||||
(HasHit, PlannedLocation, CollisionPoint, CollisionNormal, CollidedObject) = ComputeDashLocation();
|
||||
CanDashThroughTarget = false;
|
||||
if (CollidedObject is ITargetable targetable)
|
||||
{
|
||||
_dashTarget.SetVisible(false);
|
||||
CanDashThroughTarget = true;
|
||||
return;
|
||||
}
|
||||
|
||||
MantleSystem.SetGlobalPosition(PlannedLocation);
|
||||
MantleSystem.SetRotation(new Vector3(
|
||||
MantleSystem.Rotation.X,
|
||||
_head.Rotation.Y,
|
||||
MantleSystem.Rotation.Z));
|
||||
MantleSystem.ProcessMantle(false);
|
||||
ShouldMantle = MantleSystem.IsMantlePossible;
|
||||
|
||||
// Setup dash target
|
||||
var targetColor = HasHit ? new Color(1f, 0.2f, 0.2f) : new Color(1f, 1f, 1f);
|
||||
targetColor = ShouldMantle ? new Color(0.2f, 0.2f, 1f) : targetColor;
|
||||
var targetMaterial = (StandardMaterial3D) _dashTarget.GetSurfaceOverrideMaterial(0);
|
||||
targetMaterial.SetAlbedo(targetColor);
|
||||
_dashTarget.SetVisible(true);
|
||||
var targetLocation = ShouldMantle ? MantleSystem.FirstMantleProfilePoint : PlannedLocation;
|
||||
_dashTarget.SetGlobalPosition(targetLocation);
|
||||
return;
|
||||
|
||||
var shouldShowDropIndicator = !HasHit && !ShouldMantle;
|
||||
_dashDropIndicator.SetVisible(shouldShowDropIndicator);
|
||||
_dashDropLocationIndicator.SetVisible(shouldShowDropIndicator);
|
||||
if (shouldShowDropIndicator)
|
||||
{
|
||||
_dashCastDrop.GlobalPosition = targetLocation; // Place drop indication cast at dash location
|
||||
var startDropLocation = targetLocation; // Start of the drop is the dash target location
|
||||
|
||||
// End of the drop is either max cast distance or first collision
|
||||
var hasDropLocationHit = _dashCastDrop.IsColliding();
|
||||
var endDropLocation = hasDropLocationHit ? _dashCastDrop.GetCollisionPoint(0) : _dashCastDrop.ToGlobal(DashCast3D.TargetPosition);
|
||||
|
||||
// Only show drop location indicator if drop cast has hit
|
||||
_dashDropLocationIndicator.SetVisible(hasDropLocationHit);
|
||||
_dashDropLocationIndicator.SetGlobalPosition(endDropLocation);
|
||||
|
||||
var dropLength = (endDropLocation - startDropLocation).Length();
|
||||
var dropDirection = (endDropLocation - startDropLocation).Normalized();
|
||||
_dashDropIndicator.SetScale(new Vector3(1, dropLength, 1));
|
||||
_dashDropIndicator.SetGlobalPosition(startDropLocation + dropDirection * dropLength * 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
public void StopPreparingDash()
|
||||
{
|
||||
CanDashThroughTarget = false;
|
||||
_dashTarget.SetVisible(false);
|
||||
_dashDropIndicator.SetVisible(false);
|
||||
_dashDropLocationIndicator.SetVisible(false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://dwoppk8j5fxeg
|
||||
77
scenes/player_controller/components/dash/dash_indicator.tscn
Normal file
77
scenes/player_controller/components/dash/dash_indicator.tscn
Normal file
@@ -0,0 +1,77 @@
|
||||
[gd_scene format=3 uid="uid://hd0868f4pb63"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://chvt6g0xn5c2m" path="res://scenes/player_controller/components/dash/light-ring.jpg" id="1_jadbb"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_tqt6i"]
|
||||
transparency = 1
|
||||
blend_mode = 1
|
||||
shading_mode = 0
|
||||
albedo_texture = ExtResource("1_jadbb")
|
||||
billboard_mode = 1
|
||||
|
||||
[sub_resource type="PlaneMesh" id="PlaneMesh_jngg2"]
|
||||
orientation = 2
|
||||
|
||||
[sub_resource type="Animation" id="Animation_fmn25"]
|
||||
length = 0.001
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath(".:mesh:size")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector2(2, 2)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_stbcc"]
|
||||
resource_name = "start"
|
||||
length = 0.2
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath(".:mesh:size")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.2),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector2(2, 2), Vector2(0, 0)]
|
||||
}
|
||||
tracks/1/type = "method"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath(".")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0.2),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"values": [{
|
||||
"args": [],
|
||||
"method": &"queue_free"
|
||||
}]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_3aile"]
|
||||
_data = {
|
||||
&"RESET": SubResource("Animation_fmn25"),
|
||||
&"start": SubResource("Animation_stbcc")
|
||||
}
|
||||
|
||||
[node name="DashIndicator" type="CPUParticles3D" unique_id=585575469]
|
||||
material_override = SubResource("StandardMaterial3D_tqt6i")
|
||||
emitting = false
|
||||
amount = 1
|
||||
lifetime = 0.5
|
||||
one_shot = true
|
||||
mesh = SubResource("PlaneMesh_jngg2")
|
||||
gravity = Vector3(0, 0, 0)
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="." unique_id=686842148]
|
||||
libraries/ = SubResource("AnimationLibrary_3aile")
|
||||
autoplay = &"start"
|
||||
57
scenes/player_controller/components/dash/dash_system.tscn
Normal file
57
scenes/player_controller/components/dash/dash_system.tscn
Normal file
@@ -0,0 +1,57 @@
|
||||
[gd_scene format=3 uid="uid://cqduhd4opgwvm"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dwoppk8j5fxeg" path="res://scenes/player_controller/components/dash/DashSystem.cs" id="1_hwig2"]
|
||||
[ext_resource type="PackedScene" uid="uid://wq1okogkhc5l" path="res://scenes/player_controller/components/mantle/mantle_system.tscn" id="2_pff7b"]
|
||||
[ext_resource type="PackedScene" uid="uid://hd0868f4pb63" path="res://scenes/player_controller/components/dash/dash_indicator.tscn" id="2_tqt6i"]
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_jngg2"]
|
||||
|
||||
[sub_resource type="SphereMesh" id="SphereMesh_qu4wy"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_v31n3"]
|
||||
|
||||
[sub_resource type="CylinderMesh" id="CylinderMesh_jngg2"]
|
||||
top_radius = 0.1
|
||||
bottom_radius = 0.1
|
||||
height = 1.0
|
||||
|
||||
[sub_resource type="TorusMesh" id="TorusMesh_tqt6i"]
|
||||
inner_radius = 0.1
|
||||
outer_radius = 0.5
|
||||
|
||||
[node name="DashSystem" type="Node3D" unique_id=2116632075]
|
||||
script = ExtResource("1_hwig2")
|
||||
DashIndicatorScene = ExtResource("2_tqt6i")
|
||||
|
||||
[node name="DashCast3D" type="ShapeCast3D" parent="." unique_id=1635795914]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.6, 0)
|
||||
shape = SubResource("SphereShape3D_jngg2")
|
||||
target_position = Vector3(0, 0, -12)
|
||||
max_results = 1
|
||||
collision_mask = 304
|
||||
debug_shape_custom_color = Color(0.911631, 0.11884, 0.656218, 1)
|
||||
|
||||
[node name="DashCastDrop" type="ShapeCast3D" parent="." unique_id=980436638]
|
||||
transform = Transform3D(1, 0, 0, 0, -4.371139e-08, 1, 0, -1, -4.371139e-08, 0, 1.6, 0)
|
||||
shape = SubResource("SphereShape3D_jngg2")
|
||||
target_position = Vector3(0, 0, -50)
|
||||
max_results = 1
|
||||
collision_mask = 304
|
||||
debug_shape_custom_color = Color(0.911631, 0.11884, 0.656218, 1)
|
||||
|
||||
[node name="DashTarget" type="MeshInstance3D" parent="." unique_id=711803810]
|
||||
mesh = SubResource("SphereMesh_qu4wy")
|
||||
surface_material_override/0 = SubResource("StandardMaterial3D_v31n3")
|
||||
|
||||
[node name="MantleSystem" parent="." unique_id=1511791010 instance=ExtResource("2_pff7b")]
|
||||
MantleEndLocationDistanceFromWall = 0.25
|
||||
MantleHeightCastStart = 2.0
|
||||
|
||||
[node name="DashIndicator" parent="." unique_id=98967688 instance=ExtResource("2_tqt6i")]
|
||||
visible = false
|
||||
|
||||
[node name="DashDropIndicator" type="MeshInstance3D" parent="." unique_id=173959533]
|
||||
mesh = SubResource("CylinderMesh_jngg2")
|
||||
|
||||
[node name="DashDropLocationIndicator" type="MeshInstance3D" parent="." unique_id=1260955364]
|
||||
mesh = SubResource("TorusMesh_tqt6i")
|
||||
@@ -0,0 +1,5 @@
|
||||
[gd_resource type="Curve" format=3 uid="uid://c2a8soliruf35"]
|
||||
|
||||
[resource]
|
||||
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.5, 1), -1.89032e-07, -1.89032e-07, 0, 0, Vector2(0.8, 0.05), -9.56219, 0.0, 0, 1, Vector2(0.995, 0.05), 0.0, 0.0, 0, 0, Vector2(1, 1), -0.0540619, -0.0540619, 0, 0]
|
||||
point_count = 5
|
||||
BIN
scenes/player_controller/components/dash/light-ring.jpg
(Stored with Git LFS)
Normal file
BIN
scenes/player_controller/components/dash/light-ring.jpg
(Stored with Git LFS)
Normal file
Binary file not shown.
@@ -0,0 +1,42 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://chvt6g0xn5c2m"
|
||||
path.s3tc="res://.godot/imported/light-ring.jpg-59a7aa6aff8e55915b68cd23f0e30ad8.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/light-ring.jpg-59a7aa6aff8e55915b68cd23f0e30ad8.etc2.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc", "etc2_astc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://scenes/player_controller/components/dash/light-ring.jpg"
|
||||
dest_files=["res://.godot/imported/light-ring.jpg-59a7aa6aff8e55915b68cd23f0e30ad8.s3tc.ctex", "res://.godot/imported/light-ring.jpg-59a7aa6aff8e55915b68cd23f0e30ad8.etc2.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
370
scenes/player_controller/components/head/HeadSystem.cs
Normal file
370
scenes/player_controller/components/head/HeadSystem.cs
Normal file
@@ -0,0 +1,370 @@
|
||||
using System;
|
||||
using Godot;
|
||||
using RustyOptions;
|
||||
|
||||
namespace Movementtests.systems;
|
||||
|
||||
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_face.png")]
|
||||
public partial class HeadSystem : Node3D
|
||||
{
|
||||
[Signal]
|
||||
public delegate void HitboxActivatedEventHandler();
|
||||
[Signal]
|
||||
public delegate void HitboxDeactivatedEventHandler();
|
||||
|
||||
[Signal]
|
||||
public delegate void ParryboxActivatedEventHandler();
|
||||
[Signal]
|
||||
public delegate void ParryboxDeactivatedEventHandler();
|
||||
|
||||
[Signal]
|
||||
public delegate void HitTargetEventHandler();
|
||||
[Signal]
|
||||
public delegate void GotHitEventHandler();
|
||||
[Signal]
|
||||
public delegate void DeathAnimationFinishedEventHandler();
|
||||
|
||||
[Signal]
|
||||
public delegate void StepFootEventHandler();
|
||||
|
||||
public record CameraParameters(
|
||||
double Delta,
|
||||
Vector2 LookDir,
|
||||
Vector3 PlayerInput,
|
||||
Vector3 PlayerVelocity,
|
||||
Vector3 WallContactPoint,
|
||||
float SensitivitMultiplier,
|
||||
bool WithCameraJitter,
|
||||
bool WithCameraBobbing,
|
||||
float BobbingMultiplier,
|
||||
float FovMultiplier);
|
||||
|
||||
private Camera3D _camera;
|
||||
private Marker3D _cameraAnchor;
|
||||
private AnimationPlayer _animationPlayer;
|
||||
private AnimationTree _animationTree;
|
||||
|
||||
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
|
||||
public float LookSensitivity { get; set; } = 1f;
|
||||
|
||||
[ExportGroup("Camera incline")]
|
||||
[Export(PropertyHint.Range, "0.1,50,0.1,or_greater")]
|
||||
public double CameraInclineAcceleration { get; set; } = 10f;
|
||||
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
|
||||
public float WallRunCameraIncline { get; set; } = 5f;
|
||||
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
|
||||
public float GroundedCameraIncline { get; set; } = 5f;
|
||||
|
||||
[ExportGroup("Sliding")]
|
||||
[Export(PropertyHint.Range, "0,2,0.1,or_greater")]
|
||||
public float SlidingCameraHeightOffset { get; set; } = 1.0f;
|
||||
[Export(PropertyHint.Range, "0,1,0.01,or_greater")]
|
||||
public float SlidingJitterFrequency { get; set; } = 0.01f;
|
||||
[Export(PropertyHint.Range, "0,1,0.01,or_greater")]
|
||||
public float SlidingJitterAmplitude { get; set; } = 0.1f;
|
||||
|
||||
private FastNoiseLite _slidingNoise = new FastNoiseLite();
|
||||
|
||||
[ExportGroup("Bobbing")]
|
||||
|
||||
private float _bobbingAccumulator; // Constantly increases when player moves in X or/and Z axis
|
||||
[Export(PropertyHint.Range, "0,10,0.01,or_greater")]
|
||||
public float BobbingFrequency { set; get; } = 2.4f;
|
||||
[Export(PropertyHint.Range, "0,0.4,0.01,or_greater")]
|
||||
public float BobbingAmplitude { set; get; } = 0.08f;
|
||||
|
||||
[ExportGroup("FOV")]
|
||||
[Export(PropertyHint.Range, "0,180,0.1,degrees")]
|
||||
public float BaseFov { get; set; } = 75.0f;
|
||||
[Export(PropertyHint.Range, "0,10,0.01,or_greater")]
|
||||
public float FovChangeFactor { get; set; } = 1.2f;
|
||||
[Export(PropertyHint.Range, "0,10,0.01,or_greater")]
|
||||
public float FovChangeSpeed { get; set; } = 6.25f;
|
||||
[Export(PropertyHint.Range, "0,100,1,or_greater")]
|
||||
public float FovMaxedOutSpeed { get; set; } = 20f;
|
||||
|
||||
[ExportGroup("First Person rig")]
|
||||
private Node3D _fpRig;
|
||||
private Node3D _rightHandedWeapon;
|
||||
private Node3D _leftHandedWeapon;
|
||||
private Node3D _fpDisplacedRig;
|
||||
private Vector3 _fpDisplacedRigInitialRotation;
|
||||
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
|
||||
public float WeaponSway { get; set; } = 5f;
|
||||
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
|
||||
public float WeaponLookRotation { get; set; } = 1f;
|
||||
[Export(PropertyHint.Range, "0,200,1,or_greater")]
|
||||
public float WeaponMoveRotation { get; set; } = 80f;
|
||||
[Export(PropertyHint.Range, "0,20,0.1,or_greater")]
|
||||
public float WeaponAdjustmentSpeed { get; set; } = 10f;
|
||||
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
|
||||
public float DisplacedWeaponSway { get; set; } = 5f;
|
||||
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
|
||||
public float DisplacedWeaponLookRotation { get; set; } = 1f;
|
||||
[Export(PropertyHint.Range, "0,1,0.01,or_greater")]
|
||||
public float DisplacedWeaponMoveRotation { get; set; } = 0.1f;
|
||||
[Export(PropertyHint.Range, "0,20,0.1,or_greater")]
|
||||
public float DisplacedWeaponAdjustmentSpeed { get; set; } = 10f;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
_isPlayingForcingAnim = false;
|
||||
|
||||
Input.SetMouseMode(Input.MouseModeEnum.Captured);
|
||||
_camera = GetNode<Camera3D>("CameraSmooth/Camera3D");
|
||||
_cameraAnchor = GetNode<Marker3D>("CameraAnchor");
|
||||
_animationPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
|
||||
_animationTree = GetNode<AnimationTree>("AnimationTree");
|
||||
|
||||
_fpRig = GetNode<Node3D>("FPRig");
|
||||
_rightHandedWeapon = GetNode<Node3D>("FPRig/Sword");
|
||||
_leftHandedWeapon = GetNode<Node3D>("FPRig/Parry");
|
||||
_fpDisplacedRig = GetNode<Node3D>("FPRig/Sword");
|
||||
_fpDisplacedRigInitialRotation = _fpDisplacedRig.Rotation;
|
||||
|
||||
_slidingNoise.NoiseType = FastNoiseLite.NoiseTypeEnum.Perlin;
|
||||
_slidingNoise.SetFrequency(SlidingJitterFrequency);
|
||||
}
|
||||
|
||||
public void OnMantle()
|
||||
{
|
||||
_animationTree.Set("parameters/OnMantle/request", (int) AnimationNodeOneShot.OneShotRequest.Fire);
|
||||
}
|
||||
public void OnJumpStarted()
|
||||
{
|
||||
_animationTree.Set("parameters/OnJumpStart/request", (int) AnimationNodeOneShot.OneShotRequest.Fire);
|
||||
}
|
||||
public void OnJumpEnded()
|
||||
{
|
||||
_animationTree.Set("parameters/OnJumpEnd/request", (int) AnimationNodeOneShot.OneShotRequest.Fire);
|
||||
}
|
||||
public void OnHit()
|
||||
{
|
||||
_animationTree.Set("parameters/OnHit/request", (int) AnimationNodeOneShot.OneShotRequest.Fire);
|
||||
}
|
||||
public void OnParry()
|
||||
{
|
||||
_animationTree.Set("parameters/OnParry/request", (int) AnimationNodeOneShot.OneShotRequest.Fire);
|
||||
}
|
||||
public void OnStartDeathAnimation()
|
||||
{
|
||||
_isPlayingForcingAnim = true;
|
||||
_animationTree.Set("parameters/OnDie/request", (int) AnimationNodeOneShot.OneShotRequest.Fire);
|
||||
}
|
||||
|
||||
public void OnDeathAnimationFinished()
|
||||
{
|
||||
EmitSignalDeathAnimationFinished();
|
||||
}
|
||||
|
||||
public void OnHitTarget()
|
||||
{
|
||||
EmitSignalHitTarget();
|
||||
}
|
||||
public void OnGetHit()
|
||||
{
|
||||
EmitSignalGotHit();
|
||||
}
|
||||
|
||||
public void OnHitboxActivated()
|
||||
{
|
||||
EmitSignalHitboxActivated();
|
||||
}
|
||||
public void OnHitboxDeactivated()
|
||||
{
|
||||
EmitSignalHitboxDeactivated();
|
||||
}
|
||||
|
||||
public void OnParryboxActivated()
|
||||
{
|
||||
EmitSignalHitboxActivated();
|
||||
}
|
||||
public void OnParryboxDeactivated()
|
||||
{
|
||||
EmitSignalHitboxDeactivated();
|
||||
}
|
||||
|
||||
private bool _footstepEmitted;
|
||||
private bool _isPlayingForcingAnim;
|
||||
|
||||
public void LookAround(CameraParameters inputs)
|
||||
{
|
||||
if (_isPlayingForcingAnim)
|
||||
{
|
||||
_camera.Position = Vector3.Zero;
|
||||
_camera.Rotation = Vector3.Zero;
|
||||
return;
|
||||
}
|
||||
|
||||
var (delta,
|
||||
lookDir,
|
||||
playerInput,
|
||||
playerVelocity,
|
||||
wallContactPoint,
|
||||
sensitivitMultiplier,
|
||||
withCameraJitter,
|
||||
withCameraBobbing,
|
||||
bobbingMultiplier,
|
||||
fovMultiplier) = inputs;
|
||||
|
||||
// Horizontal movement of head
|
||||
float angleForHorizontalRotation = lookDir.X * LookSensitivity * sensitivitMultiplier;
|
||||
RotateY(angleForHorizontalRotation);
|
||||
|
||||
// Vertical movement of head
|
||||
Vector3 currentCameraRotation = _cameraAnchor.Rotation;
|
||||
currentCameraRotation.X += Convert.ToSingle(lookDir.Y * LookSensitivity * sensitivitMultiplier);
|
||||
currentCameraRotation.X = Mathf.Clamp(currentCameraRotation.X, Mathf.DegToRad(-90f), Mathf.DegToRad(90f));
|
||||
|
||||
// Camera incline on Wall and more
|
||||
var isWallRunning = wallContactPoint.Length() > Mathf.Epsilon;
|
||||
float cameraIncline;
|
||||
if (isWallRunning)
|
||||
{
|
||||
var directionToWall = (wallContactPoint - GlobalPosition).Normalized();
|
||||
var cameraInclineFactor = ComputeCameraInclineFactor(directionToWall);
|
||||
cameraIncline = Mathf.DegToRad(WallRunCameraIncline * cameraInclineFactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
var cameraInclineFactor = ComputeCameraInclineFactor(playerInput);
|
||||
cameraIncline = Mathf.DegToRad(GroundedCameraIncline * cameraInclineFactor * -1.0f);
|
||||
}
|
||||
currentCameraRotation.Z = (float) Mathf.Lerp(currentCameraRotation.Z, cameraIncline, delta * CameraInclineAcceleration);
|
||||
_cameraAnchor.Rotation = currentCameraRotation;
|
||||
|
||||
if (withCameraJitter)
|
||||
{
|
||||
_cameraAnchor.Position = Vector3.Down*SlidingCameraHeightOffset;
|
||||
float noise1D = _slidingNoise.GetNoise1D(Time.GetTicksMsec());
|
||||
float noiseAmplitude = SlidingJitterAmplitude*Mathf.Clamp(playerVelocity.Length(), 0f, 1f);
|
||||
_cameraAnchor.Position += Vector3.Up*noise1D*noiseAmplitude;
|
||||
}
|
||||
else
|
||||
{
|
||||
_cameraAnchor.Position = Vector3.Zero;
|
||||
}
|
||||
|
||||
Vector3 newPositionForCamera = Vector3.Zero;
|
||||
Vector3 newPositionForRig = Vector3.Zero;
|
||||
if (withCameraBobbing)
|
||||
{
|
||||
_bobbingAccumulator += (float) delta * playerVelocity.Length();
|
||||
|
||||
// As the _bobbingAccumulator increases we're changing values for sin and cos functions.
|
||||
// Because both of them are just waves, we will be slide up with y and then slide down with y
|
||||
// creating bobbing effect. The same works for cos. As the _bobbingAccumulator increases the cos decreases and then increases
|
||||
newPositionForCamera.Y = Mathf.Sin(_bobbingAccumulator * BobbingFrequency) * BobbingAmplitude * bobbingMultiplier;
|
||||
newPositionForCamera.X = Mathf.Cos(_bobbingAccumulator * BobbingFrequency / 2.0f) * BobbingAmplitude * bobbingMultiplier;
|
||||
|
||||
if (newPositionForCamera.Y < -0.07 && !_footstepEmitted) Footstep();
|
||||
if (newPositionForCamera.Y > 0) _footstepEmitted = false;
|
||||
|
||||
// Offset bobbing for weapon rig
|
||||
newPositionForRig.Y = Mathf.Cos(_bobbingAccumulator * BobbingFrequency) * BobbingAmplitude * bobbingMultiplier * 0.2f;
|
||||
newPositionForRig.X = Mathf.Sin(_bobbingAccumulator * BobbingFrequency / 2.0f) * BobbingAmplitude * bobbingMultiplier * 0.2f;
|
||||
}
|
||||
_cameraAnchor.Position += newPositionForCamera;
|
||||
|
||||
_camera.GlobalTransform = _cameraAnchor.GetGlobalTransformInterpolated();
|
||||
|
||||
// First person rig adjustments
|
||||
_fpRig.GlobalTransform = _cameraAnchor.GetGlobalTransformInterpolated();
|
||||
// Apply bobbing
|
||||
_fpRig.Position += newPositionForRig;
|
||||
|
||||
// Rotate the whole rig based on movement input
|
||||
var newRigRotation = _fpRig.Rotation;
|
||||
var camTilt = Mathf.Lerp(_fpRig.Rotation.Z, cameraIncline*WeaponMoveRotation, delta*WeaponAdjustmentSpeed);
|
||||
newRigRotation.Z = (float) camTilt;
|
||||
|
||||
// Rotate the whole rig based on camera rotation input
|
||||
newRigRotation.X = Mathf.Lerp(newRigRotation.X, -lookDir.Y*WeaponSway, (float) delta*WeaponAdjustmentSpeed);
|
||||
newRigRotation.Y = Mathf.Lerp(newRigRotation.Y, -lookDir.X*WeaponSway, (float) delta*WeaponAdjustmentSpeed);
|
||||
|
||||
// Apply
|
||||
_fpRig.Rotation = newRigRotation;
|
||||
|
||||
// Compute displaced rig adjustments, starting with movement input
|
||||
var newDisplacedRigRotation = _fpDisplacedRig.Rotation;
|
||||
|
||||
var howMuchForward = ComputeHowMuchInputForward(playerInput);
|
||||
var howMuchSideways = ComputeHowMuchInputSideways(playerInput);
|
||||
var displacedCamTiltForward = Mathf.Lerp(newDisplacedRigRotation.Z,
|
||||
_fpDisplacedRigInitialRotation.Z + howMuchForward*DisplacedWeaponMoveRotation,
|
||||
delta*DisplacedWeaponAdjustmentSpeed);
|
||||
var displacedCamTiltSide = Mathf.Lerp(newDisplacedRigRotation.X,
|
||||
_fpDisplacedRigInitialRotation.X - howMuchSideways*DisplacedWeaponMoveRotation,
|
||||
delta*DisplacedWeaponAdjustmentSpeed);
|
||||
|
||||
newDisplacedRigRotation.X = (float) displacedCamTiltSide;
|
||||
newDisplacedRigRotation.Z = (float) displacedCamTiltForward;
|
||||
|
||||
var displacedSwayY = Mathf.Lerp(newDisplacedRigRotation.Y,
|
||||
_fpDisplacedRigInitialRotation.Y - lookDir.X*DisplacedWeaponSway,
|
||||
delta*DisplacedWeaponAdjustmentSpeed);
|
||||
newDisplacedRigRotation.Y = (float) displacedSwayY;
|
||||
|
||||
// Apply
|
||||
_fpDisplacedRig.Rotation = newDisplacedRigRotation;
|
||||
|
||||
// Camera adjustments
|
||||
float velocityClamped = Mathf.Clamp(playerVelocity.Length(), 0.5f, FovMaxedOutSpeed);
|
||||
float targetFov = BaseFov + FovChangeFactor * velocityClamped * fovMultiplier;
|
||||
_camera.Fov = Mathf.Lerp(_camera.Fov, targetFov, (float) delta * FovChangeSpeed);
|
||||
}
|
||||
|
||||
public void Footstep()
|
||||
{
|
||||
_footstepEmitted = true;
|
||||
EmitSignalStepFoot();
|
||||
}
|
||||
|
||||
public void HideWeapon()
|
||||
{
|
||||
_rightHandedWeapon.Visible = false;
|
||||
}
|
||||
public void ShowWeapon()
|
||||
{
|
||||
_rightHandedWeapon.Visible = true;
|
||||
}
|
||||
|
||||
public float ComputeCameraInclineFactor(Vector3 direction)
|
||||
{
|
||||
var forward = GetForwardHorizontalVector().Normalized();
|
||||
var crossProduct = forward.Cross(direction);
|
||||
return crossProduct.Length()*Mathf.Sign(crossProduct.Y);
|
||||
}
|
||||
|
||||
public float ComputeHowMuchInputForward(Vector3 playerInput)
|
||||
{
|
||||
var forwardAngle = GetForwardHorizontalVector().AngleTo(playerInput);
|
||||
var forwardRemapped = Mathf.Remap(forwardAngle, 0, Mathf.Pi, -1, 1);
|
||||
return playerInput.Length() > 0 ? forwardRemapped : 0;
|
||||
}
|
||||
|
||||
public float ComputeHowMuchInputSideways(Vector3 playerInput)
|
||||
{
|
||||
var rightAngle = GetForwardHorizontalVector().Cross(Vector3.Up).Normalized().AngleTo(playerInput);
|
||||
var forwardRemapped = Mathf.Remap(rightAngle, 0, Mathf.Pi, -1, 1);
|
||||
return playerInput.Length() > 0 ? forwardRemapped : 0;
|
||||
}
|
||||
|
||||
public Vector3 GetForwardHorizontalVector()
|
||||
{
|
||||
return GetGlobalTransform().Basis.Z;
|
||||
}
|
||||
|
||||
public Vector3 GetGlobalLookRotation()
|
||||
{
|
||||
return new Vector3(
|
||||
_camera.Rotation.X,
|
||||
Rotation.Y,
|
||||
_camera.Rotation.Z);
|
||||
}
|
||||
|
||||
public void SetHeight(float height)
|
||||
{
|
||||
Position = new Vector3(Position.X, height, Position.Z);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://dtkdrnsmlwm67
|
||||
76
scenes/player_controller/components/head/fp_blend_tree.tres
Normal file
76
scenes/player_controller/components/head/fp_blend_tree.tres
Normal file
@@ -0,0 +1,76 @@
|
||||
[gd_resource type="AnimationNodeBlendTree" format=3 uid="uid://c26yvcyyyj811"]
|
||||
|
||||
[ext_resource type="AnimationNodeStateMachine" uid="uid://3r5oeg0ho0d4" path="res://scenes/player_controller/components/head/fp_state_machine.tres" id="1_knaxl"]
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_1hkum"]
|
||||
animation = &"die"
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_knaxl"]
|
||||
animation = &"idle"
|
||||
|
||||
[sub_resource type="AnimationNodeOneShot" id="AnimationNodeOneShot_ao3u1"]
|
||||
filters = ["../..", "../../FPRig/Sword:position", "../../FPRig/Sword:rotation", "..:position", "..:rotation", ".:position", ".:rotation"]
|
||||
|
||||
[sub_resource type="AnimationNodeOneShot" id="AnimationNodeOneShot_1hkum"]
|
||||
|
||||
[sub_resource type="AnimationNodeOneShot" id="AnimationNodeOneShot_knaxl"]
|
||||
filter_enabled = true
|
||||
filters = ["..:position", "..:rotation"]
|
||||
|
||||
[sub_resource type="AnimationNodeOneShot" id="AnimationNodeOneShot_23rmc"]
|
||||
filter_enabled = true
|
||||
filters = ["..:position", "..:rotation"]
|
||||
|
||||
[sub_resource type="AnimationNodeOneShot" id="AnimationNodeOneShot_dlkjl"]
|
||||
filter_enabled = true
|
||||
filters = ["..:position", "..:rotation", "..:rotation:x", "..:rotation:z"]
|
||||
|
||||
[sub_resource type="AnimationNodeOneShot" id="AnimationNodeOneShot_lwjon"]
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_calte"]
|
||||
animation = &"parry"
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_23rmc"]
|
||||
animation = &"hit1"
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_dlkjl"]
|
||||
animation = &"jump_end"
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_ao3u1"]
|
||||
animation = &"jump_start"
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_lwjon"]
|
||||
animation = &"mantle"
|
||||
|
||||
[resource]
|
||||
graph_offset = Vector2(-363.5551, -25.864124)
|
||||
nodes/output/position = Vector2(2020, -40)
|
||||
nodes/AnimationNodeStateMachine/node = ExtResource("1_knaxl")
|
||||
nodes/AnimationNodeStateMachine/position = Vector2(-560, 180)
|
||||
nodes/Idle/node = SubResource("AnimationNodeAnimation_knaxl")
|
||||
nodes/Idle/position = Vector2(-100, -20)
|
||||
nodes/OnHit/node = SubResource("AnimationNodeOneShot_1hkum")
|
||||
nodes/OnHit/position = Vector2(1240, -60)
|
||||
nodes/hit1/node = SubResource("AnimationNodeAnimation_23rmc")
|
||||
nodes/hit1/position = Vector2(1080, 320)
|
||||
nodes/OnJumpStart/node = SubResource("AnimationNodeOneShot_23rmc")
|
||||
nodes/OnJumpStart/position = Vector2(140, 0)
|
||||
nodes/OnJumpEnd/node = SubResource("AnimationNodeOneShot_knaxl")
|
||||
nodes/OnJumpEnd/position = Vector2(560, -20)
|
||||
nodes/jump_start/node = SubResource("AnimationNodeAnimation_ao3u1")
|
||||
nodes/jump_start/position = Vector2(-120, 320)
|
||||
nodes/jump_end/node = SubResource("AnimationNodeAnimation_dlkjl")
|
||||
nodes/jump_end/position = Vector2(300, 340)
|
||||
nodes/OnMantle/node = SubResource("AnimationNodeOneShot_dlkjl")
|
||||
nodes/OnMantle/position = Vector2(900, -60)
|
||||
nodes/mantle/node = SubResource("AnimationNodeAnimation_lwjon")
|
||||
nodes/mantle/position = Vector2(640, 320)
|
||||
nodes/OnDie/node = SubResource("AnimationNodeOneShot_ao3u1")
|
||||
nodes/OnDie/position = Vector2(1500, -60)
|
||||
nodes/Die/node = SubResource("AnimationNodeAnimation_1hkum")
|
||||
nodes/Die/position = Vector2(1280, 340)
|
||||
nodes/OnParry/node = SubResource("AnimationNodeOneShot_lwjon")
|
||||
nodes/OnParry/position = Vector2(1780, -40)
|
||||
nodes/Parry/node = SubResource("AnimationNodeAnimation_calte")
|
||||
nodes/Parry/position = Vector2(1600, 300)
|
||||
node_connections = [&"output", 0, &"OnParry", &"OnHit", 0, &"OnMantle", &"OnHit", 1, &"hit1", &"OnJumpStart", 0, &"Idle", &"OnJumpStart", 1, &"jump_start", &"OnJumpEnd", 0, &"OnJumpStart", &"OnJumpEnd", 1, &"jump_end", &"OnMantle", 0, &"OnJumpEnd", &"OnMantle", 1, &"mantle", &"OnDie", 0, &"OnHit", &"OnDie", 1, &"Die", &"OnParry", 0, &"OnDie", &"OnParry", 1, &"Parry"]
|
||||
@@ -0,0 +1,14 @@
|
||||
[gd_resource type="AnimationNodeStateMachine" format=3 uid="uid://3r5oeg0ho0d4"]
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_73q32"]
|
||||
animation = &"idle"
|
||||
|
||||
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_adm0b"]
|
||||
advance_mode = 2
|
||||
|
||||
[resource]
|
||||
states/Start/position = Vector2(100, 91)
|
||||
states/idle/node = SubResource("AnimationNodeAnimation_73q32")
|
||||
states/idle/position = Vector2(331, 91)
|
||||
transitions = ["Start", "idle", SubResource("AnimationNodeStateMachineTransition_adm0b")]
|
||||
graph_offset = Vector2(-82, -9)
|
||||
735
scenes/player_controller/components/head/head_system.tscn
Normal file
735
scenes/player_controller/components/head/head_system.tscn
Normal file
@@ -0,0 +1,735 @@
|
||||
[gd_scene format=3 uid="uid://0ysqmqphq6mq"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dtkdrnsmlwm67" path="res://scenes/player_controller/components/head/HeadSystem.cs" id="1_8abgy"]
|
||||
[ext_resource type="ArrayMesh" uid="uid://ckr26s4e3fj1m" path="res://assets/meshes/swords/resources/fp_sword23.tres" id="2_c5qep"]
|
||||
[ext_resource type="ArrayMesh" uid="uid://dogiv0piqfmfu" path="res://assets/meshes/swords/resources/fp_sword20.tres" id="3_1ay6d"]
|
||||
[ext_resource type="AnimationNodeBlendTree" uid="uid://c26yvcyyyj811" path="res://scenes/player_controller/components/head/fp_blend_tree.tres" id="3_r0h40"]
|
||||
[ext_resource type="Script" uid="uid://dnlxsrumw6ygp" path="res://addons/shaker/src/Vector3/shaker_component3D.gd" id="3_ubhf8"]
|
||||
[ext_resource type="Script" uid="uid://0tu2q57qqu4s" path="res://addons/shaker/data/Vector3/BaseShakerType3D.gd" id="4_1ay6d"]
|
||||
[ext_resource type="Script" uid="uid://ptaespkh1sk2" path="res://addons/shaker/data/Vector3/ShakerTypeNoiseShake3D.gd" id="5_sdjj3"]
|
||||
[ext_resource type="Script" uid="uid://mlwdmecg12xd" path="res://addons/shaker/data/Vector3/ShakerPreset3D.gd" id="6_ll12k"]
|
||||
|
||||
[sub_resource type="FastNoiseLite" id="FastNoiseLite_ubhf8"]
|
||||
frequency = 0.15
|
||||
fractal_octaves = 1
|
||||
|
||||
[sub_resource type="NoiseTexture3D" id="NoiseTexture3D_1ay6d"]
|
||||
noise = SubResource("FastNoiseLite_ubhf8")
|
||||
|
||||
[sub_resource type="Resource" id="Resource_sdjj3"]
|
||||
script = ExtResource("5_sdjj3")
|
||||
noise_texture = SubResource("NoiseTexture3D_1ay6d")
|
||||
amplitude = Vector3(0.1, 0.1, 0.1)
|
||||
metadata/_custom_type_script = "uid://ptaespkh1sk2"
|
||||
|
||||
[sub_resource type="FastNoiseLite" id="FastNoiseLite_sdjj3"]
|
||||
frequency = 0.1
|
||||
|
||||
[sub_resource type="NoiseTexture3D" id="NoiseTexture3D_ll12k"]
|
||||
noise = SubResource("FastNoiseLite_sdjj3")
|
||||
|
||||
[sub_resource type="Resource" id="Resource_dvot2"]
|
||||
script = ExtResource("5_sdjj3")
|
||||
noise_texture = SubResource("NoiseTexture3D_ll12k")
|
||||
amplitude = Vector3(0.02, 0.02, 0.02)
|
||||
metadata/_custom_type_script = "uid://ptaespkh1sk2"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_60ouj"]
|
||||
script = ExtResource("6_ll12k")
|
||||
PositionShake = Array[ExtResource("4_1ay6d")]([SubResource("Resource_sdjj3")])
|
||||
RotationShake = Array[ExtResource("4_1ay6d")]([SubResource("Resource_dvot2")])
|
||||
metadata/_custom_type_script = "uid://mlwdmecg12xd"
|
||||
|
||||
[sub_resource type="FastNoiseLite" id="FastNoiseLite_1ay6d"]
|
||||
frequency = 0.02
|
||||
fractal_octaves = 1
|
||||
|
||||
[sub_resource type="NoiseTexture3D" id="NoiseTexture3D_sdjj3"]
|
||||
noise = SubResource("FastNoiseLite_1ay6d")
|
||||
|
||||
[sub_resource type="Resource" id="Resource_ll12k"]
|
||||
script = ExtResource("5_sdjj3")
|
||||
noise_texture = SubResource("NoiseTexture3D_sdjj3")
|
||||
amplitude = Vector3(0.2, 0, 0)
|
||||
metadata/_custom_type_script = "uid://ptaespkh1sk2"
|
||||
|
||||
[sub_resource type="FastNoiseLite" id="FastNoiseLite_ll12k"]
|
||||
frequency = 0.02
|
||||
fractal_octaves = 1
|
||||
|
||||
[sub_resource type="NoiseTexture3D" id="NoiseTexture3D_se3kf"]
|
||||
noise = SubResource("FastNoiseLite_ll12k")
|
||||
|
||||
[sub_resource type="Resource" id="Resource_0k6hv"]
|
||||
script = ExtResource("5_sdjj3")
|
||||
noise_texture = SubResource("NoiseTexture3D_se3kf")
|
||||
amplitude = Vector3(0.1, 0.2, 0.1)
|
||||
metadata/_custom_type_script = "uid://ptaespkh1sk2"
|
||||
|
||||
[sub_resource type="Resource" id="Resource_se3kf"]
|
||||
script = ExtResource("6_ll12k")
|
||||
PositionShake = Array[ExtResource("4_1ay6d")]([SubResource("Resource_ll12k")])
|
||||
RotationShake = Array[ExtResource("4_1ay6d")]([SubResource("Resource_0k6hv")])
|
||||
metadata/_custom_type_script = "uid://mlwdmecg12xd"
|
||||
|
||||
[sub_resource type="Animation" id="Animation_urko7"]
|
||||
length = 0.001
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("../../FPRig/Sword:position")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0.53640664, -0.7880347, -1.9288678)]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("../../FPRig/Sword:rotation")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector3(-0.083978735, -1.136043, 0.19867715)]
|
||||
}
|
||||
tracks/2/type = "value"
|
||||
tracks/2/imported = false
|
||||
tracks/2/enabled = true
|
||||
tracks/2/path = NodePath("../../FPRig/Sword:scale")
|
||||
tracks/2/interp = 1
|
||||
tracks/2/loop_wrap = true
|
||||
tracks/2/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector3(1.0000001, 1.0000001, 1.0000005)]
|
||||
}
|
||||
tracks/3/type = "value"
|
||||
tracks/3/imported = false
|
||||
tracks/3/enabled = true
|
||||
tracks/3/path = NodePath("..:rotation")
|
||||
tracks/3/interp = 1
|
||||
tracks/3/loop_wrap = true
|
||||
tracks/3/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0, 0, 0.00011616433)]
|
||||
}
|
||||
tracks/4/type = "value"
|
||||
tracks/4/imported = false
|
||||
tracks/4/enabled = true
|
||||
tracks/4/path = NodePath("..:position")
|
||||
tracks/4/interp = 1
|
||||
tracks/4/loop_wrap = true
|
||||
tracks/4/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0, 0, 0)]
|
||||
}
|
||||
tracks/5/type = "value"
|
||||
tracks/5/imported = false
|
||||
tracks/5/enabled = true
|
||||
tracks/5/path = NodePath("../../FPRig/Parry:position")
|
||||
tracks/5/interp = 1
|
||||
tracks/5/loop_wrap = true
|
||||
tracks/5/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector3(-0.22145952, -0.19867475, -1.3653086)]
|
||||
}
|
||||
tracks/6/type = "value"
|
||||
tracks/6/imported = false
|
||||
tracks/6/enabled = true
|
||||
tracks/6/path = NodePath("../../FPRig/Parry:rotation")
|
||||
tracks/6/interp = 1
|
||||
tracks/6/loop_wrap = true
|
||||
tracks/6/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0.9350104, 3.0957325, -1.9789876)]
|
||||
}
|
||||
tracks/7/type = "value"
|
||||
tracks/7/imported = false
|
||||
tracks/7/enabled = true
|
||||
tracks/7/path = NodePath("../../FPRig/Parry:visible")
|
||||
tracks/7/interp = 1
|
||||
tracks/7/loop_wrap = true
|
||||
tracks/7/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 1,
|
||||
"values": [true]
|
||||
}
|
||||
tracks/8/type = "bezier"
|
||||
tracks/8/imported = false
|
||||
tracks/8/enabled = true
|
||||
tracks/8/path = NodePath("../../FPRig/Parry:rotation:x")
|
||||
tracks/8/interp = 1
|
||||
tracks/8/loop_wrap = true
|
||||
tracks/8/keys = {
|
||||
"handle_modes": PackedInt32Array(0),
|
||||
"points": PackedFloat32Array(0.9350104, -0.15, 0, 0.15, 0),
|
||||
"times": PackedFloat32Array(0)
|
||||
}
|
||||
tracks/9/type = "bezier"
|
||||
tracks/9/imported = false
|
||||
tracks/9/enabled = true
|
||||
tracks/9/path = NodePath("../../FPRig/Parry:rotation:y")
|
||||
tracks/9/interp = 1
|
||||
tracks/9/loop_wrap = true
|
||||
tracks/9/keys = {
|
||||
"handle_modes": PackedInt32Array(0),
|
||||
"points": PackedFloat32Array(3.0957325, -0.15, 0, 0.15, 0),
|
||||
"times": PackedFloat32Array(0)
|
||||
}
|
||||
tracks/10/type = "bezier"
|
||||
tracks/10/imported = false
|
||||
tracks/10/enabled = true
|
||||
tracks/10/path = NodePath("../../FPRig/Parry:rotation:z")
|
||||
tracks/10/interp = 1
|
||||
tracks/10/loop_wrap = true
|
||||
tracks/10/keys = {
|
||||
"handle_modes": PackedInt32Array(0),
|
||||
"points": PackedFloat32Array(-1.9789876, -0.15, 0, 0.15, 0),
|
||||
"times": PackedFloat32Array(0)
|
||||
}
|
||||
tracks/11/type = "value"
|
||||
tracks/11/imported = false
|
||||
tracks/11/enabled = true
|
||||
tracks/11/path = NodePath("../../FPRig/Parry:scale")
|
||||
tracks/11/interp = 1
|
||||
tracks/11/loop_wrap = true
|
||||
tracks/11/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector3(1.2, 1.2, 1.2)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_sdjj3"]
|
||||
resource_name = "die"
|
||||
length = 1.0000033
|
||||
tracks/0/type = "method"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("../..")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(1),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"values": [{
|
||||
"args": [],
|
||||
"method": &"OnDeathAnimationFinished"
|
||||
}]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("../../FPRig/Sword:position")
|
||||
tracks/1/interp = 2
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0, 0.20000002, 0.4, 0.53333336, 0.8000001),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0.53640664, -0.7880347, -1.9288678), Vector3(0.1057997, -0.21274538, -0.63147813), Vector3(0.53640664, 1.0949166, -1.9288678), Vector3(0.13969281, 3.1670854, 0.20333667), Vector3(0.14, -1.255, 0)]
|
||||
}
|
||||
tracks/2/type = "value"
|
||||
tracks/2/imported = false
|
||||
tracks/2/enabled = true
|
||||
tracks/2/path = NodePath("../../FPRig/Sword:rotation")
|
||||
tracks/2/interp = 2
|
||||
tracks/2/loop_wrap = true
|
||||
tracks/2/keys = {
|
||||
"times": PackedFloat32Array(0, 0.20000002, 0.4, 0.53333336, 0.8000001),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(-0.083978735, -1.136043, 0.19867715), Vector3(-1.113491, -0.31576312, -0.983999), Vector3(-0.7104627, -0.98405164, -0.17152688), Vector3(0.111641094, -0.3489763, -2.955844), Vector3(0.11164107, -0.34897622, -2.955844)]
|
||||
}
|
||||
tracks/3/type = "value"
|
||||
tracks/3/imported = false
|
||||
tracks/3/enabled = true
|
||||
tracks/3/path = NodePath("..:position")
|
||||
tracks/3/interp = 2
|
||||
tracks/3/loop_wrap = true
|
||||
tracks/3/keys = {
|
||||
"times": PackedFloat32Array(0, 0.20000002, 0.6333333),
|
||||
"transitions": PackedFloat32Array(1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0, 0, 0), Vector3(0, -0.35507536, 0.32742357), Vector3(0.219, -1.5, 1.166)]
|
||||
}
|
||||
tracks/4/type = "value"
|
||||
tracks/4/imported = false
|
||||
tracks/4/enabled = true
|
||||
tracks/4/path = NodePath("..:rotation")
|
||||
tracks/4/interp = 2
|
||||
tracks/4/loop_wrap = true
|
||||
tracks/4/keys = {
|
||||
"times": PackedFloat32Array(0, 0.20000002, 0.6333333),
|
||||
"transitions": PackedFloat32Array(1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0, 0, 0.00011616433), Vector3(0, 0, -0.092299014), Vector3(0, 0, 1.2653637)]
|
||||
}
|
||||
tracks/5/type = "value"
|
||||
tracks/5/imported = false
|
||||
tracks/5/enabled = true
|
||||
tracks/5/path = NodePath("../../FPRig/Parry:position")
|
||||
tracks/5/interp = 2
|
||||
tracks/5/loop_wrap = true
|
||||
tracks/5/keys = {
|
||||
"times": PackedFloat32Array(0, 0.2),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(-0.22145952, -0.19867475, -1.3653086), Vector3(-1.3323143, -0.19867463, -1.7020192)]
|
||||
}
|
||||
tracks/6/type = "value"
|
||||
tracks/6/imported = false
|
||||
tracks/6/enabled = true
|
||||
tracks/6/path = NodePath("../../FPRig/Parry:rotation")
|
||||
tracks/6/interp = 2
|
||||
tracks/6/loop_wrap = true
|
||||
tracks/6/keys = {
|
||||
"times": PackedFloat32Array(0, 0.2),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0.9350104, 3.0957325, -1.9789876), Vector3(0.5242357, 2.32568, -3.0527115)]
|
||||
}
|
||||
tracks/7/type = "value"
|
||||
tracks/7/imported = false
|
||||
tracks/7/enabled = true
|
||||
tracks/7/path = NodePath("../../FPRig/Parry:visible")
|
||||
tracks/7/interp = 1
|
||||
tracks/7/loop_wrap = true
|
||||
tracks/7/keys = {
|
||||
"times": PackedFloat32Array(0, 0.2),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"update": 1,
|
||||
"values": [true, false]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_r0h40"]
|
||||
resource_name = "hit1"
|
||||
length = 0.30000168
|
||||
step = 0.016666668
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("../../FPRig/Sword:position")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.06666667, 0.11666667, 0.15, 0.21666667, 0.3),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0.53640664, -0.7880347, -1.9288678), Vector3(0.4045868, -0.4412415, -1.5352597), Vector3(-0.4799922, -0.5403832, -1.6861614), Vector3(-0.46995986, -0.53766656, -1.3638693), Vector3(-0.49520528, -0.5369735, -1.3145388), Vector3(-0.4048354, -0.5878634, -1.2836416)]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("../../FPRig/Sword:rotation")
|
||||
tracks/1/interp = 1
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0, 0.06666667, 0.11666667, 0.15, 0.21666667, 0.3),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(-0.083978735, -1.136043, 0.19867715), Vector3(-0.7788485, -2.0049822, -0.2951485), Vector3(-0.94931036, -0.5881021, -0.61733377), Vector3(-1.3252386, -0.102411434, 0.58406436), Vector3(-1.2938086, -0.18945412, 0.7334958), Vector3(-1.1484056, -0.2900904, 0.6867544)]
|
||||
}
|
||||
tracks/2/type = "value"
|
||||
tracks/2/imported = false
|
||||
tracks/2/enabled = true
|
||||
tracks/2/path = NodePath("../../FPRig/Sword:scale")
|
||||
tracks/2/interp = 2
|
||||
tracks/2/loop_wrap = true
|
||||
tracks/2/keys = {
|
||||
"times": PackedFloat32Array(0, 0.06666667, 0.11666667, 0.15, 0.21666667, 0.3),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(1.0000001, 1.0000001, 1.0000005), Vector3(1, 1.0004268, 1.0000002), Vector3(0.99999994, 1.2493719, 0.99999976), Vector3(1.0000001, 1.1750004, 1.0000004), Vector3(0.99999994, 0.99999994, 0.99999994), Vector3(1.0000001, 0.9999999, 1)]
|
||||
}
|
||||
tracks/3/type = "value"
|
||||
tracks/3/imported = false
|
||||
tracks/3/enabled = true
|
||||
tracks/3/path = NodePath("..:rotation")
|
||||
tracks/3/interp = 2
|
||||
tracks/3/loop_wrap = true
|
||||
tracks/3/keys = {
|
||||
"times": PackedFloat32Array(0, 0.083333336, 0.11666667, 0.2, 0.23333333, 0.3),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0, 0, 0), Vector3(0, 0, 0), Vector3(0, 0, 0.00011616433), Vector3(0, -0.02617994, -0.02617994), Vector3(0, 0.02617994, 0.02617994), Vector3(0, 0, 0)]
|
||||
}
|
||||
tracks/4/type = "method"
|
||||
tracks/4/imported = false
|
||||
tracks/4/enabled = true
|
||||
tracks/4/path = NodePath("../..")
|
||||
tracks/4/interp = 1
|
||||
tracks/4/loop_wrap = true
|
||||
tracks/4/keys = {
|
||||
"times": PackedFloat32Array(0.083333336, 0.23333333),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"values": [{
|
||||
"args": [],
|
||||
"method": &"OnHitboxActivated"
|
||||
}, {
|
||||
"args": [],
|
||||
"method": &"OnHitboxDeactivated"
|
||||
}]
|
||||
}
|
||||
tracks/5/type = "value"
|
||||
tracks/5/imported = false
|
||||
tracks/5/enabled = true
|
||||
tracks/5/path = NodePath("../../FPRig/Parry:position")
|
||||
tracks/5/interp = 2
|
||||
tracks/5/loop_wrap = true
|
||||
tracks/5/keys = {
|
||||
"times": PackedFloat32Array(0, 0.033333335, 0.083333336, 0.16666667, 0.3),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(-0.22145952, -0.19867475, -1.3653086), Vector3(-0.0715476, -0.16325326, -0.8197592), Vector3(-0.36483923, -0.26392323, -1.3945884), Vector3(-0.8528395, -0.26392323, -1.2049117), Vector3(-0.8528395, -0.26392323, -1.2049117)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_0hyrq"]
|
||||
resource_name = "idle"
|
||||
length = 2.0
|
||||
loop_mode = 1
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("../../FPRig/Sword:position")
|
||||
tracks/0/interp = 2
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.3, 0.6, 1, 1.4),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0.53640664, -0.7880347, -1.9288678), Vector3(0.53640664, -0.83580256, -1.9288678), Vector3(0.53640664, -0.86088884, -1.9288678), Vector3(0.53640664, -0.8256072, -1.9288678), Vector3(0.53640664, -0.7880347, -1.9288678)]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("../../FPRig/Sword:rotation")
|
||||
tracks/1/interp = 2
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0, 0.3, 0.6, 1, 1.4),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(-0.083978735, -1.136043, 0.19867715), Vector3(-0.06987281, -1.1365474, 0.20524277), Vector3(-0.05990464, -1.1368362, 0.20987195), Vector3(-0.06303402, -1.1367121, 0.2084137), Vector3(-0.083978735, -1.136043, 0.19867715)]
|
||||
}
|
||||
tracks/2/type = "value"
|
||||
tracks/2/imported = false
|
||||
tracks/2/enabled = true
|
||||
tracks/2/path = NodePath("../../FPRig/Parry:position")
|
||||
tracks/2/interp = 2
|
||||
tracks/2/loop_wrap = true
|
||||
tracks/2/keys = {
|
||||
"times": PackedFloat32Array(0, 0.3, 0.8000001),
|
||||
"transitions": PackedFloat32Array(1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(-0.22145952, -0.19867475, -1.3653086), Vector3(-0.221, -0.211, -1.365), Vector3(-0.221, -0.16, -1.365)]
|
||||
}
|
||||
tracks/3/type = "value"
|
||||
tracks/3/imported = false
|
||||
tracks/3/enabled = true
|
||||
tracks/3/path = NodePath("../../FPRig/Parry:rotation")
|
||||
tracks/3/interp = 2
|
||||
tracks/3/loop_wrap = true
|
||||
tracks/3/keys = {
|
||||
"times": PackedFloat32Array(0, 0.3, 0.8000001),
|
||||
"transitions": PackedFloat32Array(1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0.9350104, 3.0957325, -1.9789876), Vector3(0.93194425, 3.0397656, -2.0486145), Vector3(0.9362563, 3.1298003, -1.9366695)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_1ay6d"]
|
||||
resource_name = "jump_end"
|
||||
length = 0.26667002
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("..:rotation")
|
||||
tracks/0/interp = 2
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.13333334, 0.26666668),
|
||||
"transitions": PackedFloat32Array(1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0, 0, 0.00011616433), Vector3(-0.08726646, 0, 0), Vector3(0, 0, 0)]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("..:position")
|
||||
tracks/1/interp = 2
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0, 0.06666667, 0.26666668),
|
||||
"transitions": PackedFloat32Array(1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0, 0, 0), Vector3(0, -0.05, 0), Vector3(0, 0, 0)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_ubhf8"]
|
||||
resource_name = "jump_start"
|
||||
length = 0.26667002
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("..:position")
|
||||
tracks/0/interp = 2
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.06666667, 0.26666668),
|
||||
"transitions": PackedFloat32Array(1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0, 0, 0), Vector3(0, -0.1, 0), Vector3(0, 0, 0)]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("..:rotation")
|
||||
tracks/1/interp = 2
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0, 0.13333334, 0.26666668),
|
||||
"transitions": PackedFloat32Array(1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0, 0, 0.00011616433), Vector3(-0.08726646, 0, 0), Vector3(0, 0, 0)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_8abgy"]
|
||||
resource_name = "mantle"
|
||||
length = 0.3
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("..:rotation")
|
||||
tracks/0/interp = 2
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.1, 0.3),
|
||||
"transitions": PackedFloat32Array(1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0, 0, 0.00011616433), Vector3(-0.5235988, 0, 0), Vector3(0, 0, 0)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_ll12k"]
|
||||
resource_name = "parry"
|
||||
length = 0.3
|
||||
step = 0.016666668
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("../../FPRig/Parry:position")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 0.083333336, 0.13333334, 0.16666667, 0.20000002, 0.3),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(-0.22145952, -0.19867475, -1.3653086), Vector3(0.08582078, -0.10871372, -0.57329714), Vector3(0.23993218, -0.07025133, -0.8836378), Vector3(0.2783246, -0.07025109, -0.9678366), Vector3(0.2897812, -0.07025109, -0.8572479), Vector3(-0.22145952, -0.19867475, -1.3653086)]
|
||||
}
|
||||
tracks/1/type = "value"
|
||||
tracks/1/imported = false
|
||||
tracks/1/enabled = true
|
||||
tracks/1/path = NodePath("../../FPRig/Sword:position")
|
||||
tracks/1/interp = 2
|
||||
tracks/1/loop_wrap = true
|
||||
tracks/1/keys = {
|
||||
"times": PackedFloat32Array(0, 0.06666667, 0.15, 0.21666668, 0.3),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0.53640664, -0.7880347, -1.9288678), Vector3(0.35144368, -0.7880347, -0.88497114), Vector3(0.87958574, -0.7880347, -1.4807583), Vector3(0.87958574, -0.7880347, -1.4807583), Vector3(0.53640664, -0.7880347, -1.9288678)]
|
||||
}
|
||||
tracks/2/type = "value"
|
||||
tracks/2/imported = false
|
||||
tracks/2/enabled = true
|
||||
tracks/2/path = NodePath("../../FPRig/Sword:rotation")
|
||||
tracks/2/interp = 2
|
||||
tracks/2/loop_wrap = true
|
||||
tracks/2/keys = {
|
||||
"times": PackedFloat32Array(0, 0.06666667, 0.15, 0.21666668, 0.3),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(-0.083978735, -1.136043, 0.19867715), Vector3(0.012032291, -1.1376454, 0.24317425), Vector3(0.012032287, -1.8018653, 0.24317427), Vector3(0.012032287, -1.8018653, 0.24317427), Vector3(-0.083978735, -1.136043, 0.19867715)]
|
||||
}
|
||||
tracks/3/type = "value"
|
||||
tracks/3/imported = false
|
||||
tracks/3/enabled = true
|
||||
tracks/3/path = NodePath("..:rotation")
|
||||
tracks/3/interp = 2
|
||||
tracks/3/loop_wrap = true
|
||||
tracks/3/keys = {
|
||||
"times": PackedFloat32Array(0, 0.016666666, 0.1, 0.16666667, 0.2, 0.3),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(0, 0, 0), Vector3(0, 0, 0), Vector3(0, 0, 0.05235988), Vector3(0, -0.05235988, -0.10471976), Vector3(0, 0.02617994, 0.05235988), Vector3(0, 0, 0)]
|
||||
}
|
||||
tracks/4/type = "method"
|
||||
tracks/4/imported = false
|
||||
tracks/4/enabled = true
|
||||
tracks/4/path = NodePath("../..")
|
||||
tracks/4/interp = 1
|
||||
tracks/4/loop_wrap = true
|
||||
tracks/4/keys = {
|
||||
"times": PackedFloat32Array(0.06666667, 0.18333334),
|
||||
"transitions": PackedFloat32Array(1, 1),
|
||||
"values": [{
|
||||
"args": [],
|
||||
"method": &"OnParryboxActivated"
|
||||
}, {
|
||||
"args": [],
|
||||
"method": &"OnParryboxDeactivated"
|
||||
}]
|
||||
}
|
||||
tracks/5/type = "bezier"
|
||||
tracks/5/imported = false
|
||||
tracks/5/enabled = true
|
||||
tracks/5/path = NodePath("../../FPRig/Parry:rotation:x")
|
||||
tracks/5/interp = 1
|
||||
tracks/5/loop_wrap = true
|
||||
tracks/5/keys = {
|
||||
"handle_modes": PackedInt32Array(0, 0, 2, 2, 2, 0),
|
||||
"points": PackedFloat32Array(0.9350104, -0.15, 0, 0.033333335, 0.17374629, 0.98194534, -0.01666667, 0.016720235, 0, 0, 1.4891908, -0.03333334, -0.06340563, 0, 0, 1.5010982, -0.005555555, 0, 0, 0, 1.3694806, -0.008333336, 0.021936258, 0, 0, 0.9350104, -0.03333333, 0.17374629, 0.033333335, 0.17374629),
|
||||
"times": PackedFloat32Array(0, 0.083333336, 0.13333334, 0.16666667, 0.21666668, 0.3)
|
||||
}
|
||||
tracks/6/type = "bezier"
|
||||
tracks/6/imported = false
|
||||
tracks/6/enabled = true
|
||||
tracks/6/path = NodePath("../../FPRig/Parry:rotation:y")
|
||||
tracks/6/interp = 1
|
||||
tracks/6/loop_wrap = true
|
||||
tracks/6/keys = {
|
||||
"handle_modes": PackedInt32Array(0, 0, 2, 2, 2, 0),
|
||||
"points": PackedFloat32Array(3.0957325, -0.15, 0, 0.05, -0.045176744, 2.8761902, -0.033333335, 0.30117726, 0, 0, 2.9792244, -0.03333334, -0.25362277, 0, 0, 2.9158187, -0.016666666, 0.11096001, 0, 0, 2.8365617, -0.01666668, -0.18834376, 0, 0, 3.0957325, -0.050000012, -0.21161652, 0.05, -0.045176744),
|
||||
"times": PackedFloat32Array(0, 0.083333336, 0.13333334, 0.16666667, 0.21666668, 0.3)
|
||||
}
|
||||
tracks/7/type = "bezier"
|
||||
tracks/7/imported = false
|
||||
tracks/7/enabled = true
|
||||
tracks/7/path = NodePath("../../FPRig/Parry:rotation:z")
|
||||
tracks/7/interp = 1
|
||||
tracks/7/loop_wrap = true
|
||||
tracks/7/keys = {
|
||||
"handle_modes": PackedInt32Array(0, 0, 2, 2, 2, 0),
|
||||
"points": PackedFloat32Array(-1.9789876, -0.15, 0, 0.016666668, 0.6069969, -1.5225792, -0.01666667, 0.26527464, 0, 0, -0.9026986, -0.011111112, -0.101292565, 0, 0, -0.90269864, -0.005555555, 9.934108e-09, 0, 0, -1.642684, -0.008333336, 0.1233309, 0, 0, -1.9789876, -0.050000012, 0.13937998, 0.016666668, 0.6069969),
|
||||
"times": PackedFloat32Array(0, 0.083333336, 0.13333334, 0.16666667, 0.21666668, 0.3)
|
||||
}
|
||||
tracks/8/type = "value"
|
||||
tracks/8/imported = false
|
||||
tracks/8/enabled = true
|
||||
tracks/8/path = NodePath("../../FPRig/Parry:scale")
|
||||
tracks/8/interp = 2
|
||||
tracks/8/loop_wrap = true
|
||||
tracks/8/keys = {
|
||||
"times": PackedFloat32Array(0, 0.083333336, 0.13333334, 0.16666667, 0.3),
|
||||
"transitions": PackedFloat32Array(1, 1, 1, 1, 1),
|
||||
"update": 0,
|
||||
"values": [Vector3(1, 1, 1), Vector3(1.2, 1.2, 1.2), Vector3(1.65, 1, 1), Vector3(1, 1, 1), Vector3(1, 1, 1)]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_0hyrq"]
|
||||
_data = {
|
||||
&"RESET": SubResource("Animation_urko7"),
|
||||
&"die": SubResource("Animation_sdjj3"),
|
||||
&"hit1": SubResource("Animation_r0h40"),
|
||||
&"idle": SubResource("Animation_0hyrq"),
|
||||
&"jump_end": SubResource("Animation_1ay6d"),
|
||||
&"jump_start": SubResource("Animation_ubhf8"),
|
||||
&"mantle": SubResource("Animation_8abgy"),
|
||||
&"parry": SubResource("Animation_ll12k")
|
||||
}
|
||||
|
||||
[node name="HeadSystem" type="Node3D" unique_id=2067407038]
|
||||
script = ExtResource("1_8abgy")
|
||||
WeaponMoveRotation = 20.0
|
||||
DisplacedWeaponSway = 1.0
|
||||
DisplacedWeaponAdjustmentSpeed = 8.0
|
||||
|
||||
[node name="FPRig" type="Node3D" parent="." unique_id=922968399]
|
||||
transform = Transform3D(0.9999998, 0, 0, 0, 1.0000002, 0, 0, 0, 1.0000002, 0, 0, 0)
|
||||
|
||||
[node name="Sword" type="Node3D" parent="FPRig" unique_id=1946191657]
|
||||
transform = Transform3D(0.42791694, -0.008550272, -0.9037781, 0.19667713, 0.9768738, 0.0838801, 0.88215953, -0.2136461, 0.41970265, 0.53640664, -0.7880347, -1.9288678)
|
||||
|
||||
[node name="SwordMesh" type="MeshInstance3D" parent="FPRig/Sword" unique_id=1887561286]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.99999994, 0, 0, 0, 1, 0, 0, 0)
|
||||
cast_shadow = 0
|
||||
mesh = ExtResource("2_c5qep")
|
||||
|
||||
[node name="Parry" type="Node3D" parent="FPRig" unique_id=1218775403]
|
||||
transform = Transform3D(0.43521196, -1.1178209, 0.03266725, -0.65402746, -0.2828554, -0.96552634, 0.9071047, 0.33236945, -0.711823, -0.22145952, -0.19867475, -1.3653086)
|
||||
|
||||
[node name="ParryMesh" type="MeshInstance3D" parent="FPRig/Parry" unique_id=1993291456]
|
||||
mesh = ExtResource("3_1ay6d")
|
||||
|
||||
[node name="CameraSmooth" type="Node3D" parent="." unique_id=2072010960]
|
||||
transform = Transform3D(0.9999998, -0.00011616429, 0, 0.00011616431, 0.99999964, 0, 0, 0, 0.99999976, 0, 0, 0)
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="CameraSmooth" unique_id=544372058]
|
||||
transform = Transform3D(1, 0, 0, 0, 1.0000002, 0, 0, 0, 1.0000001, 0, 0, 0)
|
||||
current = true
|
||||
fov = 90.0
|
||||
|
||||
[node name="OnGetHitShaker" type="Node3D" parent="CameraSmooth/Camera3D" unique_id=1644568585]
|
||||
transform = Transform3D(1, 0, 0, -7.275958e-12, 0.99999976, 0, 0, 0, 0.99999976, 0, 1.8626451e-09, 3.7252903e-09)
|
||||
script = ExtResource("3_ubhf8")
|
||||
intensity = 1.2
|
||||
duration = 0.5
|
||||
fade_in = 0.06470415
|
||||
fade_out = 0.46651623
|
||||
shakerPreset = SubResource("Resource_60ouj")
|
||||
metadata/_custom_type_script = "uid://dnlxsrumw6ygp"
|
||||
|
||||
[node name="OnHitShaker" type="Node3D" parent="CameraSmooth/Camera3D" unique_id=1445921461]
|
||||
transform = Transform3D(1, 0, 0, -7.275958e-12, 0.99999976, 0, 0, 0, 0.99999976, 0, 1.8626451e-09, 3.7252903e-09)
|
||||
script = ExtResource("3_ubhf8")
|
||||
duration = 0.3
|
||||
fade_in = 0.041234624
|
||||
fade_out = 0.5547845
|
||||
shakerPreset = SubResource("Resource_se3kf")
|
||||
metadata/_custom_type_script = "uid://dnlxsrumw6ygp"
|
||||
|
||||
[node name="CameraAnchor" type="Marker3D" parent="." unique_id=1554357312]
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="." unique_id=1831491746]
|
||||
root_node = NodePath("../CameraSmooth/Camera3D")
|
||||
libraries/ = SubResource("AnimationLibrary_0hyrq")
|
||||
|
||||
[node name="AnimationTree" type="AnimationTree" parent="." unique_id=1817901670]
|
||||
root_node = NodePath("../CameraSmooth/Camera3D")
|
||||
tree_root = ExtResource("3_r0h40")
|
||||
anim_player = NodePath("../AnimationPlayer")
|
||||
parameters/OnHit/active = false
|
||||
parameters/OnHit/internal_active = false
|
||||
parameters/OnHit/request = 0
|
||||
parameters/OnJumpStart/active = false
|
||||
parameters/OnJumpStart/internal_active = false
|
||||
parameters/OnJumpStart/request = 0
|
||||
parameters/OnJumpEnd/active = false
|
||||
parameters/OnJumpEnd/internal_active = false
|
||||
parameters/OnJumpEnd/request = 0
|
||||
parameters/OnMantle/active = false
|
||||
parameters/OnMantle/internal_active = false
|
||||
parameters/OnMantle/request = 0
|
||||
parameters/OnDie/active = false
|
||||
parameters/OnDie/internal_active = false
|
||||
parameters/OnDie/request = 0
|
||||
parameters/OnParry/active = false
|
||||
parameters/OnParry/internal_active = false
|
||||
parameters/OnParry/request = 0
|
||||
|
||||
[connection signal="GotHit" from="." to="CameraSmooth/Camera3D/OnGetHitShaker" method="play_shake"]
|
||||
[connection signal="HitTarget" from="." to="CameraSmooth/Camera3D/OnHitShaker" method="play_shake"]
|
||||
114
scenes/player_controller/components/mantle/MantleSystem.cs
Normal file
114
scenes/player_controller/components/mantle/MantleSystem.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using Godot;
|
||||
using RustyOptions;
|
||||
|
||||
namespace Movementtests.systems;
|
||||
|
||||
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_follower.png")]
|
||||
public partial class MantleSystem: Node3D
|
||||
{
|
||||
[Export(PropertyHint.Range, "0,2,0.01,suffix:m,or_greater")]
|
||||
public float MantleEndLocationDistanceFromWall { get; set; } = 1f;
|
||||
[Export(PropertyHint.Range, "0,10,0.1,suffix:m,or_greater")]
|
||||
public float MantleHeightCastStart { get; set; } = 2f;
|
||||
[Export(PropertyHint.Range, "0,10,0.01,suffix:m,or_greater")]
|
||||
public float MaxStepHeight = 0.5f;
|
||||
|
||||
private ShapeCast3D _wallInFrontCast3D;
|
||||
private ShapeCast3D _mantleCast3D;
|
||||
|
||||
private ShapeCast3D _inAirWallDetect;
|
||||
private ShapeCast3D _groundedWallDetect;
|
||||
public Curve3D MantleCurve { get; private set; }
|
||||
public Vector3 FirstMantleProfilePoint { get; private set; } = Vector3.Zero;
|
||||
|
||||
public bool IsMantlePossible { get; private set; } = false;
|
||||
public bool EndedOnOtherSideOfWall { get; private set; } = false;
|
||||
public bool FoundGround { get; private set; } = false;
|
||||
public const int WallProfileCastCount = 7;
|
||||
|
||||
private ShapeCast3D[] _wallProfileShapecasts = new ShapeCast3D[WallProfileCastCount];
|
||||
|
||||
public void Init()
|
||||
{
|
||||
_wallInFrontCast3D = GetNode<ShapeCast3D>("WallInFrontCast3D");
|
||||
_mantleCast3D = GetNode<ShapeCast3D>("MantleCast3D");
|
||||
|
||||
_inAirWallDetect = GetNode<ShapeCast3D>("InAirWallDetect");
|
||||
_groundedWallDetect = GetNode<ShapeCast3D>("GroundedWallDetect");
|
||||
for (int i = 0; i < _wallProfileShapecasts.Length; i++)
|
||||
{
|
||||
_wallProfileShapecasts[i] = GetNode<ShapeCast3D>($"WallProfileShapeCasts/ShapeCast{i + 1}");
|
||||
}
|
||||
}
|
||||
|
||||
private void SetCastsEnabled(bool enabled)
|
||||
{
|
||||
foreach (var wallProfileShapecast in _wallProfileShapecasts)
|
||||
{
|
||||
wallProfileShapecast.SetEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
public void ProcessMantle(bool isGrounded)
|
||||
{
|
||||
_inAirWallDetect.SetEnabled(!isGrounded);
|
||||
_groundedWallDetect.SetEnabled(isGrounded);
|
||||
var isColliding = _inAirWallDetect.IsColliding() || _groundedWallDetect.IsColliding();
|
||||
SetCastsEnabled(isColliding);
|
||||
|
||||
// Reset state
|
||||
IsMantlePossible = false;
|
||||
EndedOnOtherSideOfWall = false;
|
||||
FoundGround = false;
|
||||
if (!isColliding) return;
|
||||
|
||||
// Check if face something wall-like that should be climbable
|
||||
var collisionNormal = isGrounded ? _groundedWallDetect.GetCollisionNormal(0) : _inAirWallDetect.GetCollisionNormal(0);
|
||||
if (collisionNormal.Y > 0.7f) return;
|
||||
|
||||
var spaceState = GetWorld3D().DirectSpaceState;
|
||||
|
||||
MantleCurve = new Curve3D();
|
||||
MantleCurve.AddPoint(Vector3.Zero);
|
||||
var hasFirstProfileHit = false;
|
||||
var previousProfilePoint = GlobalPosition;
|
||||
foreach (var wallProfileShapecast in _wallProfileShapecasts)
|
||||
{
|
||||
// Haven't met the wall yet
|
||||
if (!wallProfileShapecast.IsColliding() && !hasFirstProfileHit) continue;
|
||||
|
||||
var globalTargetPosition = wallProfileShapecast.GlobalPosition + wallProfileShapecast.TargetPosition;
|
||||
|
||||
// Got to the other side of the wall, we stop there
|
||||
if (!wallProfileShapecast.IsColliding())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var profilePoint = wallProfileShapecast.GetCollisionPoint(0);
|
||||
var profileNormal = wallProfileShapecast.GetCollisionNormal(0);
|
||||
var shape = wallProfileShapecast.Shape as SphereShape3D;
|
||||
var shapeRadius = shape == null ? 0.125f : shape.Radius;
|
||||
var centerOfShape = profilePoint + profileNormal * shapeRadius;
|
||||
|
||||
// Check if we collided parallel to a wall
|
||||
var isCollisionSameAsTarget = globalTargetPosition.IsEqualApprox(centerOfShape);
|
||||
var isCollidingWithWall = profileNormal.Y < 0.1f;
|
||||
if (isCollisionSameAsTarget || isCollidingWithWall) continue;
|
||||
|
||||
// Check if the path from the previous point makes us go through a wall
|
||||
var query = PhysicsRayQueryParameters3D.Create(previousProfilePoint, centerOfShape, wallProfileShapecast.CollisionMask);
|
||||
var result = spaceState.IntersectRay(query);
|
||||
if (result.Count > 0) break; // We are going through a wall, we stop there
|
||||
|
||||
// We have a valid collision
|
||||
if (!hasFirstProfileHit) FirstMantleProfilePoint = centerOfShape;
|
||||
hasFirstProfileHit = true;
|
||||
previousProfilePoint = centerOfShape;
|
||||
MantleCurve.AddPoint(ToLocal(centerOfShape));
|
||||
}
|
||||
if (MantleCurve.PointCount == 1) return;
|
||||
|
||||
IsMantlePossible = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://bja6tis1vaysu
|
||||
@@ -0,0 +1,4 @@
|
||||
[gd_resource type="SphereShape3D" format=3 uid="uid://dp2p8v7demb5j"]
|
||||
|
||||
[resource]
|
||||
radius = 0.25
|
||||
104
scenes/player_controller/components/mantle/mantle_system.tscn
Normal file
104
scenes/player_controller/components/mantle/mantle_system.tscn
Normal file
@@ -0,0 +1,104 @@
|
||||
[gd_scene format=3 uid="uid://wq1okogkhc5l"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bja6tis1vaysu" path="res://scenes/player_controller/components/mantle/MantleSystem.cs" id="1_2oobp"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_4coqe"]
|
||||
height = 1.7
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_2oobp"]
|
||||
radius = 0.75
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_2oobp"]
|
||||
radius = 0.25
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_i32qj"]
|
||||
radius = 0.25
|
||||
height = 1.5
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_i32qj"]
|
||||
radius = 0.125
|
||||
|
||||
[node name="MantleSystem" type="Node3D" unique_id=1117790260]
|
||||
script = ExtResource("1_2oobp")
|
||||
MantleEndLocationDistanceFromWall = 0.2
|
||||
MantleHeightCastStart = 3.0
|
||||
|
||||
[node name="MantleCast3D" type="ShapeCast3D" parent="." unique_id=977434819]
|
||||
visible = false
|
||||
shape = SubResource("CapsuleShape3D_4coqe")
|
||||
target_position = Vector3(0, 0, 0)
|
||||
max_results = 1
|
||||
collision_mask = 256
|
||||
debug_shape_custom_color = Color(1, 0, 0, 1)
|
||||
|
||||
[node name="WallInFrontCast3D" type="ShapeCast3D" parent="." unique_id=774357590]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
|
||||
visible = false
|
||||
shape = SubResource("SphereShape3D_2oobp")
|
||||
target_position = Vector3(0, 0, -1.5)
|
||||
max_results = 1
|
||||
collision_mask = 256
|
||||
debug_shape_custom_color = Color(0.911631, 0.11884, 0.656218, 1)
|
||||
|
||||
[node name="InAirWallDetect" type="ShapeCast3D" parent="." unique_id=276043236]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.01, 0)
|
||||
shape = SubResource("CapsuleShape3D_2oobp")
|
||||
target_position = Vector3(0, 0, -2)
|
||||
collision_mask = 256
|
||||
|
||||
[node name="GroundedWallDetect" type="ShapeCast3D" parent="." unique_id=1673208243]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.26, 0)
|
||||
shape = SubResource("CapsuleShape3D_i32qj")
|
||||
target_position = Vector3(0, 0, -2)
|
||||
collision_mask = 256
|
||||
|
||||
[node name="WallProfileShapeCasts" type="Node3D" parent="." unique_id=857147957]
|
||||
|
||||
[node name="ShapeCast1" type="ShapeCast3D" parent="WallProfileShapeCasts" unique_id=1271662121]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -0.5)
|
||||
enabled = false
|
||||
shape = SubResource("SphereShape3D_i32qj")
|
||||
target_position = Vector3(0, -2.125, 0)
|
||||
collision_mask = 256
|
||||
|
||||
[node name="ShapeCast2" type="ShapeCast3D" parent="WallProfileShapeCasts" unique_id=147611166]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -0.75)
|
||||
enabled = false
|
||||
shape = SubResource("SphereShape3D_i32qj")
|
||||
target_position = Vector3(0, -2.125, 0)
|
||||
collision_mask = 256
|
||||
|
||||
[node name="ShapeCast3" type="ShapeCast3D" parent="WallProfileShapeCasts" unique_id=1248645023]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -1)
|
||||
enabled = false
|
||||
shape = SubResource("SphereShape3D_i32qj")
|
||||
target_position = Vector3(0, -2.125, 0)
|
||||
collision_mask = 256
|
||||
|
||||
[node name="ShapeCast4" type="ShapeCast3D" parent="WallProfileShapeCasts" unique_id=839558141]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -1.25)
|
||||
enabled = false
|
||||
shape = SubResource("SphereShape3D_i32qj")
|
||||
target_position = Vector3(0, -2.125, 0)
|
||||
collision_mask = 256
|
||||
|
||||
[node name="ShapeCast5" type="ShapeCast3D" parent="WallProfileShapeCasts" unique_id=886271592]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -1.5)
|
||||
enabled = false
|
||||
shape = SubResource("SphereShape3D_i32qj")
|
||||
target_position = Vector3(0, -2.125, 0)
|
||||
collision_mask = 256
|
||||
|
||||
[node name="ShapeCast6" type="ShapeCast3D" parent="WallProfileShapeCasts" unique_id=1927435390]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -1.75)
|
||||
enabled = false
|
||||
shape = SubResource("SphereShape3D_i32qj")
|
||||
target_position = Vector3(0, -2.125, 0)
|
||||
collision_mask = 256
|
||||
|
||||
[node name="ShapeCast7" type="ShapeCast3D" parent="WallProfileShapeCasts" unique_id=2112972214]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.5, -2)
|
||||
enabled = false
|
||||
shape = SubResource("SphereShape3D_i32qj")
|
||||
target_position = Vector3(0, -2.125, 0)
|
||||
collision_mask = 256
|
||||
196
scenes/player_controller/components/weapon/WeaponSystem.cs
Normal file
196
scenes/player_controller/components/weapon/WeaponSystem.cs
Normal file
@@ -0,0 +1,196 @@
|
||||
using System;
|
||||
using Godot;
|
||||
using GodotStateCharts;
|
||||
using Movementtests.interfaces;
|
||||
using Movementtests.systems.damage;
|
||||
|
||||
namespace Movementtests.systems;
|
||||
|
||||
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_sword.png")]
|
||||
public partial class WeaponSystem : RigidBody3D, IDamageDealer
|
||||
{
|
||||
[Signal]
|
||||
public delegate void WeaponThrownEventHandler();
|
||||
|
||||
[Signal]
|
||||
public delegate void WeaponRetrievedEventHandler();
|
||||
|
||||
[Export]
|
||||
public RDamage RDamage { get; set; }
|
||||
[Export(PropertyHint.Range, "0,100,1,or_greater")]
|
||||
public float ThrowForce { get; set; } = 1f;
|
||||
[Export(PropertyHint.Range, "0,0.2,0.01,or_greater")]
|
||||
public float StraightThrowDuration { get; set; } = 0.1f;
|
||||
|
||||
private StateChart _weaponState;
|
||||
public StateChartState InHandState;
|
||||
public StateChartState FlyingState;
|
||||
public StateChartState PlantedState;
|
||||
|
||||
private ShapeCast3D _dashCast3D;
|
||||
|
||||
private Transform3D _startTransform;
|
||||
private Vector3 _startMeshRotation;
|
||||
|
||||
private Vector3 _throwDirection;
|
||||
public Vector3 PlantLocation { get; set; }
|
||||
public Vector3 PlantNormal { get; set; }
|
||||
public Node PlantObject { get; set; }
|
||||
|
||||
public MeshInstance3D WeaponLocationIndicator { get; set; }
|
||||
public StandardMaterial3D WeaponLocationIndicatorMaterial { get; set; }
|
||||
public MeshInstance3D WeaponMesh { get; set; }
|
||||
|
||||
public void Init()
|
||||
{
|
||||
_weaponState = StateChart.Of(GetNode("StateChart"));
|
||||
InHandState = StateChartState.Of(GetNode("StateChart/Root/InHand"));
|
||||
FlyingState = StateChartState.Of(GetNode("StateChart/Root/Flying"));
|
||||
PlantedState = StateChartState.Of(GetNode("StateChart/Root/Planted"));
|
||||
|
||||
WeaponLocationIndicator = GetNode<MeshInstance3D>("WeaponLocationIndicator");
|
||||
WeaponLocationIndicator.Visible = false;
|
||||
WeaponLocationIndicatorMaterial = WeaponLocationIndicator.GetActiveMaterial(0) as StandardMaterial3D;
|
||||
|
||||
WeaponMesh = GetNode<MeshInstance3D>("Weapon");
|
||||
_startMeshRotation = WeaponMesh.Rotation;
|
||||
|
||||
_startTransform = Transform;
|
||||
Freeze = true;
|
||||
Visible = false;
|
||||
|
||||
BodyEntered += OnThrownWeaponReachesGround;
|
||||
|
||||
InHandState.StateExited += WeaponLeft;
|
||||
InHandState.StateEntered += WeaponBack;
|
||||
}
|
||||
|
||||
public void WeaponLeft()
|
||||
{
|
||||
Visible = true;
|
||||
// WeaponLocationIndicator.Visible = true;
|
||||
EmitSignalWeaponThrown();
|
||||
}
|
||||
|
||||
public void WeaponBack()
|
||||
{
|
||||
Visible = false;
|
||||
// WeaponLocationIndicator.Visible = false;
|
||||
EmitSignalWeaponRetrieved();
|
||||
}
|
||||
|
||||
public void PlaceWeaponForTutorial(Vector3 location)
|
||||
{
|
||||
_weaponState.SendEvent("plant");
|
||||
Freeze = true;
|
||||
GlobalPosition = location;
|
||||
PlantLocation = location;
|
||||
}
|
||||
|
||||
public void ThrowWeapon(Vector3 end, bool hasHit, Vector3 collisionLocation, Vector3 collisionNormal, Node collidedObject)
|
||||
{
|
||||
_weaponState.SendEvent("throw");
|
||||
|
||||
// WeaponLocationIndicatorMaterial.StencilColor = new Color(1f, 1f, 1f);
|
||||
|
||||
_throwDirection = (end - GlobalPosition).Normalized();
|
||||
PlantLocation = collisionLocation;
|
||||
PlantNormal = collisionNormal;
|
||||
LookAt(end);
|
||||
|
||||
|
||||
var tween = GetTree().CreateTween();
|
||||
tween.SetParallel(true);
|
||||
tween.TweenProperty(this, "global_position", end, StraightThrowDuration);
|
||||
if (hasHit)
|
||||
{
|
||||
PlantObject = collidedObject;
|
||||
tween.Finished += PlantWeaponInWall;
|
||||
}
|
||||
else
|
||||
tween.Finished += ThrowWeaponOnCurve;
|
||||
}
|
||||
|
||||
public void PlantInEnemy(Node3D enemy)
|
||||
{
|
||||
GetTree().GetRoot().CallDeferred(Node.MethodName.RemoveChild, this);
|
||||
enemy.CallDeferred(Node.MethodName.AddChild, this);
|
||||
|
||||
if (enemy is IDamageable damageable)
|
||||
{
|
||||
damageable.TakeDamage(new DamageRecord(GlobalPosition, RDamage));
|
||||
}
|
||||
}
|
||||
|
||||
public void RethrowWeapon()
|
||||
{
|
||||
_weaponState.SendEvent("throw");
|
||||
_throwDirection = Vector3.Up;
|
||||
ThrowWeaponOnCurve();
|
||||
}
|
||||
|
||||
public void ThrowWeaponOnCurve()
|
||||
{
|
||||
Freeze = false;
|
||||
ApplyImpulse(_throwDirection * ThrowForce);
|
||||
}
|
||||
|
||||
public void PlantWeaponInWall()
|
||||
{
|
||||
_weaponState.SendEvent("plant");
|
||||
|
||||
Freeze = true;
|
||||
WeaponMesh.Rotation = _startMeshRotation;
|
||||
|
||||
// WeaponLocationIndicatorMaterial.StencilColor = new Color(1f, 0.2f, 0.2f);
|
||||
if (PlantObject is Node3D node)
|
||||
{
|
||||
PlantInEnemy(node);
|
||||
}
|
||||
CallDeferred(Node3D.MethodName.SetGlobalPosition, PlantLocation);
|
||||
CallDeferred(Node3D.MethodName.LookAt, GlobalTransform.Origin + PlantNormal, Vector3.Up, true);
|
||||
}
|
||||
|
||||
public void OnThrownWeaponReachesGround(Node other)
|
||||
{
|
||||
PlantObject = other;
|
||||
PlantWeaponInWall();
|
||||
}
|
||||
|
||||
public void ResetWeapon()
|
||||
{
|
||||
_weaponState.SendEvent("recover");
|
||||
Transform = _startTransform;
|
||||
Freeze = true;
|
||||
Visible = false;
|
||||
}
|
||||
|
||||
public override void _IntegrateForces(PhysicsDirectBodyState3D state)
|
||||
{
|
||||
base._IntegrateForces(state);
|
||||
|
||||
if (!Freeze && state.GetContactCount() > 0)
|
||||
{
|
||||
PlantLocation = state.GetContactLocalPosition(0);
|
||||
PlantNormal = state.GetContactLocalNormal(0);
|
||||
}
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (!FlyingState.Active) return;
|
||||
|
||||
WeaponMesh.Rotation = new Vector3(WeaponMesh.Rotation.X, WeaponMesh.Rotation.Y + (float) delta * 100, WeaponMesh.Rotation.Z);
|
||||
//LookAt(GlobalTransform.Origin + LinearVelocity.Normalized(), Vector3.Up, false);
|
||||
}
|
||||
|
||||
public bool IsPlantedUnderPlatform()
|
||||
{
|
||||
return PlantedState.Active && GlobalRotation.X > 1 && Math.Abs(GlobalRotation.Y) > 1;
|
||||
}
|
||||
|
||||
public bool IsPlantedInWall()
|
||||
{
|
||||
return PlantedState.Active && Math.Abs(GlobalRotation.X) + Math.Abs(GlobalRotation.Z) < 0.3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://iii3wfto4t5b
|
||||
@@ -0,0 +1,5 @@
|
||||
extends MeshInstance3D
|
||||
|
||||
|
||||
func _on_weapon_retrieved_body_entered(body: Node3D) -> void:
|
||||
visible = false
|
||||
@@ -0,0 +1 @@
|
||||
uid://v4nnql2laqdn
|
||||
13
scenes/player_controller/components/weapon/weapon.tres
Normal file
13
scenes/player_controller/components/weapon/weapon.tres
Normal file
@@ -0,0 +1,13 @@
|
||||
[gd_resource type="CylinderMesh" format=3 uid="uid://b7vt0nk2htpo4"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_jv82r"]
|
||||
use_z_clip_scale = true
|
||||
z_clip_scale = 0.9
|
||||
use_fov_override = true
|
||||
fov_override = 70.0
|
||||
|
||||
[resource]
|
||||
material = SubResource("StandardMaterial3D_jv82r")
|
||||
top_radius = 0.0
|
||||
bottom_radius = 0.05
|
||||
height = 1.0
|
||||
109
scenes/player_controller/components/weapon/weapon.tscn
Normal file
109
scenes/player_controller/components/weapon/weapon.tscn
Normal file
@@ -0,0 +1,109 @@
|
||||
[gd_scene format=3 uid="uid://ckm3d6k08a72u"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://iii3wfto4t5b" path="res://scenes/player_controller/components/weapon/WeaponSystem.cs" id="1_csqwk"]
|
||||
[ext_resource type="Script" uid="uid://jitubgv6judn" path="res://scenes/components/damage/RDamage.cs" id="2_m0v1h"]
|
||||
[ext_resource type="Script" uid="uid://couw105c3bde4" path="res://addons/godot_state_charts/state_chart.gd" id="3_5owyf"]
|
||||
[ext_resource type="ArrayMesh" uid="uid://cho5fixitrbds" path="res://assets/meshes/swords/resources/sword23.tres" id="3_svc06"]
|
||||
[ext_resource type="Script" uid="uid://jk2jm1g6q853" path="res://addons/godot_state_charts/compound_state.gd" id="4_svc06"]
|
||||
[ext_resource type="Script" uid="uid://cytafq8i1y8qm" path="res://addons/godot_state_charts/atomic_state.gd" id="5_m0v1h"]
|
||||
[ext_resource type="Script" uid="uid://cf1nsco3w0mf6" path="res://addons/godot_state_charts/transition.gd" id="6_jpdh0"]
|
||||
|
||||
[sub_resource type="Resource" id="Resource_jpdh0"]
|
||||
script = ExtResource("2_m0v1h")
|
||||
DamageDealt = 2.0
|
||||
metadata/_custom_type_script = "uid://jitubgv6judn"
|
||||
|
||||
[sub_resource type="CylinderShape3D" id="CylinderShape3D_avini"]
|
||||
height = 1.0
|
||||
radius = 0.1
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_svc06"]
|
||||
render_priority = 1
|
||||
transparency = 1
|
||||
no_depth_test = true
|
||||
shading_mode = 0
|
||||
grow_amount = 0.1
|
||||
stencil_mode = 3
|
||||
stencil_flags = 1
|
||||
stencil_compare = 5
|
||||
metadata/_stencil_owned = true
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m0v1h"]
|
||||
next_pass = SubResource("StandardMaterial3D_svc06")
|
||||
transparency = 1
|
||||
albedo_color = Color(1, 1, 1, 0)
|
||||
z_clip_scale = 0.1
|
||||
stencil_mode = 2
|
||||
stencil_flags = 2
|
||||
stencil_color = Color(1, 1, 1, 1)
|
||||
stencil_outline_thickness = 0.1
|
||||
|
||||
[sub_resource type="SphereMesh" id="SphereMesh_jpdh0"]
|
||||
material = SubResource("StandardMaterial3D_m0v1h")
|
||||
|
||||
[node name="Weapon" type="RigidBody3D" unique_id=831063023]
|
||||
collision_layer = 65536
|
||||
collision_mask = 304
|
||||
continuous_cd = true
|
||||
contact_monitor = true
|
||||
max_contacts_reported = 1
|
||||
script = ExtResource("1_csqwk")
|
||||
RDamage = SubResource("Resource_jpdh0")
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="." unique_id=884463982]
|
||||
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0)
|
||||
shape = SubResource("CylinderShape3D_avini")
|
||||
|
||||
[node name="Weapon" type="MeshInstance3D" parent="." unique_id=1970473659]
|
||||
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0.8673003)
|
||||
mesh = ExtResource("3_svc06")
|
||||
|
||||
[node name="WeaponLocationIndicator" type="MeshInstance3D" parent="." unique_id=406396593]
|
||||
mesh = SubResource("SphereMesh_jpdh0")
|
||||
|
||||
[node name="StateChart" type="Node" parent="." unique_id=1135887603]
|
||||
script = ExtResource("3_5owyf")
|
||||
metadata/_custom_type_script = "uid://couw105c3bde4"
|
||||
|
||||
[node name="Root" type="Node" parent="StateChart" unique_id=1816439862]
|
||||
script = ExtResource("4_svc06")
|
||||
initial_state = NodePath("InHand")
|
||||
|
||||
[node name="ToPlanted" type="Node" parent="StateChart/Root" unique_id=357013486]
|
||||
script = ExtResource("6_jpdh0")
|
||||
to = NodePath("../Planted")
|
||||
event = &"plant"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="InHand" type="Node" parent="StateChart/Root" unique_id=1828871728]
|
||||
script = ExtResource("5_m0v1h")
|
||||
|
||||
[node name="ToFlying" type="Node" parent="StateChart/Root/InHand" unique_id=1644664016]
|
||||
script = ExtResource("6_jpdh0")
|
||||
to = NodePath("../../Flying")
|
||||
event = &"throw"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="Flying" type="Node" parent="StateChart/Root" unique_id=861606667]
|
||||
script = ExtResource("5_m0v1h")
|
||||
|
||||
[node name="ToHand" type="Node" parent="StateChart/Root/Flying" unique_id=1236392249]
|
||||
script = ExtResource("6_jpdh0")
|
||||
to = NodePath("../../InHand")
|
||||
event = &"recover"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="Planted" type="Node" parent="StateChart/Root" unique_id=1036062749]
|
||||
script = ExtResource("5_m0v1h")
|
||||
|
||||
[node name="ToFlying" type="Node" parent="StateChart/Root/Planted" unique_id=1472568793]
|
||||
script = ExtResource("6_jpdh0")
|
||||
to = NodePath("../../Flying")
|
||||
event = &"throw"
|
||||
delay_in_seconds = "0.0"
|
||||
|
||||
[node name="ToHand" type="Node" parent="StateChart/Root/Planted" unique_id=627081934]
|
||||
script = ExtResource("6_jpdh0")
|
||||
to = NodePath("../../InHand")
|
||||
event = &"recover"
|
||||
delay_in_seconds = "0.0"
|
||||
11
scenes/player_controller/components/weapon/weapon_tuto.tres
Normal file
11
scenes/player_controller/components/weapon/weapon_tuto.tres
Normal file
@@ -0,0 +1,11 @@
|
||||
[gd_resource type="CylinderMesh" format=3 uid="uid://bhkbwvuft1bpg"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_f5qr4"]
|
||||
z_clip_scale = 0.9
|
||||
fov_override = 70.0
|
||||
|
||||
[resource]
|
||||
material = SubResource("StandardMaterial3D_f5qr4")
|
||||
top_radius = 0.0
|
||||
bottom_radius = 0.05
|
||||
height = 1.0
|
||||
4
scenes/player_controller/resources/PlayerShape.tres
Normal file
4
scenes/player_controller/resources/PlayerShape.tres
Normal file
@@ -0,0 +1,4 @@
|
||||
[gd_resource type="CapsuleShape3D" format=3 uid="uid://keseacdcooot"]
|
||||
|
||||
[resource]
|
||||
height = 1.7
|
||||
7
scenes/player_controller/resources/player_health.tres
Normal file
7
scenes/player_controller/resources/player_health.tres
Normal file
@@ -0,0 +1,7 @@
|
||||
[gd_resource type="Resource" script_class="RHealth" format=3 uid="uid://bjyd801wvverk"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://baiapod3csndf" path="res://scenes/components/health/RHealth.cs" id="1_tv6ah"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_tv6ah")
|
||||
metadata/_custom_type_script = "uid://baiapod3csndf"
|
||||
8
scenes/player_controller/resources/player_knockback.tres
Normal file
8
scenes/player_controller/resources/player_knockback.tres
Normal file
@@ -0,0 +1,8 @@
|
||||
[gd_resource type="Resource" script_class="RKnockback" format=3 uid="uid://bs8b0oojixm4q"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://b44cse62qru7j" path="res://scenes/components/knockback/RKnockback.cs" id="1_dthjm"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_dthjm")
|
||||
Modifier = 30.0
|
||||
metadata/_custom_type_script = "uid://b44cse62qru7j"
|
||||
@@ -0,0 +1,7 @@
|
||||
[gd_resource type="Resource" script_class="RDamageModifier" format=3 uid="uid://dyru7mxo121w6"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://b6y3ugfydvch0" path="res://scenes/components/damage/RDamageModifier.cs" id="1_7i47t"]
|
||||
|
||||
[resource]
|
||||
script = ExtResource("1_7i47t")
|
||||
metadata/_custom_type_script = "uid://b6y3ugfydvch0"
|
||||
9
scenes/player_controller/scripts/AnimationPlayer.cs
Normal file
9
scenes/player_controller/scripts/AnimationPlayer.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace Movementtests.player_controller.Scripts;
|
||||
|
||||
public partial class AnimationPlayer : Godot.AnimationPlayer
|
||||
{
|
||||
public void PlayCameraRotationOnDeath()
|
||||
{
|
||||
Play(Constants.PLAYERS_HEAD_ANIMATION_ON_DYING);
|
||||
}
|
||||
}
|
||||
1
scenes/player_controller/scripts/AnimationPlayer.cs.uid
Normal file
1
scenes/player_controller/scripts/AnimationPlayer.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bt8flen3mi28r
|
||||
48
scenes/player_controller/scripts/Bobbing.cs
Normal file
48
scenes/player_controller/scripts/Bobbing.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using Godot;
|
||||
|
||||
namespace Movementtests.player_controller.Scripts;
|
||||
|
||||
public partial class Bobbing: Node3D
|
||||
{
|
||||
[Export(PropertyHint.Range, "0,10,0.01,or_greater")]
|
||||
public float BobbingFrequency { set; get; } = 2.4f;
|
||||
[Export(PropertyHint.Range, "0,0.4,0.01,or_greater")]
|
||||
public float BobbingAmplitude { set; get; } = 0.08f;
|
||||
|
||||
private Camera3D _camera;
|
||||
|
||||
public void Init(Camera3D cam)
|
||||
{
|
||||
_camera = cam;
|
||||
}
|
||||
|
||||
public struct CameraBobbingParams
|
||||
{
|
||||
public float Delta;
|
||||
public bool IsOnFloorCustom;
|
||||
public Vector3 Velocity;
|
||||
public float SettingsMultiplier;
|
||||
}
|
||||
|
||||
private float _bobbingAccumulator; // Constantly increases when player moves in X or/and Z axis
|
||||
|
||||
public void PerformCameraBobbing(CameraBobbingParams parameters)
|
||||
{
|
||||
if (parameters.IsOnFloorCustom)
|
||||
{
|
||||
// Head bob
|
||||
_bobbingAccumulator += parameters.Delta * parameters.Velocity.Length();
|
||||
|
||||
Vector3 newPositionForCamera = Vector3.Zero;
|
||||
|
||||
// As the _bobbingAccumulator increases we're changing values for sin and cos functions.
|
||||
// Because both of them are just waves, we will be slide up with y and then slide down with y
|
||||
// creating bobbing effect. The same works for cos. As the _bobbingAccumulator increases the cos decreases and then increases
|
||||
|
||||
newPositionForCamera.Y = Mathf.Sin(_bobbingAccumulator * BobbingFrequency) * BobbingAmplitude * parameters.SettingsMultiplier;
|
||||
newPositionForCamera.X = Mathf.Cos(_bobbingAccumulator * BobbingFrequency / 2.0f) * BobbingAmplitude * parameters.SettingsMultiplier;
|
||||
|
||||
_camera.Position = newPositionForCamera;
|
||||
}
|
||||
}
|
||||
}
|
||||
1
scenes/player_controller/scripts/Bobbing.cs.uid
Normal file
1
scenes/player_controller/scripts/Bobbing.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://g8idirw62qe0
|
||||
52
scenes/player_controller/scripts/CapsuleCollider.cs
Normal file
52
scenes/player_controller/scripts/CapsuleCollider.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using Godot;
|
||||
|
||||
namespace Movementtests.player_controller.Scripts;
|
||||
|
||||
public partial class CapsuleCollider : CollisionShape3D
|
||||
{
|
||||
[Export(PropertyHint.Range, "0,5.0,0.01,suffix:m,or_greater")]
|
||||
public float CapsuleDefaultHeight { get; set; } = 2.0f;
|
||||
[Export(PropertyHint.Range, "0,5.0,0.01,suffix:m,or_greater")]
|
||||
public float CapsuleCrouchHeight { get; set; } = 1.0f;
|
||||
|
||||
public float GetCurrentHeight() { return _shape.Height; }
|
||||
public float GetDefaultHeight() { return CapsuleDefaultHeight; }
|
||||
|
||||
private CapsuleShape3D _shape;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_shape = Shape as CapsuleShape3D;
|
||||
_shape.Height = CapsuleDefaultHeight;
|
||||
}
|
||||
|
||||
public bool IsCapsuleHeightLessThanNormal()
|
||||
{
|
||||
return _shape.Height < CapsuleDefaultHeight;
|
||||
}
|
||||
|
||||
public bool IsBetweenCrouchingAndNormalHeight()
|
||||
{
|
||||
return _shape.Height > CapsuleCrouchHeight && _shape.Height < CapsuleDefaultHeight;
|
||||
}
|
||||
|
||||
public bool IsDefaultHeight()
|
||||
{
|
||||
return Mathf.IsEqualApprox(_shape.Height, CapsuleDefaultHeight);
|
||||
}
|
||||
|
||||
public bool IsCrouchingHeight()
|
||||
{
|
||||
return Mathf.IsEqualApprox(_shape.Height, CapsuleCrouchHeight);
|
||||
}
|
||||
|
||||
public void Crouch()
|
||||
{
|
||||
_shape.Height = CapsuleCrouchHeight;
|
||||
}
|
||||
|
||||
public void Uncrouch()
|
||||
{
|
||||
_shape.Height = CapsuleDefaultHeight;
|
||||
}
|
||||
}
|
||||
1
scenes/player_controller/scripts/CapsuleCollider.cs.uid
Normal file
1
scenes/player_controller/scripts/CapsuleCollider.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dd1yrt7eiiyf4
|
||||
45
scenes/player_controller/scripts/FieldOfView.cs
Normal file
45
scenes/player_controller/scripts/FieldOfView.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using Godot;
|
||||
|
||||
namespace Movementtests.player_controller.Scripts;
|
||||
|
||||
public partial class FieldOfView: Node3D
|
||||
{
|
||||
[Export(PropertyHint.Range, "0,180,0.1,degrees")]
|
||||
public float BaseFov { get; set; } = 75.0f;
|
||||
[Export(PropertyHint.Range, "0,10,0.01,or_greater")]
|
||||
public float FovChangeFactor { get; set; } = 1.2f;
|
||||
[Export(PropertyHint.Range, "0,10,0.01,or_greater")]
|
||||
public float FovChangeSpeed { get; set; } = 6.25f;
|
||||
|
||||
private Camera3D _camera;
|
||||
|
||||
public void Init(Camera3D cam)
|
||||
{
|
||||
_camera = cam;
|
||||
}
|
||||
|
||||
public struct FovParameters
|
||||
{
|
||||
public bool IsCrouchingHeight;
|
||||
public float Delta;
|
||||
public float SprintSpeed;
|
||||
public Vector3 Velocity;
|
||||
public float FOVMultiplier;
|
||||
}
|
||||
|
||||
public void PerformFovAdjustment(FovParameters parameters)
|
||||
{
|
||||
float velocityClamped = Mathf.Clamp(
|
||||
Mathf.Abs(parameters.Velocity.X) + Mathf.Abs(parameters.Velocity.Z),
|
||||
0.5f,
|
||||
parameters.SprintSpeed * 2.0f);
|
||||
|
||||
float targetFov = BaseFov + FovChangeFactor * velocityClamped * parameters.FOVMultiplier;
|
||||
|
||||
if (parameters.IsCrouchingHeight){
|
||||
targetFov = BaseFov - FovChangeFactor * velocityClamped * parameters.FOVMultiplier;
|
||||
}
|
||||
|
||||
_camera.Fov = Mathf.Lerp(_camera.Fov, targetFov, parameters.Delta * FovChangeSpeed);
|
||||
}
|
||||
}
|
||||
1
scenes/player_controller/scripts/FieldOfView.cs.uid
Normal file
1
scenes/player_controller/scripts/FieldOfView.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b6k73aj5povgv
|
||||
23
scenes/player_controller/scripts/Global.cs
Normal file
23
scenes/player_controller/scripts/Global.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
namespace Movementtests.player_controller.Scripts;
|
||||
|
||||
public class Constants
|
||||
{
|
||||
// Shaders' parameters
|
||||
public const string DISTORTION_SHADER_SCREEN_DARKNESS = "screen_darkness";
|
||||
public const string DISTORTION_SHADER_DARKNESS_PROGRESSION = "darkness_progression";
|
||||
public const string DISTORTION_SHADER_UV_OFFSET = "uv_offset";
|
||||
public const string DISTORTION_SHADER_SIZE = "size";
|
||||
|
||||
public const string VIGNETTE_SHADER_MULTIPLIER = "multiplier";
|
||||
public const string VIGNETTE_SHADER_SOFTNESS = "softness";
|
||||
|
||||
public const string BLUR_SHADER_LIMIT = "limit";
|
||||
public const string BLUR_SHADER_BLUR = "blur";
|
||||
|
||||
// Animation
|
||||
public const string PLAYERS_HEAD_ANIMATION_ON_DYING = "players_head_on_dying";
|
||||
|
||||
// Math
|
||||
public const float ACCEPTABLE_TOLERANCE = 0.01f;
|
||||
}
|
||||
|
||||
1
scenes/player_controller/scripts/Global.cs.uid
Normal file
1
scenes/player_controller/scripts/Global.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://yrcg34scpt5k
|
||||
32
scenes/player_controller/scripts/Gravity.cs
Normal file
32
scenes/player_controller/scripts/Gravity.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using Godot;
|
||||
|
||||
namespace Movementtests.player_controller.Scripts;
|
||||
|
||||
public partial class Gravity: Node3D
|
||||
{
|
||||
[Export(PropertyHint.Range, "0,10,0.01,or_greater")]
|
||||
public float Weight { get; set; } = 3.0f;
|
||||
[Export(PropertyHint.Range, "0,2,0.01,or_greater")]
|
||||
public float StartVelocity { get; set; } = 1.0f;
|
||||
[Export(PropertyHint.Range, "0.1,10,0.1,or_greater")]
|
||||
public float DoubleJumpSpeedFactor { get; set; } = 2f;
|
||||
[Export(PropertyHint.Range, "0.1,10,0.1,or_greater")]
|
||||
public float JumpFromDashSpeedFactor { get; set; } = 2f;
|
||||
[Export(PropertyHint.Range, "0.1,10,0.1,or_greater")]
|
||||
public float JumpFromWallSpeedFactor { get; set; } = 2f;
|
||||
[Export(PropertyHint.Range, "0,1,0.01,or_greater")]
|
||||
public float AdditionalGravityPower { get; set; } = 1f;
|
||||
|
||||
private float _gravity;
|
||||
|
||||
public void Init(float gravitySetting)
|
||||
{
|
||||
_gravity = gravitySetting;
|
||||
}
|
||||
|
||||
public float CalculateJumpForce() => _gravity * (StartVelocity / AdditionalGravityPower);
|
||||
public float CalculateJumpFromDashForce() => CalculateJumpForce() * JumpFromDashSpeedFactor;
|
||||
public float CalculateJumpFromWallForce() => CalculateJumpForce() * JumpFromWallSpeedFactor;
|
||||
public float CalculateDoubleJumpForce() => CalculateJumpForce() * DoubleJumpSpeedFactor;
|
||||
public float CalculateGravityForce() => _gravity * Weight;
|
||||
}
|
||||
1
scenes/player_controller/scripts/Gravity.cs.uid
Normal file
1
scenes/player_controller/scripts/Gravity.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bt0xv2q8iv1vn
|
||||
470
scenes/player_controller/scripts/HealthSystem.cs
Normal file
470
scenes/player_controller/scripts/HealthSystem.cs
Normal file
@@ -0,0 +1,470 @@
|
||||
using System;
|
||||
using Godot;
|
||||
|
||||
namespace Movementtests.player_controller.Scripts;
|
||||
|
||||
public partial class HealthSystem : Node3D
|
||||
{
|
||||
new enum Rotation
|
||||
{
|
||||
NoRotation = 0,
|
||||
CameraRotationTriggered = 1,
|
||||
RotatingOnZAxis = 2,
|
||||
ReturningBack = 3,
|
||||
}
|
||||
|
||||
[ExportGroup("Health Metrics")]
|
||||
[ExportSubgroup("Amounts")]
|
||||
[Export(PropertyHint.Range, "0,100,0.1,or_greater")]
|
||||
public float MaxHealth { get; set; } = 100.0f;
|
||||
[Export(PropertyHint.Range, "0,100,0.1,or_greater")]
|
||||
public float CurrentHealth { get; set; } = 100.0f;
|
||||
[Export(PropertyHint.Range, "0,100,0.1,or_greater")]
|
||||
public float MinimalDamageUnit { get; set; } = 25.0f;
|
||||
[Export(PropertyHint.Range, "-100,0,0.1,or_smaller")]
|
||||
public float ThresholdVelYForDamage { get; set; } = -15.0f;
|
||||
[ExportSubgroup("Regeneration")]
|
||||
[Export(PropertyHint.Range, "0,10,0.01,suffix:s,or_greater")]
|
||||
public float SecondsBeforeRegeneration { get; set; } = 5.5f;
|
||||
[Export(PropertyHint.Range, "0,10,0.01,or_greater")]
|
||||
public float RegenerationSpeed { get; set; } = 10.0f;
|
||||
|
||||
[ExportGroup("Damage Camera Effects")]
|
||||
[ExportSubgroup("Camera Shake")]
|
||||
[Export(PropertyHint.Range, "0,100,0.1,or_greater")]
|
||||
public float RotationSpeed { get; set; } = 9.0f;
|
||||
[Export(PropertyHint.Range, "0,180,0.1,degrees")]
|
||||
public float RotationDegree { get; set; } = 14.0f;
|
||||
[ExportSubgroup("Visual Distortion")]
|
||||
// Screen darkness controls how dark the screen will be, where 0.0 - natural
|
||||
// color of the screen(unaltered) and 1.0 - black screen
|
||||
[Export(PropertyHint.Range, "0.0,1.0,0.01")]
|
||||
public float ScreenDarknessMin { get; set; } = 0.0f;
|
||||
[Export(PropertyHint.Range, "0.0,1.0,0.01")]
|
||||
public float ScreenDarknessMax { get; set; } = 0.3f;
|
||||
[Export(PropertyHint.Range, "0.0,1.0,0.01")]
|
||||
public float DistortionSpeedMin { get; set; } = 0.0f;
|
||||
[Export(PropertyHint.Range, "0.0,1.0,0.01")]
|
||||
public float DistortionSpeedMax { get; set; } = 0.6f;
|
||||
[Export(PropertyHint.Range, "0.0,1.0,0.01")]
|
||||
public float DistortionSizeMin { get; set; } = 0.0f;
|
||||
[Export(PropertyHint.Range, "0.0,1.0,0.01")]
|
||||
public float DistortionSizeMax { get; set; } = 1.0f;
|
||||
[ExportSubgroup("Vignetting")]
|
||||
[Export(PropertyHint.Range, "0.0,1.0,0.01")]
|
||||
public float ActiveZoneMultiplierMin { get; set; } = 0.45f;
|
||||
[Export(PropertyHint.Range, "0.0,1.0,0.01")]
|
||||
public float ActiveZoneMultiplierMax { get; set; } = 0.475f;
|
||||
[Export(PropertyHint.Range, "0.0,1.0,0.01,or_greater")]
|
||||
public float MultiplierDeltaForAnimation { get; set; } = 0.066f;
|
||||
[Export(PropertyHint.Range, "0.0,1.0,0.01")]
|
||||
public float Softness { get; set; } = 1.0f;
|
||||
[Export(PropertyHint.Range, "0.0,10,0.01")]
|
||||
public float SpeedMin { get; set; } = 2.95f;
|
||||
[Export(PropertyHint.Range, "0.0,10,0.01")]
|
||||
public float SpeedMax { get; set; } = 4.0f;
|
||||
|
||||
// Death / GameOver
|
||||
[ExportGroup("Death")]
|
||||
[ExportSubgroup("Before Fade Out")]
|
||||
[Export(PropertyHint.Range, "0,1,0.01,or_less,or_greater")]
|
||||
public float BlurLimitValueToStartFadeOut { get; set; } = 0.3f;
|
||||
[Export(PropertyHint.Range, "0,1,0.01,or_greater")]
|
||||
public float BlurValueToStartFadeOut { get; set; } = 3.376f;
|
||||
[ExportSubgroup("Speeds")]
|
||||
[Export(PropertyHint.Range, "0.1,20.0,0.1,or_greater")]
|
||||
public float CameraDropSpeedOnDeath { get; set; } = 18.0f;
|
||||
[Export(PropertyHint.Range, "0.01,5.0,0.01,or_greater")]
|
||||
public float FadeOutSpeed { get; set; } = 0.11f;
|
||||
|
||||
[Export(PropertyHint.Range, "0.1,10,0.01,or_greater")]
|
||||
public float BlurLimitSpeedOnDeath { get; set; } = 0.9f;
|
||||
[Export(PropertyHint.Range, "0.1,10,0.01,or_greater")]
|
||||
public float BlurSpeedOnDeath { get; set; } = 1.5f;
|
||||
|
||||
[ExportSubgroup("Target values")]
|
||||
[Export(PropertyHint.Range, "0,5.0,0.01,suffix:m,or_greater")]
|
||||
public float CameraHeightOnDeath { get; set; } = 0.68f;
|
||||
[Export(PropertyHint.Range, "0,5.0,0.01,suffix:m,or_greater")]
|
||||
public float FadeOutTargetValue { get; set; } = 4.0f;
|
||||
|
||||
// TODO: add setter: BlurLimitValueToStartFadeOut should always be less than BlurLimitTargetValue
|
||||
// (control it in editor)
|
||||
[Export(PropertyHint.Range, "0,10,0.01,or_greater")]
|
||||
public float BlurLimitTargetValue { get; set; } = 0.5f;
|
||||
|
||||
// TODO: add setter: BlurValueToStartFadeOut should always be less than BlurTargetValue
|
||||
// (control it in editor)
|
||||
[Export(PropertyHint.Range, "0,10,0.01,or_greater")]
|
||||
public float BlurTargetValue { get; set; } = 7.0f;
|
||||
|
||||
[ExportSubgroup("Other")]
|
||||
[Export(PropertyHint.Range, "0.0,4.0,0.01,suffix:s,or_greater")]
|
||||
public float ScreenDarknessToReloadScene { get; set; } = 1.74f;
|
||||
|
||||
|
||||
// Required to hide Vignette effect
|
||||
private float _currentHealthInPrevFrame;
|
||||
|
||||
private float _currentVelocityYInAir;
|
||||
|
||||
private CharacterBody3D _characterBody3D;
|
||||
|
||||
private Camera3D _camera;
|
||||
private float _cameraInitialRotationZ;
|
||||
private float _targetRotationZAxis;
|
||||
private Rotation _cameraRotation = Rotation.NoRotation;
|
||||
private float _progressOnCamRotation;
|
||||
|
||||
private Vector2 _uvOffset = Vector2.Zero;
|
||||
private float _offsetResetThreshold = 5.0f;
|
||||
|
||||
private ShaderMaterial _distortionMaterial;
|
||||
|
||||
private float _timeAccumulator;
|
||||
|
||||
private float _currentSpeed;
|
||||
|
||||
private const float InitialMultiplierMidVal = 0.6f;
|
||||
private const float MultiplierMidValToHideVignette = 0.8f;
|
||||
private float _currentMultiplierMidValue;
|
||||
|
||||
private ShaderMaterial _vignetteMaterial;
|
||||
|
||||
private bool _deathAnimationPlayed;
|
||||
private float _screenDarknessOnDeath;
|
||||
private float _currentBlurLimit;
|
||||
private float _currentBlur;
|
||||
private float _currentScreenDarkness;
|
||||
|
||||
private bool _dead;
|
||||
private Node3D _head;
|
||||
private ShaderMaterial _blurMaterial;
|
||||
|
||||
public struct HealthSystemInitParams
|
||||
{
|
||||
public CharacterBody3D Parent;
|
||||
public Camera3D Camera;
|
||||
public Node3D Head;
|
||||
}
|
||||
|
||||
public void Init(HealthSystemInitParams initParams)
|
||||
{
|
||||
_currentHealthInPrevFrame = CurrentHealth;
|
||||
_currentMultiplierMidValue = InitialMultiplierMidVal;
|
||||
|
||||
_currentSpeed = SpeedMin;
|
||||
|
||||
_characterBody3D = initParams.Parent;
|
||||
_camera = initParams.Camera;
|
||||
|
||||
_head = initParams.Head;
|
||||
|
||||
// Resetting shaders' parameters
|
||||
|
||||
_vignetteMaterial.SetShaderParameter(Constants.VIGNETTE_SHADER_MULTIPLIER, 1.0f);
|
||||
_vignetteMaterial.SetShaderParameter(Constants.VIGNETTE_SHADER_SOFTNESS, 1.0f);
|
||||
|
||||
_distortionMaterial.SetShaderParameter(Constants.DISTORTION_SHADER_SCREEN_DARKNESS, 0.0f);
|
||||
_distortionMaterial.SetShaderParameter(Constants.DISTORTION_SHADER_DARKNESS_PROGRESSION, 0.0f);
|
||||
|
||||
_distortionMaterial.SetShaderParameter(
|
||||
Constants.DISTORTION_SHADER_UV_OFFSET, new Vector2(0.0f, 0.0f));
|
||||
|
||||
_distortionMaterial.SetShaderParameter(Constants.DISTORTION_SHADER_SIZE, 0.0);
|
||||
|
||||
_blurMaterial.SetShaderParameter(Constants.BLUR_SHADER_LIMIT, 0.0f);
|
||||
_blurMaterial.SetShaderParameter(Constants.BLUR_SHADER_BLUR, 0.0f);
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
float deltaConverted = (float)delta;
|
||||
|
||||
HandleDeath(deltaConverted);
|
||||
|
||||
HandleVignetteShader(deltaConverted);
|
||||
HandleDistortionShader(deltaConverted);
|
||||
|
||||
HandleCameraRotationOnHit(deltaConverted);
|
||||
HandleDamageOnFall();
|
||||
|
||||
HandleHealthRegeneration(deltaConverted);
|
||||
}
|
||||
|
||||
public void TakeDamage(float amount)
|
||||
{
|
||||
if (_dead)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_cameraRotation == Rotation.NoRotation)
|
||||
{
|
||||
_cameraRotation = Rotation.CameraRotationTriggered;
|
||||
}
|
||||
|
||||
CurrentHealth -= amount;
|
||||
CurrentHealth = Mathf.Clamp(CurrentHealth, 0, MaxHealth);
|
||||
|
||||
if (CurrentHealth == 0)
|
||||
{
|
||||
_dead = true;
|
||||
return;
|
||||
}
|
||||
|
||||
_lastHitTime = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public float GetCurrentHealth() { return CurrentHealth; }
|
||||
|
||||
#if DEBUG
|
||||
public override void _UnhandledInput(InputEvent @event)
|
||||
{
|
||||
if (@event is InputEventKey eventKey)
|
||||
|
||||
if (eventKey.Pressed && eventKey.Keycode == Key.H)
|
||||
TakeDamage(MinimalDamageUnit);
|
||||
}
|
||||
#endif
|
||||
|
||||
public bool IsDead() { return _dead; }
|
||||
|
||||
private void HandleDeath(float delta)
|
||||
{
|
||||
if (!_dead) { return; }
|
||||
|
||||
if (!_deathAnimationPlayed)
|
||||
{
|
||||
_deathAnimationPlayed = true;
|
||||
}
|
||||
|
||||
Vector3 newPosition = _head.Position;
|
||||
newPosition.Y = Mathf.Lerp(newPosition.Y, CameraHeightOnDeath, CameraDropSpeedOnDeath * delta);
|
||||
|
||||
if (newPosition.Y < CameraHeightOnDeath) { newPosition.Y = CameraHeightOnDeath; }
|
||||
|
||||
_head.Position = newPosition;
|
||||
|
||||
_currentBlurLimit = Mathf.Lerp(
|
||||
_currentBlurLimit, BlurLimitTargetValue, BlurLimitSpeedOnDeath * delta);
|
||||
|
||||
_blurMaterial.SetShaderParameter(Constants.BLUR_SHADER_LIMIT, _currentBlurLimit);
|
||||
|
||||
_currentBlur = Mathf.Lerp(_currentBlur, BlurTargetValue, BlurSpeedOnDeath * delta);
|
||||
_blurMaterial.SetShaderParameter(Constants.BLUR_SHADER_BLUR, _currentBlur);
|
||||
|
||||
if (_currentBlurLimit >= BlurLimitValueToStartFadeOut && _currentBlur >= BlurValueToStartFadeOut)
|
||||
{
|
||||
float currentScreenDarknessVariant = (float)_distortionMaterial.GetShaderParameter(
|
||||
Constants.DISTORTION_SHADER_SCREEN_DARKNESS);
|
||||
|
||||
_screenDarknessOnDeath = Mathf.Lerp(
|
||||
currentScreenDarknessVariant, FadeOutTargetValue, FadeOutSpeed * delta);
|
||||
|
||||
_distortionMaterial.SetShaderParameter(
|
||||
Constants.DISTORTION_SHADER_SCREEN_DARKNESS, _screenDarknessOnDeath);
|
||||
|
||||
if (_screenDarknessOnDeath >= ScreenDarknessToReloadScene)
|
||||
{
|
||||
GD.Print("reload");
|
||||
// Reload the current scene
|
||||
GetTree().ReloadCurrentScene();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleVignetteShader(float delta)
|
||||
{
|
||||
if (Mathf.IsEqualApprox(CurrentHealth, MaxHealth))
|
||||
{
|
||||
_currentHealthInPrevFrame = CurrentHealth;
|
||||
_currentMultiplierMidValue = InitialMultiplierMidVal;
|
||||
_timeAccumulator = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
float healthNormalized = CurrentHealth / MaxHealth;
|
||||
float healthReverted = 1.0f - healthNormalized;
|
||||
|
||||
float newAnimationSpeed = Mathf.Lerp(SpeedMin, SpeedMax, healthReverted);
|
||||
_currentSpeed = Mathf.Lerp(_currentSpeed, newAnimationSpeed, delta);
|
||||
|
||||
float completeSinCycle = Mathf.Tau / _currentSpeed;
|
||||
|
||||
_timeAccumulator = Mathf.Wrap(_timeAccumulator + delta, 0.0f, completeSinCycle);
|
||||
|
||||
float rawAnimationWeight = Mathf.Sin(_timeAccumulator * _currentSpeed);
|
||||
|
||||
float animationWeight = Mathf.Abs(rawAnimationWeight);
|
||||
|
||||
float difference = _currentHealthInPrevFrame - CurrentHealth;
|
||||
|
||||
float newMultiplierMidValue;
|
||||
|
||||
if (difference < 0)
|
||||
{
|
||||
newMultiplierMidValue = Mathf.Lerp(
|
||||
MultiplierMidValToHideVignette, ActiveZoneMultiplierMin, healthReverted);
|
||||
} else
|
||||
{
|
||||
newMultiplierMidValue = Mathf.Lerp(
|
||||
ActiveZoneMultiplierMax, ActiveZoneMultiplierMin, healthReverted);
|
||||
}
|
||||
|
||||
_currentMultiplierMidValue = Mathf.Lerp(
|
||||
_currentMultiplierMidValue, newMultiplierMidValue, delta);
|
||||
|
||||
float multiplier = Mathf.Lerp(
|
||||
_currentMultiplierMidValue - MultiplierDeltaForAnimation,
|
||||
_currentMultiplierMidValue + MultiplierDeltaForAnimation,
|
||||
animationWeight * animationWeight
|
||||
);
|
||||
|
||||
_vignetteMaterial.SetShaderParameter(Constants.VIGNETTE_SHADER_MULTIPLIER, multiplier);
|
||||
_vignetteMaterial.SetShaderParameter(Constants.VIGNETTE_SHADER_SOFTNESS, Softness);
|
||||
|
||||
_currentHealthInPrevFrame = CurrentHealth;
|
||||
}
|
||||
|
||||
private void HandleDistortionShader(float delta)
|
||||
{
|
||||
if (Mathf.IsEqualApprox(CurrentHealth, MaxHealth))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float healthNormalized = CurrentHealth / MaxHealth;
|
||||
float healthReverted = 1 - healthNormalized;
|
||||
|
||||
_distortionMaterial.SetShaderParameter(
|
||||
Constants.DISTORTION_SHADER_DARKNESS_PROGRESSION, healthReverted);
|
||||
|
||||
if (!_dead)
|
||||
{
|
||||
float screenDarkness = Mathf.Remap(
|
||||
healthReverted, 0, 1, ScreenDarknessMin, ScreenDarknessMax);
|
||||
|
||||
_distortionMaterial.SetShaderParameter(
|
||||
Constants.DISTORTION_SHADER_SCREEN_DARKNESS, screenDarkness);
|
||||
}
|
||||
|
||||
float distortionSpeed = Mathf.Remap(
|
||||
healthReverted, 0.0f, 1.0f, DistortionSpeedMin, DistortionSpeedMax);
|
||||
|
||||
float offsetVal = delta * distortionSpeed;
|
||||
|
||||
_uvOffset += new Vector2(offsetVal, offsetVal);
|
||||
|
||||
_distortionMaterial.SetShaderParameter(
|
||||
Constants.DISTORTION_SHADER_UV_OFFSET, _uvOffset);
|
||||
|
||||
if (_uvOffset.X > _offsetResetThreshold) { _uvOffset.X = 0.0f; _uvOffset.Y = 0.0f; }
|
||||
|
||||
float distortionSize = Mathf.Remap(
|
||||
healthReverted, 0.0f, 1.0f, DistortionSizeMin, DistortionSizeMax);
|
||||
|
||||
_distortionMaterial.SetShaderParameter(
|
||||
Constants.DISTORTION_SHADER_SIZE, distortionSize);
|
||||
}
|
||||
|
||||
private void RotateCameraOnZAxis(float delta, float targetAngleInRadians, Rotation rotationStateToSetOnFinish)
|
||||
{
|
||||
_progressOnCamRotation += delta * RotationSpeed;
|
||||
_progressOnCamRotation = Mathf.Clamp(_progressOnCamRotation, 0f, 1f);
|
||||
|
||||
float lerpedAngleZ = Mathf.LerpAngle(
|
||||
_camera.Rotation.Z,targetAngleInRadians, _progressOnCamRotation);
|
||||
|
||||
_camera.Rotation = new Vector3(_camera.Rotation.X, _camera.Rotation.Y, lerpedAngleZ);
|
||||
|
||||
float difference = Mathf.Abs(targetAngleInRadians - _camera.Rotation.Z);
|
||||
|
||||
if (difference < Constants.ACCEPTABLE_TOLERANCE)
|
||||
{
|
||||
_cameraRotation = rotationStateToSetOnFinish;
|
||||
_progressOnCamRotation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleCameraRotationOnHit(float delta)
|
||||
{
|
||||
if (_cameraRotation == Rotation.NoRotation || _dead) return;
|
||||
|
||||
if (_cameraRotation == Rotation.CameraRotationTriggered)
|
||||
{
|
||||
if (GD.Randi() % 2 == 0)
|
||||
{
|
||||
_targetRotationZAxis = Mathf.DegToRad(RotationDegree * -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
_targetRotationZAxis = Mathf.DegToRad(RotationDegree);
|
||||
}
|
||||
|
||||
_cameraRotation = Rotation.RotatingOnZAxis;
|
||||
}
|
||||
|
||||
if (_cameraRotation == Rotation.RotatingOnZAxis)
|
||||
{
|
||||
RotateCameraOnZAxis(delta, _targetRotationZAxis, Rotation.ReturningBack);
|
||||
}
|
||||
|
||||
if (_cameraRotation == Rotation.ReturningBack)
|
||||
{
|
||||
RotateCameraOnZAxis(delta, 0, Rotation.NoRotation);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleDamageOnFall()
|
||||
{
|
||||
if (_dead) { return;}
|
||||
|
||||
if (!_characterBody3D.IsOnFloor())
|
||||
{
|
||||
_currentVelocityYInAir = _characterBody3D.Velocity.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_currentVelocityYInAir < ThresholdVelYForDamage && ThresholdVelYForDamage > 0)
|
||||
{
|
||||
float hit = Mathf.Remap(_currentVelocityYInAir,
|
||||
ThresholdVelYForDamage, ThresholdVelYForDamage - 9.0f,
|
||||
MinimalDamageUnit, MaxHealth);
|
||||
|
||||
GD.Print("Hit damage: ", hit);
|
||||
|
||||
TakeDamage(hit);
|
||||
}
|
||||
|
||||
_currentVelocityYInAir = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
private DateTime? _lastHitTime;
|
||||
|
||||
private void HandleHealthRegeneration(float delta)
|
||||
{
|
||||
if (_lastHitTime == null || _dead) return;
|
||||
|
||||
DateTime lastHitTimeConverted = (DateTime)_lastHitTime;
|
||||
|
||||
double differenceInSeconds = (DateTime.UtcNow - lastHitTimeConverted).TotalSeconds;
|
||||
float differenceInSecondsConverted = (float)differenceInSeconds;
|
||||
|
||||
if (differenceInSecondsConverted < SecondsBeforeRegeneration)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Mathf.IsEqualApprox(CurrentHealth, MaxHealth))
|
||||
{
|
||||
CurrentHealth = MaxHealth;
|
||||
_lastHitTime = null;
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentHealth += delta * RegenerationSpeed;
|
||||
CurrentHealth = Mathf.Clamp(CurrentHealth, 0, MaxHealth);
|
||||
}
|
||||
}
|
||||
1
scenes/player_controller/scripts/HealthSystem.cs.uid
Normal file
1
scenes/player_controller/scripts/HealthSystem.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dv7v1ywmbvvcd
|
||||
41
scenes/player_controller/scripts/Mouse.cs
Normal file
41
scenes/player_controller/scripts/Mouse.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using Godot;
|
||||
|
||||
namespace Movementtests.player_controller.Scripts;
|
||||
|
||||
public partial class Mouse : Node3D
|
||||
{
|
||||
[Export(PropertyHint.Range, "0,0.1,0.001,or_greater")]
|
||||
public float Sensitivity { get; set; } = 0.004f;
|
||||
|
||||
private Node3D _head;
|
||||
private Camera3D _camera;
|
||||
|
||||
public delegate bool IsDead();
|
||||
|
||||
private IsDead _isPlayerDead;
|
||||
|
||||
public void Init(Node3D head, Camera3D cam, IsDead isDeadFunc)
|
||||
{
|
||||
Input.SetMouseMode(Input.MouseModeEnum.Captured);
|
||||
|
||||
_head = head;
|
||||
_camera = cam;
|
||||
_isPlayerDead = isDeadFunc;
|
||||
}
|
||||
|
||||
public void LookAround(Vector2 lookDir)
|
||||
{
|
||||
// Horizontal movement of head
|
||||
float angleForHorizontalRotation = lookDir.X * Sensitivity;
|
||||
_head.RotateY(angleForHorizontalRotation);
|
||||
|
||||
// Vertical movement of head
|
||||
Vector3 currentCameraRotation = _camera.Rotation;
|
||||
currentCameraRotation.X += Convert.ToSingle(lookDir.Y * Sensitivity);
|
||||
currentCameraRotation.X = Mathf.Clamp(currentCameraRotation.X, Mathf.DegToRad(-90f), Mathf.DegToRad(90f));
|
||||
|
||||
_camera.Rotation = currentCameraRotation;
|
||||
}
|
||||
|
||||
}
|
||||
1
scenes/player_controller/scripts/Mouse.cs.uid
Normal file
1
scenes/player_controller/scripts/Mouse.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://c6bx47wr7fbdm
|
||||
2225
scenes/player_controller/scripts/PlayerController.cs
Normal file
2225
scenes/player_controller/scripts/PlayerController.cs
Normal file
File diff suppressed because it is too large
Load Diff
1
scenes/player_controller/scripts/PlayerController.cs.uid
Normal file
1
scenes/player_controller/scripts/PlayerController.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bbbrf5ckydfna
|
||||
353
scenes/player_controller/scripts/StairsSystem.cs
Normal file
353
scenes/player_controller/scripts/StairsSystem.cs
Normal file
@@ -0,0 +1,353 @@
|
||||
using Godot;
|
||||
|
||||
namespace Movementtests.player_controller.Scripts;
|
||||
|
||||
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_boots.png")]
|
||||
public partial class StairsSystem: Node3D
|
||||
{
|
||||
[Export(PropertyHint.Range, "0,10,0.01,suffix:m,or_greater")]
|
||||
public float MaxStepHeight = 0.5f;
|
||||
|
||||
private RayCast3D _stairsBelowRayCast3D;
|
||||
private RayCast3D _stairsAheadRayCast3D;
|
||||
|
||||
private Node3D _cameraSmooth;
|
||||
|
||||
private bool _snappedToStairsLastFrame;
|
||||
|
||||
private Vector3? _savedCameraGlobalPos;
|
||||
|
||||
|
||||
|
||||
public void Init(RayCast3D stairsBelowRayCast3D, RayCast3D stairsAheadRayCast3D, Node3D cameraSmooth)
|
||||
{
|
||||
_stairsBelowRayCast3D = stairsBelowRayCast3D;
|
||||
_stairsAheadRayCast3D = stairsAheadRayCast3D;
|
||||
_cameraSmooth = cameraSmooth;
|
||||
}
|
||||
|
||||
public bool WasSnappedToStairsLastFrame() { return _snappedToStairsLastFrame; }
|
||||
|
||||
private bool RunBodyTestMotion(
|
||||
Transform3D from, Vector3 motion, Rid rid, out PhysicsTestMotionResult3D resultOut)
|
||||
{
|
||||
PhysicsTestMotionResult3D result = new PhysicsTestMotionResult3D();
|
||||
|
||||
resultOut = result;
|
||||
|
||||
PhysicsTestMotionParameters3D parameters = new PhysicsTestMotionParameters3D
|
||||
{
|
||||
From = from,
|
||||
Motion = motion,
|
||||
Margin = 0.00001f
|
||||
};
|
||||
|
||||
return PhysicsServer3D.BodyTestMotion(rid, parameters, result);
|
||||
}
|
||||
|
||||
|
||||
public struct UpStairsCheckParams
|
||||
{
|
||||
public bool IsOnFloorCustom;
|
||||
public bool IsCapsuleHeightLessThanNormal;
|
||||
public bool CurrentSpeedGreaterThanWalkSpeed;
|
||||
public bool IsCrouchingHeight;
|
||||
public float Delta;
|
||||
public float FloorMaxAngle;
|
||||
public Vector3 GlobalPositionFromDriver;
|
||||
public Vector3 Velocity;
|
||||
public Transform3D GlobalTransformFromDriver;
|
||||
public Rid Rid;
|
||||
}
|
||||
|
||||
public delegate void UpdateAfterUpStairsCheck(CharacterBody3D cb3D);
|
||||
public struct UpStairsCheckResult
|
||||
{
|
||||
public bool UpdateRequired;
|
||||
public UpdateAfterUpStairsCheck Update;
|
||||
}
|
||||
|
||||
public UpStairsCheckResult SnapUpStairsCheck(UpStairsCheckParams parameters)
|
||||
{
|
||||
UpStairsCheckResult updateIsNotRequired = new UpStairsCheckResult
|
||||
{
|
||||
UpdateRequired = false,
|
||||
Update = (CharacterBody3D cb3D) => { }
|
||||
};
|
||||
|
||||
if (!parameters.IsOnFloorCustom) { return updateIsNotRequired; }
|
||||
|
||||
// Different velocity multipliers are set for different situations because we alter player's speed
|
||||
// depending on those situations. For example, while crouching, player is moving slower, so we should account
|
||||
// for this while running body test motion, as the velocity of the player becomes lower. When sprinting,
|
||||
// player will have higher velocity and we can compensate it by setting lower velocity multiplier.
|
||||
|
||||
float motionVelocityMultiplier;
|
||||
|
||||
if (parameters.IsCapsuleHeightLessThanNormal)
|
||||
{
|
||||
motionVelocityMultiplier = 1.55f; // Going to crouch mode
|
||||
}
|
||||
else if (parameters.CurrentSpeedGreaterThanWalkSpeed)
|
||||
{
|
||||
motionVelocityMultiplier = 1.1f; // Sprinting
|
||||
}
|
||||
else
|
||||
{
|
||||
motionVelocityMultiplier = 1.4f; // Walking
|
||||
}
|
||||
|
||||
Vector3 expectedMoveMotion = parameters.Velocity *
|
||||
new Vector3(motionVelocityMultiplier, 0.0f, motionVelocityMultiplier) *
|
||||
parameters.Delta;
|
||||
|
||||
Vector3 offset = expectedMoveMotion + new Vector3(0, MaxStepHeight * 2.0f, 0);
|
||||
|
||||
Transform3D stepPosWithClearance = parameters.GlobalTransformFromDriver.Translated(offset);
|
||||
|
||||
Vector3 motion = new Vector3(0, -MaxStepHeight * 2.0f, 0);
|
||||
bool doesProjectionCollide = RunBodyTestMotion(
|
||||
stepPosWithClearance, motion, parameters.Rid, out var downCheckResult);
|
||||
|
||||
if (doesProjectionCollide)
|
||||
{
|
||||
GodotObject collider = downCheckResult.GetCollider();
|
||||
|
||||
if (!collider.IsClass("StaticBody3D") && !collider.IsClass("CSGShape3D"))
|
||||
{
|
||||
return updateIsNotRequired;
|
||||
}
|
||||
|
||||
// We add 0.5 because when player is crouching, his height is less than normal by the factor of 2:
|
||||
// so, 2 meters / 2 = 1 meter (Crouching height). In Godot, this is achieved by subtracting 0.5 from the
|
||||
// top and the bottom of capsule collider shape. As a result, GlobalPosition goes under the ground by 0.5
|
||||
// because capsule shape collider was cut off by 0.5 from the bottom, and GlobalPosition does not give a
|
||||
// a damn about physics (it's not the GlobalPosition of capsule shape, it's just the global coordinate of a
|
||||
// point in space). So, MaxHeight is 0.5 - 0.5(GlobalPosition that went under the ground) = 0. It means that
|
||||
// MaxStepHeight for the player while he is crouching is 0, so he can't overcome obstacles while crouching.
|
||||
// In order to address this problem we should add some offset to 0. Basically, the average height of
|
||||
// stairs is 0.23. But, also, we want to climb automatically to obstacles that are 50cm height. So, we add
|
||||
// 0.5 offset. And it means, that we balanced the max step height while crouching: when capsule height is
|
||||
// normal then max step height is 0.5, when player is crouching, then max step height is also 0.5.
|
||||
|
||||
float maxStepHeightAdjusted = parameters.IsCrouchingHeight ? MaxStepHeight + 0.5f : MaxStepHeight;
|
||||
|
||||
Vector3 stepHeight = stepPosWithClearance.Origin + downCheckResult.GetTravel() - parameters.GlobalPositionFromDriver;
|
||||
float stepHeightYToTravelEnd = stepHeight.Y;
|
||||
|
||||
float realStepHeightY = (downCheckResult.GetCollisionPoint() - parameters.GlobalPositionFromDriver).Y;
|
||||
|
||||
if (stepHeightYToTravelEnd <= 0.01 || realStepHeightY > maxStepHeightAdjusted)
|
||||
{
|
||||
return updateIsNotRequired;
|
||||
}
|
||||
|
||||
_stairsAheadRayCast3D.GlobalPosition = downCheckResult.GetCollisionPoint() + new Vector3(
|
||||
0, MaxStepHeight, 0) + expectedMoveMotion.Normalized() * 0.1f;
|
||||
|
||||
_stairsAheadRayCast3D.ForceRaycastUpdate();
|
||||
|
||||
// It's needed in order to deny too steep angles of climbing. For hills. And hills-like bumps
|
||||
// For casual stairs it's, of course, will pass
|
||||
if (!IsSurfaceTooSteep(
|
||||
_stairsAheadRayCast3D.GetCollisionNormal(), parameters.FloorMaxAngle))
|
||||
{
|
||||
|
||||
return new UpStairsCheckResult
|
||||
{
|
||||
UpdateRequired = true,
|
||||
Update = (CharacterBody3D cb3D) =>
|
||||
{
|
||||
SaveCameraGlobalPosForSmoothing();
|
||||
|
||||
cb3D.GlobalPosition = stepPosWithClearance.Origin + downCheckResult.GetTravel();
|
||||
cb3D.ApplyFloorSnap();
|
||||
|
||||
_snappedToStairsLastFrame = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return updateIsNotRequired;
|
||||
}
|
||||
|
||||
public struct DownStairsCheckParams
|
||||
{
|
||||
public bool IsOnFloor;
|
||||
public bool IsCrouchingHeight;
|
||||
public float LastFrameWasOnFloor;
|
||||
public float CapsuleDefaultHeight;
|
||||
public float CurrentCapsuleHeight;
|
||||
public float FloorMaxAngle;
|
||||
public float VelocityY;
|
||||
public Transform3D GlobalTransformFromDriver;
|
||||
public Rid Rid;
|
||||
}
|
||||
|
||||
public delegate void UpdateAfterDownStairsCheck(CharacterBody3D cb3D);
|
||||
|
||||
public struct DownStairsCheckResult
|
||||
{
|
||||
public bool UpdateIsRequired;
|
||||
public UpdateAfterDownStairsCheck Update;
|
||||
|
||||
}
|
||||
|
||||
public DownStairsCheckResult SnapDownStairsCheck(DownStairsCheckParams parameters)
|
||||
{
|
||||
bool didSnap = false;
|
||||
|
||||
if (parameters.IsCrouchingHeight)
|
||||
{
|
||||
float yCoordAdjustment = (parameters.CapsuleDefaultHeight - parameters.CurrentCapsuleHeight) / 2.0f;
|
||||
_stairsBelowRayCast3D.Position = new Vector3(0f, yCoordAdjustment, 0.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
_stairsBelowRayCast3D.Position = new Vector3(0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
_stairsBelowRayCast3D.ForceRaycastUpdate();
|
||||
|
||||
bool floorBelow = _stairsBelowRayCast3D.IsColliding() && !IsSurfaceTooSteep(
|
||||
_stairsBelowRayCast3D.GetCollisionNormal(), parameters.FloorMaxAngle);
|
||||
|
||||
float differenceInPhysicalFrames = Engine.GetPhysicsFrames() - parameters.LastFrameWasOnFloor;
|
||||
|
||||
bool wasOnFloorLastFrame = Mathf.IsEqualApprox(differenceInPhysicalFrames, 1.0f);
|
||||
|
||||
PhysicsTestMotionResult3D bodyTestResult = new PhysicsTestMotionResult3D();
|
||||
|
||||
if (!parameters.IsOnFloor && parameters.VelocityY <= 0 &&
|
||||
(wasOnFloorLastFrame || _snappedToStairsLastFrame) && floorBelow)
|
||||
{
|
||||
Vector3 motion = new Vector3(0, -MaxStepHeight, 0);
|
||||
|
||||
bool doesProjectionCollide = RunBodyTestMotion(
|
||||
parameters.GlobalTransformFromDriver, motion, parameters.Rid, out bodyTestResult);
|
||||
|
||||
if (doesProjectionCollide)
|
||||
{
|
||||
didSnap = true;
|
||||
}
|
||||
}
|
||||
|
||||
_snappedToStairsLastFrame = didSnap;
|
||||
|
||||
if (_snappedToStairsLastFrame)
|
||||
{
|
||||
return new DownStairsCheckResult
|
||||
{
|
||||
UpdateIsRequired = true,
|
||||
Update = (CharacterBody3D cb3D) =>
|
||||
{
|
||||
SaveCameraGlobalPosForSmoothing();
|
||||
|
||||
float yDelta = bodyTestResult.GetTravel().Y;
|
||||
|
||||
Vector3 positionForModification = cb3D.Position;
|
||||
|
||||
positionForModification.Y += yDelta;
|
||||
|
||||
cb3D.Position = positionForModification;
|
||||
|
||||
cb3D.ApplyFloorSnap();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return new DownStairsCheckResult
|
||||
{
|
||||
UpdateIsRequired = false,
|
||||
Update = (CharacterBody3D cb3D) => { }
|
||||
};
|
||||
}
|
||||
|
||||
private void SaveCameraGlobalPosForSmoothing()
|
||||
{
|
||||
if (_savedCameraGlobalPos == null)
|
||||
{
|
||||
_savedCameraGlobalPos = _cameraSmooth.GlobalPosition;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public struct SlideCameraParams
|
||||
{
|
||||
public bool IsCapsuleHeightLessThanNormal;
|
||||
public bool CurrentSpeedGreaterThanWalkSpeed;
|
||||
public bool BetweenCrouchingAndNormalHeight;
|
||||
public float Delta;
|
||||
}
|
||||
|
||||
private const float CrouchingLerpingWeight = 15;
|
||||
private const float WalkingLerpingWeight = 30;
|
||||
private const float SprintingLerpingWeight = 75;
|
||||
|
||||
private const float DefaultLerpingWeight = 100;
|
||||
|
||||
private float _lerpingWeight = DefaultLerpingWeight;
|
||||
|
||||
private const float MaxCameraDelayDistance = 0.25f;
|
||||
|
||||
public void SlideCameraSmoothBackToOrigin(SlideCameraParams parameters)
|
||||
{
|
||||
if (_savedCameraGlobalPos == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Vector3 savedCameraGlobalPosConverted = (Vector3)_savedCameraGlobalPos;
|
||||
|
||||
Vector3 globalPositionForModification = _cameraSmooth.GlobalPosition;
|
||||
globalPositionForModification.Y = savedCameraGlobalPosConverted.Y;
|
||||
_cameraSmooth.GlobalPosition = globalPositionForModification;
|
||||
|
||||
Vector3 positionForModification = _cameraSmooth.Position;
|
||||
positionForModification.Y = Mathf.Clamp(
|
||||
_cameraSmooth.Position.Y, -MaxCameraDelayDistance, MaxCameraDelayDistance);
|
||||
_cameraSmooth.Position = positionForModification;
|
||||
|
||||
|
||||
|
||||
if (parameters.IsCapsuleHeightLessThanNormal)
|
||||
{
|
||||
_lerpingWeight = CrouchingLerpingWeight;
|
||||
}else
|
||||
{
|
||||
if (parameters.CurrentSpeedGreaterThanWalkSpeed)
|
||||
{
|
||||
_lerpingWeight = SprintingLerpingWeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
_lerpingWeight = WalkingLerpingWeight;
|
||||
}
|
||||
}
|
||||
|
||||
// Smooth control, to smoothly go to crouching mode on stairs (if capsule height has default height initially)
|
||||
if (parameters.BetweenCrouchingAndNormalHeight)
|
||||
{
|
||||
_lerpingWeight = 150;
|
||||
positionForModification.Y = 0.05f;
|
||||
}
|
||||
|
||||
positionForModification.Y = Mathf.Lerp(
|
||||
_cameraSmooth.Position.Y, 0.0f, _lerpingWeight * parameters.Delta);
|
||||
|
||||
_cameraSmooth.Position = positionForModification;
|
||||
|
||||
_savedCameraGlobalPos = _cameraSmooth.GlobalPosition;
|
||||
|
||||
if (_cameraSmooth.Position.Y == 0)
|
||||
{
|
||||
_savedCameraGlobalPos = null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsSurfaceTooSteep(Vector3 normal, float floorMaxAngle)
|
||||
{
|
||||
return normal.AngleTo(Vector3.Up) > floorMaxAngle;
|
||||
}
|
||||
}
|
||||
1
scenes/player_controller/scripts/StairsSystem.cs.uid
Normal file
1
scenes/player_controller/scripts/StairsSystem.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cwbvxlfvmocc1
|
||||
40
scenes/player_controller/scripts/Stamina.cs
Normal file
40
scenes/player_controller/scripts/Stamina.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using Godot;
|
||||
|
||||
namespace Movementtests.player_controller.Scripts;
|
||||
|
||||
public partial class Stamina : Node
|
||||
{
|
||||
[Export(PropertyHint.Range, "0,60,0.1,suffix:s,or_greater")]
|
||||
public float MaxRunTime { get; set; } = 10.0f;
|
||||
// Regenerate run time multiplier (when run 10s and RunTimeMultiplier = 2.0f to full regenerate you need 5s)
|
||||
[Export(PropertyHint.Range, "0,10,0.01,or_greater")]
|
||||
public float RunTimeMultiplier { get; set; } = 2.0f;
|
||||
|
||||
private float _currentRunTime;
|
||||
|
||||
private float _walkSpeed;
|
||||
private float _sprintSpeed;
|
||||
|
||||
public void SetSpeeds(float walkSpeed, float sprintSpeed)
|
||||
{
|
||||
_walkSpeed = walkSpeed;
|
||||
_sprintSpeed = sprintSpeed;
|
||||
}
|
||||
|
||||
public float AccountStamina(double delta, float wantedSpeed)
|
||||
{
|
||||
if (Mathf.Abs(wantedSpeed - _sprintSpeed) > 0.1f)
|
||||
{
|
||||
float runtimeLeft = _currentRunTime - (RunTimeMultiplier * (float)delta);
|
||||
|
||||
if (_currentRunTime != 0.0f)
|
||||
_currentRunTime = Mathf.Clamp(runtimeLeft, 0, MaxRunTime);
|
||||
|
||||
return wantedSpeed;
|
||||
}
|
||||
|
||||
_currentRunTime = Mathf.Clamp(_currentRunTime + (float) delta, 0, MaxRunTime);
|
||||
|
||||
return _currentRunTime >= MaxRunTime ? _walkSpeed : wantedSpeed;
|
||||
}
|
||||
}
|
||||
1
scenes/player_controller/scripts/Stamina.cs.uid
Normal file
1
scenes/player_controller/scripts/Stamina.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://vuq8rjq3vegn
|
||||
59
scenes/player_controller/scripts/WallHugSystem.cs
Normal file
59
scenes/player_controller/scripts/WallHugSystem.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using RustyOptions;
|
||||
|
||||
namespace Movementtests.systems;
|
||||
|
||||
|
||||
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_wall.png")]
|
||||
public partial class WallHugSystem : Node3D
|
||||
{
|
||||
[Signal]
|
||||
public delegate void WallDetectedEventHandler();
|
||||
|
||||
private List<RayCast3D> _raycasts;
|
||||
public Option<Vector3> WallHugLocation { get; private set; } = Option<Vector3>.None;
|
||||
public Option<Vector3> WallHugNormal { get; private set; } = Option<Vector3>.None;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
_raycasts = new List<RayCast3D>();
|
||||
_raycasts.Add(GetNode<RayCast3D>("front"));
|
||||
_raycasts.Add(GetNode<RayCast3D>("front2"));
|
||||
_raycasts.Add(GetNode<RayCast3D>("back"));
|
||||
_raycasts.Add(GetNode<RayCast3D>("back2"));
|
||||
_raycasts.Add(GetNode<RayCast3D>("left"));
|
||||
_raycasts.Add(GetNode<RayCast3D>("left2"));
|
||||
_raycasts.Add(GetNode<RayCast3D>("right"));
|
||||
_raycasts.Add(GetNode<RayCast3D>("right2"));
|
||||
}
|
||||
|
||||
public override void _PhysicsProcess(double delta)
|
||||
{
|
||||
base._PhysicsProcess(delta);
|
||||
CheckWallHugging();
|
||||
if (IsWallHugging())
|
||||
EmitSignal(SignalName.WallDetected);
|
||||
}
|
||||
|
||||
public void CheckWallHugging()
|
||||
{
|
||||
foreach (RayCast3D raycast in _raycasts)
|
||||
{
|
||||
if (raycast.IsColliding() && Math.Abs(raycast.GetCollisionNormal().Y) < 0.3f)
|
||||
{
|
||||
WallHugLocation = raycast.GetCollisionPoint().Some();
|
||||
WallHugNormal = raycast.GetCollisionNormal().Some();
|
||||
return;
|
||||
}
|
||||
}
|
||||
WallHugLocation = Option<Vector3>.None;
|
||||
WallHugNormal = Option<Vector3>.None;
|
||||
}
|
||||
|
||||
public bool IsWallHugging()
|
||||
{
|
||||
return !WallHugLocation.IsNone;
|
||||
}
|
||||
}
|
||||
1
scenes/player_controller/scripts/WallHugSystem.cs.uid
Normal file
1
scenes/player_controller/scripts/WallHugSystem.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://tjiji63wlom5
|
||||
24
scenes/player_controller/shaders/Blur.gdshader
Normal file
24
scenes/player_controller/shaders/Blur.gdshader
Normal file
@@ -0,0 +1,24 @@
|
||||
// Original by ChaffDave : https://godotshaders.com/shader/tilt-shift-shader/
|
||||
|
||||
shader_type canvas_item;
|
||||
|
||||
uniform float limit: hint_range(0.0,0.5) = 0.2;
|
||||
uniform float blur: hint_range(0.0,8.0) = 2.0;
|
||||
uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap;
|
||||
|
||||
void fragment(){
|
||||
|
||||
if (UV.y<limit){
|
||||
|
||||
float blur_amount = blur * (1.0 - (SCREEN_UV.y / limit));
|
||||
COLOR = textureLod(screen_texture, SCREEN_UV, blur_amount);
|
||||
|
||||
} else if (UV.y > 1.0-limit){
|
||||
|
||||
float blur_amount = blur * (1.0 - ((1.0 - SCREEN_UV.y) / limit));
|
||||
COLOR = textureLod(screen_texture, SCREEN_UV, blur_amount);
|
||||
|
||||
} else {
|
||||
COLOR.a = 0.0;
|
||||
}
|
||||
}
|
||||
1
scenes/player_controller/shaders/Blur.gdshader.uid
Normal file
1
scenes/player_controller/shaders/Blur.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://btw6vsb6sa7sn
|
||||
45
scenes/player_controller/shaders/Distortion.gdshader
Normal file
45
scenes/player_controller/shaders/Distortion.gdshader
Normal file
@@ -0,0 +1,45 @@
|
||||
shader_type canvas_item;
|
||||
|
||||
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
|
||||
uniform float screen_darkness = 0.0;
|
||||
uniform float darkness_progression = 0.0;
|
||||
|
||||
uniform sampler2D smoke;
|
||||
uniform float size: hint_range(0.0, 1.0);
|
||||
|
||||
uniform vec2 uv_offset;
|
||||
|
||||
vec4 lerp(vec4 a, vec4 b, float t){
|
||||
vec4 val = vec4(
|
||||
(b.x * t) + a.x * (1.0 - t),
|
||||
(b.y * t) + a.y * (1.0 - t),
|
||||
(b.z * t) + a.z * (1.0 - t),
|
||||
(b.w * t) + a.w * (1.0 - t));
|
||||
|
||||
return clamp(val, 0, 1);
|
||||
}
|
||||
|
||||
// Function to remap a value from one range to another
|
||||
float remap(float value, float old_min, float old_max, float new_min, float new_max) {
|
||||
return new_min + (value - old_min) * (new_max - new_min) / (old_max - old_min);
|
||||
}
|
||||
|
||||
void fragment(){
|
||||
vec2 smoke_uv = UV;
|
||||
smoke_uv += uv_offset;
|
||||
|
||||
vec4 smoke_color = texture(smoke, fract(smoke_uv));
|
||||
|
||||
float size_remapped = remap(size, 0.0, 1.0, 0.0, 0.008);
|
||||
|
||||
smoke_color = clamp(smoke_color * size_remapped, 0.0, 1.0);
|
||||
|
||||
vec4 img_color = texture(SCREEN_TEXTURE, SCREEN_UV + vec2(smoke_color.g - size_remapped/2.0,0.0));
|
||||
|
||||
float screen_darkness_inverted = 1.0 - screen_darkness;
|
||||
|
||||
float darkness_scalar = (img_color.x + img_color.y + img_color.z) / 3.0 * screen_darkness_inverted;
|
||||
vec4 darkness_color = vec4(darkness_scalar, darkness_scalar, darkness_scalar, 1.0);
|
||||
|
||||
COLOR = lerp(img_color, darkness_color, darkness_progression);
|
||||
}
|
||||
1
scenes/player_controller/shaders/Distortion.gdshader.uid
Normal file
1
scenes/player_controller/shaders/Distortion.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b11c2xtiflut5
|
||||
10
scenes/player_controller/shaders/Vignette.gdshader
Normal file
10
scenes/player_controller/shaders/Vignette.gdshader
Normal file
@@ -0,0 +1,10 @@
|
||||
shader_type canvas_item;
|
||||
|
||||
uniform vec4 color : source_color;
|
||||
uniform float multiplier = 0.2;
|
||||
uniform float softness = 3.0;
|
||||
|
||||
void fragment() {
|
||||
float distance_to_center = distance(UV, vec2(0.5));
|
||||
COLOR = vec4(color.rgb, smoothstep(multiplier, softness, distance_to_center));
|
||||
}
|
||||
1
scenes/player_controller/shaders/Vignette.gdshader.uid
Normal file
1
scenes/player_controller/shaders/Vignette.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://vf7jayskpmj4
|
||||
Reference in New Issue
Block a user