Merge branch 'feat/physics-smoothing' into 'develop'

Implement movement smoothing on Player entity

See merge request open-fpsz/open-fpsz!53
This commit is contained in:
Squinty 2024-04-19 22:02:37 +00:00
commit 7e1c836b26
11 changed files with 587 additions and 77 deletions

21
addons/smoothing/LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Lawnjelly
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.

View file

@ -0,0 +1,7 @@
[plugin]
name="Smoothing"
description="Smoothing nodes for fixed timestep interpolation."
author="Lawnjelly"
version="1.2.1"
script="smoothing_plugin.gd"

View file

@ -0,0 +1,235 @@
# Copyright (c) 2019 Lawnjelly
#
# 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.
extends Node3D
@export
var target: NodePath:
get:
return target
set(v):
target = v
set_target()
var _m_Target: Node3D
var _m_trCurr: Transform3D
var _m_trPrev: Transform3D
const SF_ENABLED = 1 << 0
const SF_TRANSLATE = 1 << 1
const SF_BASIS = 1 << 2
const SF_SLERP = 1 << 3
const SF_INVISIBLE = 1 << 4
@export_flags("enabled", "translate", "basis", "slerp") var flags: int = SF_ENABLED | SF_TRANSLATE | SF_BASIS:
set(v):
flags = v
# we may have enabled or disabled
_SetProcessing()
get:
return flags
##########################################################################################
# USER FUNCS
# call this checked e.g. starting a level, AFTER moving the target
# so we can update both the previous and current values
func teleport():
var temp_flags = flags
_SetFlags(SF_TRANSLATE | SF_BASIS)
_RefreshTransform()
_m_trPrev = _m_trCurr
# do one frame update to make sure all components are updated
_process(0)
# resume old flags
flags = temp_flags
func set_enabled(bEnable: bool):
_ChangeFlags(SF_ENABLED, bEnable)
_SetProcessing()
func is_enabled():
return _TestFlags(SF_ENABLED)
##########################################################################################
func _ready():
_m_trCurr = Transform3D()
_m_trPrev = Transform3D()
set_process_priority(100)
set_as_top_level(true)
Engine.set_physics_jitter_fix(0.0)
func set_target():
if is_inside_tree():
_FindTarget()
func _set_flags(new_value):
flags = new_value
# we may have enabled or disabled
_SetProcessing()
func _get_flags():
return flags
func _SetProcessing():
var bEnable = _TestFlags(SF_ENABLED)
if _TestFlags(SF_INVISIBLE):
bEnable = false
set_process(bEnable)
set_physics_process(bEnable)
pass
func _enter_tree():
# might have been moved
_FindTarget()
pass
func _notification(what):
match what:
# invisible turns unchecked processing
NOTIFICATION_VISIBILITY_CHANGED:
_ChangeFlags(SF_INVISIBLE, is_visible_in_tree() == false)
_SetProcessing()
func _RefreshTransform():
if _HasTarget() == false:
return
_m_trPrev = _m_trCurr
_m_trCurr = _m_Target.global_transform
func _FindTarget():
_m_Target = null
# If no target has been assigned in the property,
# default to using the parent as the target.
if target.is_empty():
var parent = get_parent_node_3d()
if parent:
_m_Target = parent
return
var targ = get_node(target)
if ! targ:
printerr("ERROR SmoothingNode : Target " + str(target) + " not found")
return
if not targ is Node3D:
printerr("ERROR SmoothingNode : Target " + str(target) + " is not node 3D")
target = ""
return
# if we got to here targ is a spatial
_m_Target = targ
# certain targets are disallowed
if _m_Target == self:
var msg = str(_m_Target.get_name()) + " assigned to " + str(self.get_name()) + "]"
printerr("ERROR SmoothingNode : Target should not be self [", msg)
# error message
#OS.alert("Target cannot be a parent or grandparent in the scene tree.", "SmoothingNode")
_m_Target = null
target = ""
return
func _HasTarget() -> bool:
if _m_Target == null:
return false
# has not been deleted?
if is_instance_valid(_m_Target):
return true
_m_Target = null
return false
func _process(_delta):
var f = Engine.get_physics_interpolation_fraction()
var tr: Transform3D = Transform3D()
# translate
if _TestFlags(SF_TRANSLATE):
var ptDiff = _m_trCurr.origin - _m_trPrev.origin
tr.origin = _m_trPrev.origin + (ptDiff * f)
# rotate
if _TestFlags(SF_BASIS):
if _TestFlags(SF_SLERP):
tr.basis = _m_trPrev.basis.slerp(_m_trCurr.basis, f)
else:
tr.basis = _LerpBasis(_m_trPrev.basis, _m_trCurr.basis, f)
transform = tr
func _physics_process(_delta):
_RefreshTransform()
func _LerpBasis(from: Basis, to: Basis, f: float) -> Basis:
var res: Basis = Basis()
res.x = from.x.lerp(to.x, f)
res.y = from.y.lerp(to.y, f)
res.z = from.z.lerp(to.z, f)
return res
func _SetFlags(f):
flags |= f
func _ClearFlags(f):
flags &= ~f
func _TestFlags(f):
return (flags & f) == f
func _ChangeFlags(f, bSet):
if bSet:
_SetFlags(f)
else:
_ClearFlags(f)

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B

