From 70e3f70bcc159aa1f2c99ed5344b3dddce765af7 Mon Sep 17 00:00:00 2001 From: Minimata Date: Fri, 17 Oct 2025 16:53:23 +0200 Subject: [PATCH] dash indicators --- .../DashIndicators/m_weapon_location.tres | 18 ++ .../DashIndicators/weapon_location.tres | 164 ++++++++++++++++++ maps/city.tscn | 31 +--- player_controller/PlayerController.tscn | 22 ++- player_controller/Scripts/PlayerController.cs | 36 +++- project.godot | 4 +- systems/dash/DashSystem.cs | 1 + systems/weapon/WeaponSystem.cs | 40 +++++ systems/weapon/weapon.tscn | 30 +++- 9 files changed, 307 insertions(+), 39 deletions(-) create mode 100644 assets/materials/DashIndicators/m_weapon_location.tres create mode 100644 assets/materials/DashIndicators/weapon_location.tres diff --git a/assets/materials/DashIndicators/m_weapon_location.tres b/assets/materials/DashIndicators/m_weapon_location.tres new file mode 100644 index 00000000..8337cda6 --- /dev/null +++ b/assets/materials/DashIndicators/m_weapon_location.tres @@ -0,0 +1,18 @@ +[gd_resource type="ShaderMaterial" load_steps=4 format=3 uid="uid://l74a665l4d11"] + +[ext_resource type="Shader" uid="uid://c4iaaegacffb1" path="res://assets/materials/DashIndicators/weapon_location.tres" id="1_ahyha"] + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_svc06"] +frequency = 0.005 +domain_warp_enabled = true + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_m0v1h"] +noise = SubResource("FastNoiseLite_svc06") +seamless = true +seamless_blend_skirt = 1.0 + +[resource] +render_priority = 0 +shader = ExtResource("1_ahyha") +shader_parameter/ColorParameter = Color(0.23615, 0.62762386, 0.83560205, 1) +shader_parameter/Noise = SubResource("NoiseTexture2D_m0v1h") diff --git a/assets/materials/DashIndicators/weapon_location.tres b/assets/materials/DashIndicators/weapon_location.tres new file mode 100644 index 00000000..395bab67 --- /dev/null +++ b/assets/materials/DashIndicators/weapon_location.tres @@ -0,0 +1,164 @@ +[gd_resource type="VisualShader" load_steps=15 format=3 uid="uid://c4iaaegacffb1"] + +[sub_resource type="VisualShaderNodeFloatOp" id="VisualShaderNodeFloatOp_e8a82"] +default_input_values = [0, 0.0, 1, 5.0] +operator = 3 + +[sub_resource type="VisualShaderNodeColorParameter" id="VisualShaderNodeColorParameter_e8a82"] +parameter_name = "ColorParameter" + +[sub_resource type="VisualShaderNodeTexture2DParameter" id="VisualShaderNodeTexture2DParameter_e8a82"] +parameter_name = "Noise" + +[sub_resource type="VisualShaderNodeTexture" id="VisualShaderNodeTexture_e8a82"] +output_port_for_preview = 0 +source = 5 + +[sub_resource type="VisualShaderNodeVaryingGetter" id="VisualShaderNodeVaryingGetter_e8a82"] +expanded_output_ports = [0] +varying_name = "world_pos" +varying_type = 4 + +[sub_resource type="VisualShaderNodeVectorCompose" id="VisualShaderNodeVectorCompose_5yi0b"] +op_type = 0 + +[sub_resource type="VisualShaderNodeVectorOp" id="VisualShaderNodeVectorOp_5yi0b"] +operator = 2 + +[sub_resource type="VisualShaderNodeVectorOp" id="VisualShaderNodeVectorOp_38bbb"] +default_input_values = [0, Vector2(0, 0), 1, Vector2(0, 0)] +op_type = 0 + +[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_vus8j"] +input_name = "time" + +[sub_resource type="VisualShaderNodeVaryingSetter" id="VisualShaderNodeVaryingSetter_e8a82"] +varying_name = "world_pos" +varying_type = 4 + +[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_5yi0b"] +input_name = "model_matrix" + +[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_38bbb"] +expanded_output_ports = [0] +input_name = "vertex" + +[sub_resource type="VisualShaderNodeVectorCompose" id="VisualShaderNodeVectorCompose_vus8j"] +default_input_values = [0, 0.0, 1, 0.0, 2, 0.0, 3, 1.0] +op_type = 2 + +[sub_resource type="VisualShaderNodeTransformVecMult" id="VisualShaderNodeTransformVecMult_5l1m1"] + +[resource] +code = "shader_type spatial; +render_mode blend_mix, depth_draw_opaque, depth_test_default, cull_back, diffuse_lambert, specular_schlick_ggx; + + +// Varyings +varying vec3 var_world_pos; + +uniform vec4 ColorParameter : source_color; +uniform sampler2D Noise; + + + +void vertex() { +// Input:3 + mat4 n_out3p0 = MODEL_MATRIX; + + +// Input:4 + vec3 n_out4p0 = VERTEX; + float n_out4p1 = n_out4p0.r; + float n_out4p2 = n_out4p0.g; + float n_out4p3 = n_out4p0.b; + + +// TransformVectorMult:6 + vec3 n_out6p0 = (n_out3p0 * vec4(n_out4p0, 1.0)).xyz; + + +// VaryingSetter:2 + var_world_pos = n_out6p0; + + +} + +void fragment() { +// ColorParameter:2 + vec4 n_out2p0 = ColorParameter; + + +// VaryingGetter:5 + vec3 n_out5p0 = var_world_pos; + float n_out5p1 = n_out5p0.r; + float n_out5p2 = n_out5p0.g; + + +// VectorCompose:6 + vec2 n_out6p0 = vec2(n_out5p1, n_out5p2); + + +// Input:9 + float n_out9p0 = TIME; + + +// FloatOp:10 + float n_in10p1 = 5.00000; + float n_out10p0 = n_out9p0 / n_in10p1; + + +// VectorOp:8 + vec2 n_out8p0 = n_out6p0 + vec2(n_out10p0); + + + vec4 n_out4p0; +// Texture2D:4 + n_out4p0 = texture(Noise, n_out8p0); + + +// VectorOp:7 + vec3 n_out7p0 = vec3(n_out2p0.xyz) * vec3(n_out4p0.xyz); + + +// Output:0 + ALBEDO = n_out7p0; + ALPHA = n_out4p0.x; + EMISSION = n_out7p0; + + +} +" +varyings/world_pos = "0,4" +nodes/vertex/0/position = Vector2(560, 80) +nodes/vertex/2/node = SubResource("VisualShaderNodeVaryingSetter_e8a82") +nodes/vertex/2/position = Vector2(300, 100) +nodes/vertex/3/node = SubResource("VisualShaderNodeInput_5yi0b") +nodes/vertex/3/position = Vector2(-420, 100) +nodes/vertex/4/node = SubResource("VisualShaderNodeInput_38bbb") +nodes/vertex/4/position = Vector2(-460, 200) +nodes/vertex/5/node = SubResource("VisualShaderNodeVectorCompose_vus8j") +nodes/vertex/5/position = Vector2(-140, 300) +nodes/vertex/6/node = SubResource("VisualShaderNodeTransformVecMult_5l1m1") +nodes/vertex/6/position = Vector2(100, 60) +nodes/vertex/connections = PackedInt32Array(4, 1, 5, 0, 4, 2, 5, 1, 4, 3, 5, 2, 3, 0, 6, 0, 4, 0, 6, 1, 6, 0, 2, 0) +nodes/fragment/0/position = Vector2(960, 140) +nodes/fragment/2/node = SubResource("VisualShaderNodeColorParameter_e8a82") +nodes/fragment/2/position = Vector2(-160, 60) +nodes/fragment/3/node = SubResource("VisualShaderNodeTexture2DParameter_e8a82") +nodes/fragment/3/position = Vector2(-120, 660) +nodes/fragment/4/node = SubResource("VisualShaderNodeTexture_e8a82") +nodes/fragment/4/position = Vector2(260, 320) +nodes/fragment/5/node = SubResource("VisualShaderNodeVaryingGetter_e8a82") +nodes/fragment/5/position = Vector2(-540, 320) +nodes/fragment/6/node = SubResource("VisualShaderNodeVectorCompose_5yi0b") +nodes/fragment/6/position = Vector2(-320, 320) +nodes/fragment/7/node = SubResource("VisualShaderNodeVectorOp_5yi0b") +nodes/fragment/7/position = Vector2(460, 80) +nodes/fragment/8/node = SubResource("VisualShaderNodeVectorOp_38bbb") +nodes/fragment/8/position = Vector2(60, 300) +nodes/fragment/9/node = SubResource("VisualShaderNodeInput_vus8j") +nodes/fragment/9/position = Vector2(-440, 520) +nodes/fragment/10/node = SubResource("VisualShaderNodeFloatOp_e8a82") +nodes/fragment/10/position = Vector2(-140, 480) +nodes/fragment/connections = PackedInt32Array(3, 0, 4, 2, 5, 1, 6, 0, 5, 2, 6, 1, 2, 0, 7, 0, 4, 0, 7, 1, 7, 0, 0, 0, 4, 0, 0, 1, 7, 0, 0, 5, 6, 0, 8, 0, 8, 0, 4, 0, 9, 0, 10, 0, 10, 0, 8, 1) diff --git a/maps/city.tscn b/maps/city.tscn index 6b670a0e..b175cd44 100644 --- a/maps/city.tscn +++ b/maps/city.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=13 format=3 uid="uid://dmkw8cmalm5k"] +[gd_scene load_steps=10 format=3 uid="uid://dmkw8cmalm5k"] [ext_resource type="PackedScene" uid="uid://bei4nhkf8lwdo" path="res://player_controller/PlayerController.tscn" id="1_2vsi6"] [ext_resource type="Texture2D" uid="uid://ca4kkq3w8cd4n" path="res://assets/sky/sky_15_2k.png" id="2_ruo5i"] @@ -22,25 +22,13 @@ tonemap_mode = 4 ssao_enabled = true ssil_enabled = true sdfgi_use_occlusion = true -fog_light_energy = 0.0 +fog_light_color = Color(1, 1, 1, 1) +fog_density = 0.001 +fog_sky_affect = 0.121 volumetric_fog_enabled = true -volumetric_fog_density = 0.0 +volumetric_fog_density = 0.004 volumetric_fog_emission = Color(1, 1, 1, 1) -volumetric_fog_emission_energy = 0.1 -volumetric_fog_length = 200.0 - -[sub_resource type="FastNoiseLite" id="FastNoiseLite_wxle6"] -seed = 22 -frequency = 1.0 - -[sub_resource type="NoiseTexture3D" id="NoiseTexture3D_pxgdh"] -noise = SubResource("FastNoiseLite_wxle6") - -[sub_resource type="FogMaterial" id="FogMaterial_ukfuy"] -density = 0.3 -height_falloff = 0.07596937 -edge_fade = 6.625852 -density_texture = SubResource("NoiseTexture3D_pxgdh") +volumetric_fog_anisotropy = 0.6 [node name="Main" type="Node3D"] @@ -53,7 +41,8 @@ environment = SubResource("Environment_1bvp3") [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] transform = Transform3D(-0.78043425, 0.15240018, 0.60637933, 0.17673612, -0.8765135, 0.44775894, 0.5997381, 0.4566158, 0.6571267, 0, 0, 0) light_color = Color(0.99999934, 0.76777613, 0.6549227, 1) -light_energy = 5.0 +light_energy = 2.0 +light_volumetric_fog_energy = 2.0 shadow_enabled = true shadow_opacity = 0.95 shadow_blur = 2.435 @@ -73,7 +62,3 @@ transform = Transform3D(0.09033705, 0, 0.99591124, 0, 1, 0, -0.99591124, 0, 0.09 [node name="Water" parent="." instance=ExtResource("12_i2xii")] transform = Transform3D(10000, 0, 0, 0, 1, 0, 0, 0, 10000, 0, 4.03932, -186.25941) - -[node name="FogVolume" type="FogVolume" parent="."] -transform = Transform3D(500, 0, 0, 0, 200, 0, 0, 0, 500, 0, 0, 0) -material = SubResource("FogMaterial_ukfuy") diff --git a/player_controller/PlayerController.tscn b/player_controller/PlayerController.tscn index 1248309a..dc2d29f9 100644 --- a/player_controller/PlayerController.tscn +++ b/player_controller/PlayerController.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=43 format=3 uid="uid://bei4nhkf8lwdo"] +[gd_scene load_steps=45 format=3 uid="uid://bei4nhkf8lwdo"] [ext_resource type="Script" uid="uid://bbbrf5ckydfna" path="res://player_controller/Scripts/PlayerController.cs" id="1_poq2x"] [ext_resource type="Resource" uid="uid://bl5crtu1gkrtr" path="res://systems/inputs/base_mode/base_mode.tres" id="3_cresl"] @@ -44,6 +44,16 @@ [sub_resource type="CapsuleMesh" id="CapsuleMesh_xc2g5"] height = 1.7 +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_nodcl"] +transparency = 1 +albedo_color = Color(0, 0.627451, 0.6313726, 0.49019608) + +[sub_resource type="CylinderMesh" id="CylinderMesh_nodcl"] +material = SubResource("StandardMaterial3D_nodcl") +top_radius = 0.2 +bottom_radius = 0.2 +height = 1.0 + [sub_resource type="CanvasItemMaterial" id="CanvasItemMaterial_2q0ik"] blend_mode = 1 @@ -128,8 +138,7 @@ MantleHeightCastStart = 1.5 [node name="Bobbing" type="Node3D" parent="."] script = ExtResource("10_7wk1w") -BobbingFrequency = 3.0 -BobbingAmplitude = 0.05 +BobbingAmplitude = 0.0 [node name="FieldOfView" type="Node3D" parent="."] script = ExtResource("12_m2mxi") @@ -185,6 +194,12 @@ transform = Transform3D(1, 0, 0, 0, 0.173648, -0.984808, 0, 0.984808, 0.173648, ThrowForce = 15.0 StraightThrowDuration = 0.05 +[node name="DashIndicator" type="Node3D" parent="."] + +[node name="DashIndicatorMesh" type="MeshInstance3D" parent="DashIndicator"] +transform = Transform3D(1, 0, 0, 0, -4.371139e-08, 1, 0, -1, -4.371139e-08, 0, 0, -1) +mesh = SubResource("CylinderMesh_nodcl") + [node name="DashCooldown" type="Timer" parent="."] one_shot = true @@ -202,7 +217,6 @@ offset_left = 1524.0 offset_top = 1.0 offset_right = -8.0 offset_bottom = 1.0 -enabled = false initial_node_to_watch = NodePath("../StateChart") [node name="UI" type="CanvasLayer" parent="."] diff --git a/player_controller/Scripts/PlayerController.cs b/player_controller/Scripts/PlayerController.cs index ca0f8fe0..8fff6bc7 100644 --- a/player_controller/Scripts/PlayerController.cs +++ b/player_controller/Scripts/PlayerController.cs @@ -6,14 +6,6 @@ using Movementtests.systems; using Movementtests.player_controller.Scripts; using RustyOptions; -public enum JumpTypes -{ - SimpleJump, - DoubleJump, - JumpFromDash, - JumpFromWall -} - public partial class PlayerController : CharacterBody3D { // User API to important child nodes. @@ -33,6 +25,9 @@ public partial class PlayerController : CharacterBody3D public PlayerUi PlayerUi; public TextureRect DashIndicator; public ColorRect PowerCooldownIndicator; + public Node3D DashIndicatorNode; + public MeshInstance3D DashIndicatorMesh; + public CylinderMesh DashIndicatorMeshCylinder; private bool _movementEnabled = true; @@ -217,6 +212,10 @@ public partial class PlayerController : CharacterBody3D PowerCooldownIndicator.Visible = false; EmpoweredActionsLeft = MaxNumberOfEmpoweredActions; _targetSpeed = WalkSpeed; + DashIndicatorNode = GetNode("DashIndicator"); + DashIndicatorMesh = GetNode("DashIndicator/DashIndicatorMesh"); + DashIndicatorMeshCylinder = DashIndicatorMesh.Mesh as CylinderMesh; + DashIndicatorMesh.Visible = false; // Node3D mapNode = GetTree().Root.FindChild("Map", true, false) as Node3D; @@ -704,6 +703,8 @@ public partial class PlayerController : CharacterBody3D } DashSystem.StartPreparingDash(); + DashIndicatorMesh.Visible = true; + if (!isOnFloorCustom()) ReduceTimeScaleWhileAiming(); } @@ -711,12 +712,17 @@ public partial class PlayerController : CharacterBody3D { RotateWeaponWithPlayer(); + DashIndicatorMeshCylinder.Height = DashSystem.PlannedLocation.DistanceTo(GlobalPosition); + DashIndicatorNode.LookAt(DashSystem.PlannedLocation); + if (CanPerformEmpoweredAction()) DashSystem.PrepareDash(); } public void OnAimingExited() { DashSystem.StopPreparingDash(); + + DashIndicatorMesh.Visible = false; } public void DashToFlyingWeapon() @@ -1078,6 +1084,20 @@ public partial class PlayerController : CharacterBody3D LookAround(); CameraModifications((float) delta); HandleStairs((float) delta); + + if (WeaponSystem.InHandState.Active && !_aiming.Active) + { + DashIndicatorMesh.Visible = false; + } + + if (!WeaponSystem.InHandState.Active) + { + DashIndicatorMesh.Visible = true; + + DashIndicatorMeshCylinder.Height = WeaponSystem.GlobalPosition.DistanceTo(GlobalPosition) * 2; + DashIndicatorNode.LookAt(WeaponSystem.GlobalPosition); + } } + } diff --git a/project.godot b/project.godot index 03602dec..8a5f1f51 100644 --- a/project.godot +++ b/project.godot @@ -133,5 +133,5 @@ copy_path="res://scenes" [rendering] textures/vram_compression/import_etc2_astc=true -environment/volumetric_fog/volume_size=192 -environment/volumetric_fog/volume_depth=192 +environment/volumetric_fog/volume_size=256 +environment/volumetric_fog/volume_depth=256 diff --git a/systems/dash/DashSystem.cs b/systems/dash/DashSystem.cs index 31f7dbd7..f18176e1 100644 --- a/systems/dash/DashSystem.cs +++ b/systems/dash/DashSystem.cs @@ -128,5 +128,6 @@ public partial class DashSystem: Node3D public void StartPreparingDash() { _dashTarget.SetVisible(true); + } } diff --git a/systems/weapon/WeaponSystem.cs b/systems/weapon/WeaponSystem.cs index 7d1c46bb..b7076805 100644 --- a/systems/weapon/WeaponSystem.cs +++ b/systems/weapon/WeaponSystem.cs @@ -6,6 +6,12 @@ namespace Movementtests.systems; public partial class WeaponSystem : RigidBody3D { + [Signal] + public delegate void WeaponThrownEventHandler(); + + [Signal] + public delegate void WeaponRetrievedEventHandler(); + [Export(PropertyHint.Range, "0,100,1,or_greater")] public float ThrowForce { get; set; } = 1f; [Export(PropertyHint.Range, "0,0.2,0.01,or_greater")] @@ -26,6 +32,11 @@ public partial class WeaponSystem : RigidBody3D private Vector3 _throwDirection; public Vector3 PlantLocation { get; set; } public Vector3 PlantNormal { get; set; } + + public MeshInstance3D WeaponLocationIndicator { get; set; } + public StandardMaterial3D WeaponLocationIndicatorMaterial { get; set; } + public MeshInstance3D WeaponMesh { get; set; } + public StandardMaterial3D WeaponMaterial { get; set; } public void Init(Node3D head, Camera3D camera) { @@ -36,6 +47,13 @@ public partial class WeaponSystem : RigidBody3D InHandState = StateChartState.Of(GetNode("StateChart/Root/InHand")); FlyingState = StateChartState.Of(GetNode("StateChart/Root/Flying")); PlantedState = StateChartState.Of(GetNode("StateChart/Root/Planted")); + + WeaponLocationIndicator = GetNode("WeaponLocationIndicator"); + WeaponLocationIndicator.Visible = false; + WeaponLocationIndicatorMaterial = WeaponLocationIndicator.GetActiveMaterial(0) as StandardMaterial3D; + + WeaponMesh = GetNode("Weapon"); + WeaponMaterial = WeaponMesh.GetActiveMaterial(0) as StandardMaterial3D; _tweenQueueSystem = GetNode("TweenQueueSystem"); _tweenQueueSystem.Init(this); @@ -44,11 +62,30 @@ public partial class WeaponSystem : RigidBody3D Freeze = true; BodyEntered += OnThrownWeaponReachesGround; + + InHandState.StateExited += WeaponLeft; + InHandState.StateEntered += WeaponBack; + } + + public void WeaponLeft() + { + WeaponLocationIndicator.Visible = true; + WeaponMaterial!.UseFovOverride = false; + EmitSignalWeaponThrown(); + } + + public void WeaponBack() + { + WeaponLocationIndicator.Visible = false; + WeaponMaterial!.UseFovOverride = true; + EmitSignalWeaponRetrieved(); } public void ThrowWeapon(Vector3 end, bool hasHit, Vector3 collisionLocation, Vector3 collisionNormal) { _weaponState.SendEvent("throw"); + + WeaponLocationIndicatorMaterial.StencilColor = new Color(1f, 1f, 1f); _throwDirection = (end - GlobalPosition).Normalized(); PlantLocation = collisionLocation; @@ -71,6 +108,9 @@ public partial class WeaponSystem : RigidBody3D public void PlantWeaponInWall() { _weaponState.SendEvent("plant"); + + WeaponLocationIndicatorMaterial.StencilColor = new Color(1f, 0.2f, 0.2f); + Freeze = true; GlobalPosition = PlantLocation; LookAt(GlobalTransform.Origin + PlantNormal, Vector3.Up, true); diff --git a/systems/weapon/weapon.tscn b/systems/weapon/weapon.tscn index 742c3ecd..ec9bfd57 100644 --- a/systems/weapon/weapon.tscn +++ b/systems/weapon/weapon.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=10 format=3 uid="uid://ckm3d6k08a72u"] +[gd_scene load_steps=13 format=3 uid="uid://ckm3d6k08a72u"] [ext_resource type="Script" uid="uid://iii3wfto4t5b" path="res://systems/weapon/WeaponSystem.cs" id="1_csqwk"] [ext_resource type="PackedScene" uid="uid://dbe5f0p6lvqtr" path="res://systems/tween_queue/tween_queue_system.tscn" id="2_x1nha"] @@ -23,6 +23,29 @@ top_radius = 0.0 bottom_radius = 0.05 height = 1.0 +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_svc06"] +render_priority = 1 +transparency = 1 +no_depth_test = true +shading_mode = 0 +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"] collision_layer = 4 collision_mask = 2 @@ -37,7 +60,7 @@ script = ExtResource("1_csqwk") transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0) shape = SubResource("CylinderShape3D_avini") -[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +[node name="Weapon" type="MeshInstance3D" parent="."] transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0) mesh = SubResource("CylinderMesh_x1nha") @@ -81,3 +104,6 @@ script = ExtResource("6_jpdh0") to = NodePath("../../InHand") event = &"recover" delay_in_seconds = "0.0" + +[node name="WeaponLocationIndicator" type="MeshInstance3D" parent="."] +mesh = SubResource("SphereMesh_jpdh0")