View file

@ -0,0 +1,212 @@
# Copyright (c) 2019 Lawnjelly
#
# 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.
extends Node2D
@export
var target: NodePath:
get:
return target
set(v):
target = v
if is_inside_tree():
_FindTarget()
var _m_Target: Node2D
var _m_Flip:bool = false
var _m_Trans_curr: Transform2D = Transform2D()
var _m_Trans_prev: Transform2D = Transform2D()
const SF_ENABLED = 1 << 0
const SF_GLOBAL_IN = 1 << 1
const SF_GLOBAL_OUT = 1 << 2
const SF_TOP_LEVEL = 1 << 3
const SF_INVISIBLE = 1 << 4
@export_flags("enabled", "global in", "global out", "top level") var flags: int = SF_ENABLED | SF_GLOBAL_IN | SF_GLOBAL_OUT:
set(v):
flags = v
# we may have enabled or disabled
_SetProcessing()
get:
return flags
##########################################################################################
# USER FUNCS
# call this checked e.g. starting a level, AFTER moving the target
# so we can update both the previous and current values
func teleport():
_RefreshTransform()
_m_Trans_prev = _m_Trans_curr
# call frame upate to make sure all components of the node are set
_process(0)
func set_enabled(bEnable: bool):
_ChangeFlags(SF_ENABLED, bEnable)
_SetProcessing()
func is_enabled():
return _TestFlags(SF_ENABLED)
##########################################################################################
func _ready():
set_process_priority(100)
Engine.set_physics_jitter_fix(0.0)
set_as_top_level(_TestFlags(SF_TOP_LEVEL))
func _SetProcessing():
var bEnable = _TestFlags(SF_ENABLED)
if _TestFlags(SF_INVISIBLE):
bEnable = false
set_process(bEnable)
set_physics_process(bEnable)
set_as_top_level(_TestFlags(SF_TOP_LEVEL))
func _enter_tree():
# might have been moved
_FindTarget()
func _notification(what):
match what:
# invisible turns unchecked processing
NOTIFICATION_VISIBILITY_CHANGED:
_ChangeFlags(SF_INVISIBLE, is_visible_in_tree() == false)
_SetProcessing()
func _RefreshTransform():
if _HasTarget() == false:
return
_m_Trans_prev = _m_Trans_curr
if _TestFlags(SF_GLOBAL_IN):
_m_Trans_curr = _m_Target.get_global_transform()
else:
_m_Trans_curr = _m_Target.get_transform()
_m_Flip = false
# Ideally we would use determinant core function, as in commented line below, but we
# need to workaround for backward compat.
# if (_m_Trans_prev.determinant() < 0) != (_m_Trans_curr.determinant() < 0):
if (_Determinant_Sign(_m_Trans_prev) != _Determinant_Sign(_m_Trans_curr)):
_m_Flip = true
func _Determinant_Sign(t:Transform2D)->bool:
# Workaround Transform2D determinant function not being available
# until 3.6 / 4.1.
# We calculate determinant manually, slower but compatible to lower
# godot versions.
var d = (t.x.x * t.y.y) - (t.x.y * t.y.x)
return d >= 0.0
func _FindTarget():
_m_Target = null
# If no target has been assigned in the property,
# default to using the parent as the target.
if target.is_empty():
var parent = get_parent()
if parent and (parent is Node2D):
_m_Target = parent
return
var targ = get_node(target)
if ! targ:
printerr("ERROR SmoothingNode2D : Target " + str(target) + " not found")
return
if not targ is Node2D:
printerr("ERROR SmoothingNode2D : Target " + str(target) + " is not Node2D")
target = ""
return
# if we got to here targ is correct type
_m_Target = targ
func _HasTarget() -> bool:
if _m_Target == null:
return false
# has not been deleted?
if is_instance_valid(_m_Target):
return true
_m_Target = null
return false
func _process(_delta):
var f = Engine.get_physics_interpolation_fraction()
var tr = Transform2D()
tr.origin = lerp(_m_Trans_prev.origin, _m_Trans_curr.origin, f)
tr.x = lerp(_m_Trans_prev.x, _m_Trans_curr.x, f)
tr.y = lerp(_m_Trans_prev.y, _m_Trans_curr.y, f)
# When a sprite flip is detected, turn off interpolation for that tick.
if _m_Flip:
tr = _m_Trans_curr
if _TestFlags(SF_GLOBAL_OUT) and not _TestFlags(SF_TOP_LEVEL):
set_global_transform(tr)
else:
set_transform(tr)
func _physics_process(_delta):
_RefreshTransform()
func _SetFlags(f):
flags |= f
func _ClearFlags(f):
flags &= ~f
func _TestFlags(f):
return (flags & f) == f
func _ChangeFlags(f, bSet):
if bSet:
_SetFlags(f)
else:
_ClearFlags(f)

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 B

View file

@ -0,0 +1,17 @@
@tool
extends EditorPlugin
func _enter_tree():
# Initialization of the plugin goes here
# Add the new type with a name, a parent type, a script and an icon
add_custom_type("Smoothing", "Node3D", preload("smoothing.gd"), preload("smoothing.png"))
add_custom_type("Smoothing2D", "Node2D", preload("smoothing_2d.gd"), preload("smoothing_2d.png"))
pass
func _exit_tree():
# Clean-up of the plugin goes here
# Always remember to remove_at it from the engine when deactivated
remove_custom_type("Smoothing")
remove_custom_type("Smoothing2D")

View file

@ -42,17 +42,17 @@ enum PlayerState { PLAYER_ALIVE, PLAYER_DEAD }
@export var nickname : String @export var nickname : String
@onready var input : PlayerInput = $PlayerInput @onready var input : PlayerInput = $PlayerInput
@onready var camera : Camera3D = $SpringArm3D/Camera3D @onready var camera : Camera3D = $Smoothing/SpringArm3D/Camera3D
@onready var hud : CanvasLayer = $HUD @onready var hud : CanvasLayer = $HUD
@onready var shape_cast : ShapeCast3D = $ShapeCast3D @onready var shape_cast : ShapeCast3D = $ShapeCast3D
@onready var weapon : Node3D = $SpringArm3D/Inventory/SpaceGun @onready var weapon : Node3D = $Smoothing/SpringArm3D/Inventory/SpaceGun
@onready var animation_player : AnimationPlayer = $AnimationPlayer @onready var animation_player : AnimationPlayer = $AnimationPlayer
@onready var health_component : Area3D = $HealthComponent @onready var health_component : Area3D = $HealthComponent
@onready var collision_shape : CollisionShape3D = $CollisionShape3D @onready var collision_shape : CollisionShape3D = $CollisionShape3D
@onready var flag_carry_component : FlagCarryComponent = $FlagCarryComponent @onready var flag_carry_component : FlagCarryComponent = $FlagCarryComponent
@onready var spring_arm_height : float = $SpringArm3D.position.y @onready var spring_arm_height : float = $Smoothing/SpringArm3D.position.y
@onready var _original_weapon_transform : Transform3D = weapon.transform @onready var _original_weapon_transform : Transform3D = weapon.transform
@onready var flag_carry_attachment : Node3D = $SpringArm3D/FlagCarryAttachment @onready var flag_carry_attachment : Node3D = $Smoothing/SpringArm3D/FlagCarryAttachment
@onready var _game_settings : Settings = get_node("/root/GlobalSettings") @onready var _game_settings : Settings = get_node("/root/GlobalSettings")
signal died(player : Player) signal died(player : Player)
@ -80,12 +80,13 @@ func _ready() -> void:
camera.current = true camera.current = true
camera.fov = _game_settings.fov camera.fov = _game_settings.fov
# set the spring arm translation to be about head height level # set the spring arm translation to be about head height level
$SpringArm3D.transform = Transform3D().translated(Vector3(0, collision_shape.shape.height / 2, 0) * 0.9) $Smoothing/SpringArm3D.transform = Transform3D().translated(Vector3(0, collision_shape.shape.height / 2, 0) * 0.9)
flag_carry_attachment.hide() flag_carry_attachment.hide()
remove_child($ThirdPerson)
$Smoothing.remove_child($Smoothing/ThirdPerson)
else: else:
# set the iff attachment translation to be about head height level # set the iff attachment translation to be about head height level
$ThirdPerson/IFFAttachment.transform = Transform3D().translated(Vector3(0, collision_shape.shape.height / 2, 0) * 0.9) $Smoothing/ThirdPerson/IFFAttachment.transform = Transform3D().translated(Vector3(0, collision_shape.shape.height / 2, 0) * 0.9)
remove_child(hud) remove_child(hud)
weapon.hide() weapon.hide()
@ -128,13 +129,17 @@ func _handle_aerial_control(direction : Vector3) -> void:
if not input.jetting and not is_on_floor(): if not input.jetting and not is_on_floor():
apply_force(direction * aerial_control_force) apply_force(direction * aerial_control_force)
func _handle_jetpack(delta : float, direction : Vector3) -> void: func _handle_jetpack(direction : Vector3) -> void:
if input.jetting: if input.jetting:
if energy > 0: if energy > 0:
var up_vector : Vector3 = Vector3.UP * jetpack_vertical_force * jetpack_force_factor var up_vector : Vector3 = Vector3.UP * jetpack_vertical_force * jetpack_force_factor
var side_vector : Vector3 = direction * jetpack_horizontal_force * jetpack_force_factor var side_vector : Vector3 = direction * jetpack_horizontal_force * jetpack_force_factor
apply_force(up_vector + side_vector) apply_force(up_vector + side_vector)
energy -= energy_drain_rate * delta
func _update_jetpack_energy(delta : float) -> void:
if input.jetting:
if energy > 0:
energy -= energy_drain_rate * delta
else: else:
energy += energy_charge_rate * delta energy += energy_charge_rate * delta
@ -148,7 +153,7 @@ func _process(_delta : float) -> void:
else: else:
iff.show() iff.show()
if not _is_pawn(): if not _is_pawn():
$ThirdPerson/PlayerMesh.global_transform.basis = Basis.from_euler(Vector3(0.0, input.camera_rotation.x + PI, 0.0)) $Smoothing/ThirdPerson/PlayerMesh.global_transform.basis = Basis.from_euler(Vector3(0.0, input.camera_rotation.x + PI, 0.0))
else: else:
if animation_player.current_animation == "shoot": if animation_player.current_animation == "shoot":
pass pass
@ -157,20 +162,24 @@ func _process(_delta : float) -> void:
%SpringArm3D.global_transform.basis = Basis.from_euler(Vector3(input.camera_rotation.y, input.camera_rotation.x, 0.0)) %SpringArm3D.global_transform.basis = Basis.from_euler(Vector3(input.camera_rotation.y, input.camera_rotation.x, 0.0))
func _physics_process(delta : float) -> void: func _physics_process(delta : float) -> void:
_update_jetpack_energy(delta)
func _handle_movement() -> void:
# retrieve user's direction vector # retrieve user's direction vector
var _input_dir : Vector2 = input.direction var _input_dir : Vector2 = input.direction
# compute direction in local space # compute direction in local space
var _direction : Vector3 = (transform.basis * Vector3(_input_dir.x, 0, _input_dir.y)).normalized() var _direction : Vector3 = (transform.basis * Vector3(_input_dir.x, 0, _input_dir.y)).normalized()
_update_third_person_animations() _update_third_person_animations()
if _is_player_dead(): if _is_player_dead():
return return
# adjust direction based on spring arm rotation # adjust direction based on spring arm rotation
_direction = _direction.rotated(Vector3.UP, $SpringArm3D.rotation.y) _direction = _direction.rotated(Vector3.UP, $Smoothing/SpringArm3D.rotation.y)
_handle_aerial_control(_direction) _handle_aerial_control(_direction)
_handle_jetpack(delta, _direction) _handle_jetpack(_direction)
# handle ski # handle ski
if _is_skiing(): if _is_skiing():
@ -191,18 +200,20 @@ func _physics_process(delta : float) -> void:
linear_velocity = lerp(linear_velocity, _direction * ground_speed, .1) linear_velocity = lerp(linear_velocity, _direction * ground_speed, .1)
func _integrate_forces(_state : PhysicsDirectBodyState3D) -> void: if _jumping:
if is_on_floor() and _jumping: var v : float = sqrt(2 * g * jump_height)
var v : float = sqrt(2 * g * jump_height) apply_central_impulse(Vector3(0, mass * v, 0))
apply_central_impulse(Vector3(0, mass * v, 0))
_jumping = false _jumping = false
func _integrate_forces(_state : PhysicsDirectBodyState3D) -> void:
_handle_movement()
func _update_third_person_animations() -> void: func _update_third_person_animations() -> void:
if _is_pawn(): if _is_pawn():
return return
var tp_player : Vanguard = $ThirdPerson/PlayerMesh var tp_player : Vanguard = $Smoothing/ThirdPerson/PlayerMesh
if _is_player_dead(): if _is_player_dead():
tp_player.set_ground_state(Vanguard.GroundState.GROUND_STATE_DEAD) tp_player.set_ground_state(Vanguard.GroundState.GROUND_STATE_DEAD)

View file

@ -1,15 +1,16 @@
[gd_scene load_steps=21 format=3 uid="uid://cbhx1xme0sb7k"] [gd_scene load_steps=22 format=3 uid="uid://cbhx1xme0sb7k"]
[ext_resource type="Script" path="res://entities/player/player.gd" id="1_mk68k"] [ext_resource type="Script" path="res://entities/player/player.gd" id="1_mk68k"]
[ext_resource type="PackedScene" uid="uid://drbefw6akui2v" path="res://entities/player/assets/vanguard.tscn" id="2_beyex"] [ext_resource type="PackedScene" uid="uid://drbefw6akui2v" path="res://entities/player/assets/vanguard.tscn" id="2_beyex"]
[ext_resource type="Shape3D" uid="uid://cb8esdlnottdn" path="res://entities/player/collision_shape.tres" id="2_vjqny"] [ext_resource type="Shape3D" uid="uid://cb8esdlnottdn" path="res://entities/player/collision_shape.tres" id="2_vjqny"]
[ext_resource type="PackedScene" uid="uid://bcv81ku26xo" path="res://interfaces/hud/hud.tscn" id="3_ccety"] [ext_resource type="PackedScene" uid="uid://bcv81ku26xo" path="res://interfaces/hud/hud.tscn" id="3_ccety"]
[ext_resource type="PackedScene" uid="uid://c8co0qa2omjmh" path="res://entities/weapons/space_gun/space_gun.tscn" id="4_ehwwq"] [ext_resource type="PackedScene" uid="uid://c8co0qa2omjmh" path="res://entities/weapons/space_gun/space_gun.tscn" id="4_6jh57"]
[ext_resource type="PackedScene" uid="uid://dn1tcakam5egs" path="res://entities/weapons/space_gun/projectile.tscn" id="5_2xh36"]
[ext_resource type="PackedScene" uid="uid://bof3mg7wgxrmn" path="res://components/health_component.tscn" id="5_t6i6e"] [ext_resource type="PackedScene" uid="uid://bof3mg7wgxrmn" path="res://components/health_component.tscn" id="5_t6i6e"]
[ext_resource type="PackedScene" uid="uid://dn1tcakam5egs" path="res://entities/weapons/space_gun/projectile.tscn" id="5_w56pa"]
[ext_resource type="Script" path="res://entities/player/player_input.gd" id="6_ymcrr"] [ext_resource type="Script" path="res://entities/player/player_input.gd" id="6_ymcrr"]
[ext_resource type="PackedScene" uid="uid://dsysi2rd3bu76" path="res://interfaces/hud/iff.tscn" id="7_8hc80"] [ext_resource type="PackedScene" uid="uid://dsysi2rd3bu76" path="res://interfaces/hud/iff.tscn" id="7_8hc80"]
[ext_resource type="PackedScene" uid="uid://2t8ql8pkxv6c" path="res://components/flag_carry_component.tscn" id="7_e7s1a"] [ext_resource type="PackedScene" uid="uid://2t8ql8pkxv6c" path="res://components/flag_carry_component.tscn" id="7_e7s1a"]
[ext_resource type="Script" path="res://addons/smoothing/smoothing.gd" id="11_k330l"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_clur0"] [sub_resource type="PhysicsMaterial" id="PhysicsMaterial_clur0"]
resource_local_to_scene = true resource_local_to_scene = true
@ -27,7 +28,7 @@ length = 0.001
tracks/0/type = "value" tracks/0/type = "value"
tracks/0/imported = false tracks/0/imported = false
tracks/0/enabled = true tracks/0/enabled = true
tracks/0/path = NodePath("SpringArm3D/Inventory/SpaceGun:position") tracks/0/path = NodePath("Smoothing/SpringArm3D/Inventory/SpaceGun:position")
tracks/0/interp = 1 tracks/0/interp = 1
tracks/0/loop_wrap = true tracks/0/loop_wrap = true
tracks/0/keys = { tracks/0/keys = {
@ -39,7 +40,7 @@ tracks/0/keys = {
tracks/1/type = "value" tracks/1/type = "value"
tracks/1/imported = false tracks/1/imported = false
tracks/1/enabled = true tracks/1/enabled = true
tracks/1/path = NodePath("SpringArm3D/Inventory/SpaceGun:rotation") tracks/1/path = NodePath("Smoothing/SpringArm3D/Inventory/SpaceGun:rotation")
tracks/1/interp = 1 tracks/1/interp = 1
tracks/1/loop_wrap = true tracks/1/loop_wrap = true
tracks/1/keys = { tracks/1/keys = {
@ -51,7 +52,7 @@ tracks/1/keys = {
tracks/2/type = "value" tracks/2/type = "value"
tracks/2/imported = false tracks/2/imported = false
tracks/2/enabled = true tracks/2/enabled = true
tracks/2/path = NodePath("SpringArm3D:position") tracks/2/path = NodePath("Smoothing/SpringArm3D:position")
tracks/2/interp = 1 tracks/2/interp = 1
tracks/2/loop_wrap = true tracks/2/loop_wrap = true
tracks/2/keys = { tracks/2/keys = {
@ -63,7 +64,7 @@ tracks/2/keys = {
tracks/3/type = "value" tracks/3/type = "value"
tracks/3/imported = false tracks/3/imported = false
tracks/3/enabled = true tracks/3/enabled = true
tracks/3/path = NodePath("SpringArm3D:rotation") tracks/3/path = NodePath("Smoothing/SpringArm3D:rotation")
tracks/3/interp = 1 tracks/3/interp = 1
tracks/3/loop_wrap = true tracks/3/loop_wrap = true
tracks/3/keys = { tracks/3/keys = {
@ -78,7 +79,7 @@ resource_name = "death"
tracks/0/type = "value" tracks/0/type = "value"
tracks/0/imported = false tracks/0/imported = false
tracks/0/enabled = true tracks/0/enabled = true
tracks/0/path = NodePath("SpringArm3D:position") tracks/0/path = NodePath("Smoothing/SpringArm3D:position")
tracks/0/interp = 1 tracks/0/interp = 1
tracks/0/loop_wrap = true tracks/0/loop_wrap = true
tracks/0/keys = { tracks/0/keys = {
@ -90,7 +91,7 @@ tracks/0/keys = {
tracks/1/type = "value" tracks/1/type = "value"
tracks/1/imported = false tracks/1/imported = false
tracks/1/enabled = true tracks/1/enabled = true
tracks/1/path = NodePath("SpringArm3D:rotation") tracks/1/path = NodePath("Smoothing/SpringArm3D:rotation")
tracks/1/interp = 1 tracks/1/interp = 1
tracks/1/loop_wrap = true tracks/1/loop_wrap = true
tracks/1/keys = { tracks/1/keys = {
@ -107,7 +108,7 @@ loop_mode = 1
tracks/0/type = "value" tracks/0/type = "value"
tracks/0/imported = false tracks/0/imported = false
tracks/0/enabled = true tracks/0/enabled = true
tracks/0/path = NodePath("SpringArm3D/Inventory/SpaceGun:position") tracks/0/path = NodePath("Smoothing/SpringArm3D/Inventory/SpaceGun:position")
tracks/0/interp = 1 tracks/0/interp = 1
tracks/0/loop_wrap = true tracks/0/loop_wrap = true
tracks/0/keys = { tracks/0/keys = {
@ -119,7 +120,7 @@ tracks/0/keys = {
tracks/1/type = "value" tracks/1/type = "value"
tracks/1/imported = false tracks/1/imported = false
tracks/1/enabled = true tracks/1/enabled = true
tracks/1/path = NodePath("SpringArm3D/Inventory/SpaceGun:rotation") tracks/1/path = NodePath("Smoothing/SpringArm3D/Inventory/SpaceGun:rotation")
tracks/1/interp = 1 tracks/1/interp = 1
tracks/1/loop_wrap = true tracks/1/loop_wrap = true
tracks/1/keys = { tracks/1/keys = {
@ -134,7 +135,7 @@ resource_name = "shoot"
tracks/0/type = "value" tracks/0/type = "value"
tracks/0/imported = false tracks/0/imported = false
tracks/0/enabled = true tracks/0/enabled = true
tracks/0/path = NodePath("SpringArm3D/Inventory/SpaceGun:position") tracks/0/path = NodePath("Smoothing/SpringArm3D/Inventory/SpaceGun:position")
tracks/0/interp = 1 tracks/0/interp = 1
tracks/0/loop_wrap = true tracks/0/loop_wrap = true
tracks/0/keys = { tracks/0/keys = {
@ -146,7 +147,7 @@ tracks/0/keys = {
tracks/1/type = "value" tracks/1/type = "value"
tracks/1/imported = false tracks/1/imported = false
tracks/1/enabled = true tracks/1/enabled = true
tracks/1/path = NodePath("SpringArm3D/Inventory/SpaceGun:rotation") tracks/1/path = NodePath("Smoothing/SpringArm3D/Inventory/SpaceGun:rotation")
tracks/1/interp = 1 tracks/1/interp = 1
tracks/1/loop_wrap = true tracks/1/loop_wrap = true
tracks/1/keys = { tracks/1/keys = {
@ -205,9 +206,10 @@ axis_lock_angular_y = true
axis_lock_angular_z = true axis_lock_angular_z = true
mass = 75.0 mass = 75.0
physics_material_override = SubResource("PhysicsMaterial_clur0") physics_material_override = SubResource("PhysicsMaterial_clur0")
can_sleep = false
continuous_cd = true continuous_cd = true
script = ExtResource("1_mk68k") script = ExtResource("1_mk68k")
iff = NodePath("ThirdPerson/IFFAttachment/IFF") iff = NodePath("Smoothing/ThirdPerson/IFF")
jump_height = 1.5 jump_height = 1.5
[node name="MeshInstance3D" type="MeshInstance3D" parent="."] [node name="MeshInstance3D" type="MeshInstance3D" parent="."]
@ -234,49 +236,15 @@ shape = ExtResource("2_vjqny")
[node name="HUD" parent="." instance=ExtResource("3_ccety")] [node name="HUD" parent="." instance=ExtResource("3_ccety")]
[node name="SpringArm3D" type="SpringArm3D" parent="."]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
spring_length = 0.0
[node name="Camera3D" type="Camera3D" parent="SpringArm3D"]
fov = 100.0
near = 0.1
[node name="Inventory" type="Node3D" parent="SpringArm3D"]
[node name="SpaceGun" parent="SpringArm3D/Inventory" instance=ExtResource("4_ehwwq")]
transform = Transform3D(-1, 0, 2.53518e-06, 0, 1, 0, -2.53518e-06, 0, -1, 0.244668, -0.229311, -0.30332)
PROJECTILE = ExtResource("5_w56pa")
[node name="SpineIKTarget" type="Node3D" parent="SpringArm3D"]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
[node name="FlagCarryAttachment" type="Node3D" parent="SpringArm3D"]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, -0.620994, -0.287925)
[node name="HealthComponent" parent="." instance=ExtResource("5_t6i6e")] [node name="HealthComponent" parent="." instance=ExtResource("5_t6i6e")]
[node name="CollisionShape3D" type="CollisionShape3D" parent="HealthComponent"] [node name="CollisionShape3D" type="CollisionShape3D" parent="HealthComponent"]
shape = ExtResource("2_vjqny") shape = ExtResource("2_vjqny")
[node name="FlagCarryComponent" parent="." node_paths=PackedStringArray("attachment", "sensor") instance=ExtResource("7_e7s1a")] [node name="FlagCarryComponent" parent="." node_paths=PackedStringArray("attachment", "sensor") instance=ExtResource("7_e7s1a")]
attachment = NodePath("../SpringArm3D/FlagCarryAttachment") attachment = NodePath("../Smoothing/SpringArm3D/FlagCarryAttachment")
sensor = NodePath("../Sensor") sensor = NodePath("../Sensor")
[node name="ThirdPerson" type="Node3D" parent="."]
[node name="IFFAttachment" type="Marker3D" parent="ThirdPerson"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.1, 0)
[node name="IFF" parent="ThirdPerson/IFFAttachment" node_paths=PackedStringArray("player", "attach_point") instance=ExtResource("7_8hc80")]
player = NodePath("../../..")
attach_point = NodePath("..")
[node name="PlayerMesh" parent="ThirdPerson" node_paths=PackedStringArray("spine_ik_target_attachment") instance=ExtResource("2_beyex")]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
spine_ik_target_attachment = NodePath("../../SpringArm3D/SpineIKTarget")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."] [node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = { libraries = {
"": SubResource("AnimationLibrary_hg307") "": SubResource("AnimationLibrary_hg307")
@ -291,3 +259,42 @@ replication_config = SubResource("SceneReplicationConfig_rqdp6")
root_path = NodePath(".") root_path = NodePath(".")
replication_config = SubResource("SceneReplicationConfig_5j4ew") replication_config = SubResource("SceneReplicationConfig_5j4ew")
script = ExtResource("6_ymcrr") script = ExtResource("6_ymcrr")
[node name="Smoothing" type="Node3D" parent="."]
script = ExtResource("11_k330l")
target = NodePath("..")
flags = 3
[node name="SpringArm3D" type="SpringArm3D" parent="Smoothing"]
unique_name_in_owner = true
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0)
spring_length = 0.0
[node name="Camera3D" type="Camera3D" parent="Smoothing/SpringArm3D"]
fov = 100.0
near = 0.1
[node name="Inventory" type="Node3D" parent="Smoothing/SpringArm3D"]
[node name="SpaceGun" parent="Smoothing/SpringArm3D/Inventory" instance=ExtResource("4_6jh57")]
transform = Transform3D(-1, 0, 2.53518e-06, 0, 1, 0, -2.53518e-06, 0, -1, 0.244668, -0.229311, -0.30332)
PROJECTILE = ExtResource("5_2xh36")
[node name="SpineIKTarget" type="Node3D" parent="Smoothing/SpringArm3D"]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
[node name="FlagCarryAttachment" type="Node3D" parent="Smoothing/SpringArm3D"]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, -0.620994, -0.287925)
[node name="ThirdPerson" type="Node3D" parent="Smoothing"]
[node name="PlayerMesh" parent="Smoothing/ThirdPerson" node_paths=PackedStringArray("spine_ik_target_attachment") instance=ExtResource("2_beyex")]
transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0)
spine_ik_target_attachment = NodePath("../../SpringArm3D/SpineIKTarget")
[node name="IFFAttachment" type="Marker3D" parent="Smoothing/ThirdPerson"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.27457, 0)
[node name="IFF" parent="Smoothing/ThirdPerson" node_paths=PackedStringArray("player", "attach_point") instance=ExtResource("7_8hc80")]
player = NodePath("../../..")
attach_point = NodePath("../IFFAttachment")

View file

@ -47,7 +47,7 @@ movie_writer/disable_vsync=true
[editor_plugins] [editor_plugins]
enabled=PackedStringArray("res://addons/gut/plugin.cfg", "res://addons/terrain_3d/plugin.cfg") enabled=PackedStringArray("res://addons/gut/plugin.cfg", "res://addons/smoothing/plugin.cfg", "res://addons/terrain_3d/plugin.cfg")
[input] [input]