mirror of
https://port.numenaute.org/aleajactaest/bazar_alea.git
synced 2024-11-26 00:56:21 +00:00
Merge branch 'player'
This commit is contained in:
commit
cb5a30e82f
49 changed files with 9908 additions and 30 deletions
|
@ -52,7 +52,7 @@ When you're ready to make this README your own, just edit this file and use the
|
||||||
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
|
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
|
||||||
|
|
||||||
## Name
|
## Name
|
||||||
Choose a self-explaining name for your project.
|
Bazard d'Alea
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
|
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
|
||||||
|
@ -76,6 +76,9 @@ Tell people where they can go to for help. It can be any combination of an issue
|
||||||
If you have ideas for releases in the future, it is a good idea to list them in the README.
|
If you have ideas for releases in the future, it is a good idea to list them in the README.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
Based on code: ywmaa (https://github.com/ywmaa/Advanced-Movement-System-Godot.git)
|
||||||
|
|
||||||
State if you are open to contributions and what your requirements are for accepting them.
|
State if you are open to contributions and what your requirements are for accepting them.
|
||||||
|
|
||||||
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
|
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
|
||||||
|
@ -83,7 +86,9 @@ For people who want to make changes to your project, it's helpful to have some d
|
||||||
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
|
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
|
||||||
|
|
||||||
## Authors and acknowledgment
|
## Authors and acknowledgment
|
||||||
Show your appreciation to those who have contributed to the project.
|
|
||||||
|
AleaJactaEst
|
||||||
|
ywmaa (We use code provide by https://github.com/ywmaa/Advanced-Movement-System-Godot.git)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
For open source projects, say how it is licensed.
|
For open source projects, say how it is licensed.
|
||||||
|
|
16
client/defaults/default_env.tres
Normal file
16
client/defaults/default_env.tres
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[gd_resource type="Environment" load_steps=3 format=3 uid="uid://dxix86rh7notp"]
|
||||||
|
|
||||||
|
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_at5cn"]
|
||||||
|
|
||||||
|
[sub_resource type="Sky" id="Sky_vfhuk"]
|
||||||
|
sky_material = SubResource("ProceduralSkyMaterial_at5cn")
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
background_mode = 2
|
||||||
|
sky = SubResource("Sky_vfhuk")
|
||||||
|
tonemap_mode = 3
|
||||||
|
fog_enabled = true
|
||||||
|
fog_light_color = Color(0.27451, 0.423529, 0.607843, 1)
|
||||||
|
fog_density = 0.004
|
||||||
|
volumetric_fog_enabled = true
|
||||||
|
volumetric_fog_density = 0.007
|
16
client/player/AnimationTree.gd
Normal file
16
client/player/AnimationTree.gd
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
extends AnimationTree
|
||||||
|
class_name AnimBlend
|
||||||
|
#@onready @export var movement_script : CharacterMovementComponent
|
||||||
|
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
pass # Replace with function body.
|
||||||
|
|
||||||
|
|
||||||
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
func _process(delta):
|
||||||
|
#if !movement_script:
|
||||||
|
# return
|
||||||
|
pass
|
||||||
|
|
BIN
client/player/Animations/CrouchIdle.res
Normal file
BIN
client/player/Animations/CrouchIdle.res
Normal file
Binary file not shown.
BIN
client/player/Animations/CrouchWalkingForward.res
Normal file
BIN
client/player/Animations/CrouchWalkingForward.res
Normal file
Binary file not shown.
BIN
client/player/Animations/Falling.res
Normal file
BIN
client/player/Animations/Falling.res
Normal file
Binary file not shown.
BIN
client/player/Animations/FallingStart.res
Normal file
BIN
client/player/Animations/FallingStart.res
Normal file
Binary file not shown.
BIN
client/player/Animations/FallingToRoll.res
Normal file
BIN
client/player/Animations/FallingToRoll.res
Normal file
Binary file not shown.
BIN
client/player/Animations/HardFalling.res
Normal file
BIN
client/player/Animations/HardFalling.res
Normal file
Binary file not shown.
BIN
client/player/Animations/Idle.res
Normal file
BIN
client/player/Animations/Idle.res
Normal file
Binary file not shown.
BIN
client/player/Animations/Idle1.res
Normal file
BIN
client/player/Animations/Idle1.res
Normal file
Binary file not shown.
BIN
client/player/Animations/Idle2.res
Normal file
BIN
client/player/Animations/Idle2.res
Normal file
Binary file not shown.
BIN
client/player/Animations/JogForward.res
Normal file
BIN
client/player/Animations/JogForward.res
Normal file
Binary file not shown.
BIN
client/player/Animations/Jogbackward.res
Normal file
BIN
client/player/Animations/Jogbackward.res
Normal file
Binary file not shown.
BIN
client/player/Animations/Kick.res
Normal file
BIN
client/player/Animations/Kick.res
Normal file
Binary file not shown.
BIN
client/player/Animations/Run.res
Normal file
BIN
client/player/Animations/Run.res
Normal file
Binary file not shown.
BIN
client/player/Animations/RunToStop.res
Normal file
BIN
client/player/Animations/RunToStop.res
Normal file
Binary file not shown.
BIN
client/player/Animations/TPose.res
Normal file
BIN
client/player/Animations/TPose.res
Normal file
Binary file not shown.
BIN
client/player/Animations/TurnLeft.res
Normal file
BIN
client/player/Animations/TurnLeft.res
Normal file
Binary file not shown.
BIN
client/player/Animations/TurnRight.res
Normal file
BIN
client/player/Animations/TurnRight.res
Normal file
Binary file not shown.
BIN
client/player/Animations/Walk.res
Normal file
BIN
client/player/Animations/Walk.res
Normal file
Binary file not shown.
BIN
client/player/Animations/WalkingBackward.res
Normal file
BIN
client/player/Animations/WalkingBackward.res
Normal file
Binary file not shown.
23
client/player/Attributes/GameAttribute.gd
Normal file
23
client/player/Attributes/GameAttribute.gd
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
extends Node
|
||||||
|
class_name GameAttribute
|
||||||
|
|
||||||
|
|
||||||
|
@onready var attributes_manager : AttributesManager = get_parent()
|
||||||
|
|
||||||
|
@export_category("Attribute")
|
||||||
|
## Is the attribute name
|
||||||
|
@export var attribute_name : String
|
||||||
|
## Is the attribute minimum value
|
||||||
|
@export var minimum_value : float
|
||||||
|
## Is the attribute maximum value
|
||||||
|
@export var maximum_value : float
|
||||||
|
## Is the attribute initial value
|
||||||
|
@export var current_value : float :
|
||||||
|
set(v):
|
||||||
|
set_attribute(current_value, v)
|
||||||
|
current_value = v
|
||||||
|
var can_use:bool = true
|
||||||
|
|
||||||
|
|
||||||
|
func set_attribute(prev_v, current_v):
|
||||||
|
pass
|
17
client/player/Attributes/HealthAttribute.gd
Normal file
17
client/player/Attributes/HealthAttribute.gd
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
extends GameAttribute
|
||||||
|
class_name HealthAttribute
|
||||||
|
|
||||||
|
@export_category("Visual Bar")
|
||||||
|
@export var health_bar : ProgressBar
|
||||||
|
|
||||||
|
func set_attribute(prev_v, current_v):
|
||||||
|
if !attributes_manager:
|
||||||
|
return
|
||||||
|
if current_v <= 0.0: # and not dead
|
||||||
|
pass #death
|
||||||
|
|
||||||
|
|
||||||
|
func _process(delta):
|
||||||
|
if health_bar:
|
||||||
|
health_bar.max_value = maximum_value
|
||||||
|
health_bar.value = current_value
|
70
client/player/Attributes/StaminaAttribute.gd
Normal file
70
client/player/Attributes/StaminaAttribute.gd
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
extends GameAttribute
|
||||||
|
class_name StaminaAttribute
|
||||||
|
|
||||||
|
@export_category("Energy")
|
||||||
|
var regenerating_cooldown : bool = false
|
||||||
|
func enable_normal_cooldown_gen():
|
||||||
|
await get_tree().create_timer(cooldown_regen_wait_time_no_exaust).timeout
|
||||||
|
if !cooldown_exausted and !being_used:
|
||||||
|
regenerating_cooldown = true
|
||||||
|
func enable_exaust_cooldown_gen():
|
||||||
|
await get_tree().create_timer(cooldown_regen_wait_time_exaust).timeout
|
||||||
|
if !being_used:
|
||||||
|
regenerating_cooldown = true
|
||||||
|
func regenerate_cooldown(delta):
|
||||||
|
if regenerating_cooldown:
|
||||||
|
|
||||||
|
current_value = clampf(current_value+(cooldown_regeneration_speed*delta),minimum_value,maximum_value)
|
||||||
|
if cooldown_exausted and current_value == maximum_value:
|
||||||
|
cooldown_exausted = false
|
||||||
|
if cooldown_fill_sound:
|
||||||
|
cooldown_fill_sound.play()
|
||||||
|
return
|
||||||
|
if current_value == maximum_value:
|
||||||
|
regenerating_cooldown = false
|
||||||
|
if cooldown_fill_sound:
|
||||||
|
cooldown_fill_sound.play()
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
## cooldown regeneration value in each second
|
||||||
|
@export var cooldown_regeneration_speed : float = 10.0
|
||||||
|
## cooldown wait time in seconds berfore starting to regenerate
|
||||||
|
@export var cooldown_regen_wait_time_no_exaust : float = 2.0
|
||||||
|
## cooldown wait time in case of exausted in seconds berfore starting to regenerate
|
||||||
|
@export var cooldown_regen_wait_time_exaust : float = 4.0
|
||||||
|
var cooldown_exausted : bool = false:
|
||||||
|
set(value):
|
||||||
|
cooldown_exausted = value
|
||||||
|
if cooldown_exausted:
|
||||||
|
if cooldown_exaust_sound:
|
||||||
|
cooldown_exaust_sound.play()
|
||||||
|
|
||||||
|
@export_category("Visual Bar")
|
||||||
|
@export var cooldown_bar : ProgressBar
|
||||||
|
@export var cooldown_unfill_normal_color : Color
|
||||||
|
@export var cooldown_unfill_exaust_color : Color
|
||||||
|
|
||||||
|
@export_category("Sound Effects")
|
||||||
|
@export var cooldown_exaust_sound : AudioStreamPlayer3D
|
||||||
|
@export var cooldown_fill_sound : AudioStreamPlayer3D
|
||||||
|
var being_used : bool = false
|
||||||
|
func set_attribute(prev_v, current_v):
|
||||||
|
if current_v < prev_v:
|
||||||
|
if current_v <= 1.0:
|
||||||
|
cooldown_exausted = true
|
||||||
|
regenerating_cooldown = false
|
||||||
|
if current_v < maximum_value:
|
||||||
|
if cooldown_exausted:
|
||||||
|
enable_exaust_cooldown_gen()
|
||||||
|
else:
|
||||||
|
enable_normal_cooldown_gen()
|
||||||
|
func _process(delta):
|
||||||
|
can_use = !cooldown_exausted
|
||||||
|
|
||||||
|
regenerate_cooldown(delta)
|
||||||
|
if cooldown_bar:
|
||||||
|
cooldown_bar.max_value = maximum_value
|
||||||
|
cooldown_bar.value = current_value
|
||||||
|
cooldown_bar.get_theme_stylebox("background").bg_color = cooldown_unfill_normal_color if !cooldown_exausted else cooldown_unfill_exaust_color
|
||||||
|
|
12
client/player/AttributesManager.gd
Normal file
12
client/player/AttributesManager.gd
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
extends Node
|
||||||
|
class_name AttributesManager
|
||||||
|
|
||||||
|
|
||||||
|
@export var character : Node
|
||||||
|
var attributes : Dictionary
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
for child in get_children():
|
||||||
|
if !(child is GameAttribute):
|
||||||
|
assert("Only GameAttribute childs are allowed")
|
||||||
|
attributes[child.attribute_name] = child
|
132
client/player/CameraComponent.gd
Normal file
132
client/player/CameraComponent.gd
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
extends Node
|
||||||
|
class_name CameraComponent
|
||||||
|
## Script used to control the camera for the player
|
||||||
|
|
||||||
|
@export var networking : PlayerNetworkingComponent
|
||||||
|
#####################################
|
||||||
|
#Refrences
|
||||||
|
@export var SpringArm : SpringArm3D
|
||||||
|
@export var Camera : Camera3D
|
||||||
|
@export var PlayerRef : CharacterMovementComponent
|
||||||
|
@onready var HObject = SpringArm
|
||||||
|
@onready var VObject = SpringArm
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
var CameraHOffset := 0.0
|
||||||
|
@export var view_angle : Global.view_angle = Global.view_angle.right_shoulder:
|
||||||
|
get: return view_angle
|
||||||
|
set(Newview_angle):
|
||||||
|
# if view_mode == Global.view_mode.first_person:
|
||||||
|
# return
|
||||||
|
view_angle = Newview_angle
|
||||||
|
if Camera:
|
||||||
|
match Newview_angle:
|
||||||
|
Global.view_angle.right_shoulder:
|
||||||
|
CameraHOffset = 0.45
|
||||||
|
update_camera_offset()
|
||||||
|
Global.view_angle.left_shoulder:
|
||||||
|
CameraHOffset = -0.45
|
||||||
|
update_camera_offset()
|
||||||
|
Global.view_angle.head:
|
||||||
|
CameraHOffset = 0.0
|
||||||
|
update_camera_offset()
|
||||||
|
|
||||||
|
|
||||||
|
@export var view_mode : Global.view_mode = Global.view_mode.third_person :
|
||||||
|
get: return view_mode
|
||||||
|
set(Newview_mode):
|
||||||
|
view_mode = Newview_mode
|
||||||
|
if VObject:
|
||||||
|
VObject.rotation.x = 0.0
|
||||||
|
if SpringArm:
|
||||||
|
match view_mode:
|
||||||
|
Global.view_mode.first_person:
|
||||||
|
view_angle = Global.view_angle.head
|
||||||
|
PlayerRef.rotation_mode = Global.rotation_mode.looking_direction
|
||||||
|
SpringArm.spring_length = -0.4
|
||||||
|
VObject = Camera
|
||||||
|
Global.view_mode.third_person:
|
||||||
|
SpringArm.spring_length = 1.75
|
||||||
|
VObject = SpringArm
|
||||||
|
|
||||||
|
|
||||||
|
var camera_h : float = 0
|
||||||
|
var camera_v : float = 0
|
||||||
|
@export var camera_vertical_min : float = -90
|
||||||
|
@export var camera_vertical_max : float = 90
|
||||||
|
|
||||||
|
## Assign a [camera_values] resource to it and change its values to tweak camera settings
|
||||||
|
@export var camera_settings : CameraValues = CameraValues.new()
|
||||||
|
@export var first_person_camera_bone : BoneAttachment3D
|
||||||
|
var current_fov : float = 90.0
|
||||||
|
var acceleration_h = 10
|
||||||
|
var acceleration_v = 10
|
||||||
|
|
||||||
|
var spring_arm_position_relative_to_player : Vector3
|
||||||
|
func _ready():
|
||||||
|
spring_arm_position_relative_to_player = SpringArm.position
|
||||||
|
SpringArm.top_level = true
|
||||||
|
|
||||||
|
func _physics_process(delta):
|
||||||
|
if camera_settings.camera_change_fov_on_speed and PlayerRef.actual_velocity.length() > camera_settings.camera_fov_change_starting_speed:
|
||||||
|
smooth_fov(current_fov + clampf((PlayerRef.actual_velocity.length()-camera_settings.camera_fov_change_starting_speed)*(camera_settings.camera_max_fov_change/10.0),0,camera_settings.camera_max_fov_change))
|
||||||
|
|
||||||
|
SpringArm.position = SpringArm.position.lerp((get_parent().global_position + spring_arm_position_relative_to_player) if view_mode == Global.view_mode.third_person else first_person_camera_bone.global_position,(1/camera_settings.camera_inertia) if view_mode == Global.view_mode.third_person else 1.0)
|
||||||
|
|
||||||
|
camera_v = clamp(camera_v,deg_to_rad(camera_vertical_min),deg_to_rad(camera_vertical_max))
|
||||||
|
HObject.rotation.y = lerp(HObject.rotation.y,camera_h,delta * acceleration_h)
|
||||||
|
VObject.rotation.x = lerp(VObject.rotation.x,camera_v,delta * acceleration_v)
|
||||||
|
|
||||||
|
match PlayerRef.rotation_mode:
|
||||||
|
Global.rotation_mode.aiming:
|
||||||
|
if PlayerRef.gait == Global.gait.sprinting: # character can't sprint while aiming
|
||||||
|
PlayerRef.gait = Global.gait.running
|
||||||
|
smooth_fov(60.0)
|
||||||
|
Global.rotation_mode.velocity_direction:
|
||||||
|
smooth_fov(90.0)
|
||||||
|
Global.rotation_mode.looking_direction:
|
||||||
|
smooth_fov(90.0)
|
||||||
|
|
||||||
|
|
||||||
|
func update_camera_offset():
|
||||||
|
var tween := create_tween()
|
||||||
|
tween.tween_property(Camera,"h_offset",CameraHOffset,0.5).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_EXPO)
|
||||||
|
|
||||||
|
var changing_view := false
|
||||||
|
func smooth_fov(_current_fov:float):
|
||||||
|
current_fov = _current_fov
|
||||||
|
if changing_view:
|
||||||
|
return
|
||||||
|
changing_view=true
|
||||||
|
var tween := create_tween()
|
||||||
|
tween.tween_property(Camera,"fov",current_fov,0.1)
|
||||||
|
tween.tween_callback(func(): changing_view=false)
|
||||||
|
|
||||||
|
|
||||||
|
func smooth_camera_transition(pos:Vector3, look_at:Vector3, duration:float = 1.0 ,ease:Tween.EaseType = Tween.EASE_IN_OUT, trans:Tween.TransitionType = Tween.TRANS_LINEAR):
|
||||||
|
# Camera.global_position = Camera.to_global(Camera.global_position)
|
||||||
|
Camera.top_level = true
|
||||||
|
var tween := create_tween()
|
||||||
|
tween.set_parallel()
|
||||||
|
tween.tween_property(Camera,"position",pos,duration).set_ease(ease).set_trans(trans)
|
||||||
|
tween.tween_method(func(arr:Array): Camera.look_at_from_position(arr[0],arr[1]),[Camera.position,look_at],[pos,look_at],duration).set_ease(ease).set_trans(trans)
|
||||||
|
|
||||||
|
var reseting : bool = false
|
||||||
|
func reset_camera_transition(smooth_transition: bool = true):
|
||||||
|
if Camera.top_level == false:
|
||||||
|
return
|
||||||
|
if smooth_transition:
|
||||||
|
|
||||||
|
if reseting == true:
|
||||||
|
return
|
||||||
|
reseting = true
|
||||||
|
Camera.top_level = false
|
||||||
|
var tween := create_tween()
|
||||||
|
tween.set_parallel()
|
||||||
|
tween.tween_property(Camera,"position",Vector3(0,0,SpringArm.spring_length),1.0)
|
||||||
|
tween.tween_property(Camera,"rotation",Vector3.ZERO,1.0)
|
||||||
|
tween.tween_callback(func(): reseting=false)
|
||||||
|
|
||||||
|
else:
|
||||||
|
Camera.rotation = Vector3.ZERO
|
||||||
|
Camera.top_level = false
|
20
client/player/CameraValues.gd
Normal file
20
client/player/CameraValues.gd
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
extends Resource
|
||||||
|
class_name CameraValues
|
||||||
|
|
||||||
|
|
||||||
|
@export var camera_inertia : float = 7.5
|
||||||
|
@export var camera_change_fov_on_speed : bool = false
|
||||||
|
@export var camera_max_fov_change : float = 20.0
|
||||||
|
@export var camera_fov_change_starting_speed : float = 0.0
|
||||||
|
@export var target_fov : float = 90.0
|
||||||
|
|
||||||
|
|
||||||
|
func _init(_camera_inertia: float = camera_inertia, _camera_change_fov_on_speed: bool = camera_change_fov_on_speed, _camera_max_fov_change: float = camera_max_fov_change,\
|
||||||
|
_camera_fov_change_starting_speed : float = camera_fov_change_starting_speed, _target_fov : float = target_fov):
|
||||||
|
|
||||||
|
camera_inertia = _camera_inertia
|
||||||
|
camera_change_fov_on_speed = _camera_change_fov_on_speed
|
||||||
|
camera_max_fov_change = _camera_max_fov_change
|
||||||
|
|
||||||
|
camera_fov_change_starting_speed = _camera_fov_change_starting_speed
|
||||||
|
target_fov = _target_fov
|
BIN
client/player/Character.glb
Normal file
BIN
client/player/Character.glb
Normal file
Binary file not shown.
618
client/player/CharacterMovementComponent.gd
Normal file
618
client/player/CharacterMovementComponent.gd
Normal file
|
@ -0,0 +1,618 @@
|
||||||
|
extends Node
|
||||||
|
class_name CharacterMovementComponent
|
||||||
|
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
@export_category("References")
|
||||||
|
#Refrences
|
||||||
|
|
||||||
|
## Refrence to character mesh, should be assigned to a [Node3D] that is a parent to the actual mesh (Skeleton3D)
|
||||||
|
@export var mesh_ref : Node
|
||||||
|
## Refrence to AnimationTree that uses the AnimBlend Script provided in the addon
|
||||||
|
@export var anim_ref : AnimBlend
|
||||||
|
## Refrence to character mesh which should probably be [Skeleton3D]
|
||||||
|
@export var skeleton_ref : Skeleton3D
|
||||||
|
## Refrence to the [CollisionShape3D] used for the character
|
||||||
|
@export var collision_shape_ref : CollisionShape3D
|
||||||
|
#@onready var bonker = $CollisionShape3D/HeadBonker
|
||||||
|
## Refrence to [CameraComponent] Node provided by the addon
|
||||||
|
@export var camera_root : CameraComponent
|
||||||
|
|
||||||
|
## Refrence to Tree Root, which should be either a [CharacterBody3D] or [RigidBody3D]
|
||||||
|
@export var character_node : PhysicsBody3D
|
||||||
|
## Refrence to a [RayCast3D] that should detect if character is on ground
|
||||||
|
@export var ground_check : RayCast3D
|
||||||
|
## Reference to a [Market3D]
|
||||||
|
@export var look_at_object : Marker3D
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
#Movement Settings
|
||||||
|
@export_category("Movement Data")
|
||||||
|
@export var AI := false
|
||||||
|
|
||||||
|
@export var is_flying := false
|
||||||
|
var gravity : float = ProjectSettings.get_setting("physics/3d/default_gravity")
|
||||||
|
|
||||||
|
@export var tilt := false
|
||||||
|
@export var tilt_power := 1.0
|
||||||
|
|
||||||
|
|
||||||
|
@export var ragdoll := false :
|
||||||
|
get: return ragdoll
|
||||||
|
set(Newragdoll):
|
||||||
|
ragdoll = Newragdoll
|
||||||
|
if ragdoll == true:
|
||||||
|
if skeleton_ref:
|
||||||
|
skeleton_ref.physical_bones_start_simulation()
|
||||||
|
else:
|
||||||
|
if skeleton_ref:
|
||||||
|
skeleton_ref.physical_bones_stop_simulation()
|
||||||
|
|
||||||
|
|
||||||
|
@export var jump_magnitude := 4.0
|
||||||
|
|
||||||
|
## the maximum height of stair that the character can step on
|
||||||
|
@export var max_stair_climb_height : float = 0.5
|
||||||
|
|
||||||
|
## the distance to the stair that the script will start detecting it
|
||||||
|
@export var max_close_stair_distance : float = 0.75
|
||||||
|
|
||||||
|
|
||||||
|
@export var roll_magnitude := 17.0
|
||||||
|
|
||||||
|
var default_height := 2.0
|
||||||
|
var crouch_height := 1.0
|
||||||
|
|
||||||
|
@export var crouch_switch_speed := 5.0
|
||||||
|
|
||||||
|
## the maximum angle between the camera and the character's rotation.
|
||||||
|
## when the angle between them exceeds this value, the character will rotate in place to face the camera direction.
|
||||||
|
@export var rotation_in_place_min_angle := 90.0
|
||||||
|
|
||||||
|
@export var deacceleration := 0.5
|
||||||
|
## Movement Values Settings
|
||||||
|
## you can change the values to achieve different movement settings
|
||||||
|
@export var looking_direction_standing_data : MovementValues
|
||||||
|
## Movement Values Settings
|
||||||
|
## you can change the values to achieve different movement settings
|
||||||
|
@export var looking_direction_crouch_data : MovementValues
|
||||||
|
## Movement Values Settings
|
||||||
|
## you can change the values to achieve different movement settings
|
||||||
|
@export var velocity_direction_standing_data : MovementValues
|
||||||
|
## Movement Values Settings
|
||||||
|
## you can change the values to achieve different movement settings
|
||||||
|
@export var velocity_direction_crouch_data : MovementValues
|
||||||
|
## Movement Values Settings
|
||||||
|
## you can change the values to achieve different movement settings
|
||||||
|
@export var aim_standing_data : MovementValues
|
||||||
|
## Movement Values Settings
|
||||||
|
## you can change the values to achieve different movement settings
|
||||||
|
@export var aim_crouch_data : MovementValues
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
#for logic #it is better not to change it if you don't want to break the system / only change it if you want to redesign the system
|
||||||
|
|
||||||
|
## returns the actual acceleration in [Vector3]
|
||||||
|
var actual_acceleration :Vector3
|
||||||
|
## returns the acceleration that the character should move with, aka input acceleration
|
||||||
|
var input_acceleration :Vector3
|
||||||
|
|
||||||
|
var input_direction:Vector3
|
||||||
|
|
||||||
|
var vertical_velocity :Vector3
|
||||||
|
|
||||||
|
## returns the actual velocity for the player.
|
||||||
|
## so for example if player is holding forward key, but character is stuck by wall, it will return 0 velocity.
|
||||||
|
var actual_velocity :Vector3
|
||||||
|
var velocity :Vector3
|
||||||
|
## returns the input velocity for the player.
|
||||||
|
## so for example if player is holding forward key, but character is stuck by wall, it will return the velocity that the character should move using it.
|
||||||
|
var input_velocity :Vector3
|
||||||
|
|
||||||
|
## the Y/UP rotation of the movement direction
|
||||||
|
var movement_direction : float
|
||||||
|
|
||||||
|
var tiltVector : Vector3
|
||||||
|
|
||||||
|
## is the character actually moving ? regardless of the player input.
|
||||||
|
var is_moving := false
|
||||||
|
## is the player trying to move / holding input key.
|
||||||
|
var input_is_moving := false
|
||||||
|
|
||||||
|
var head_bonked := false
|
||||||
|
|
||||||
|
var is_rotating_in_place := false
|
||||||
|
var rotation_difference_camera_mesh : float
|
||||||
|
|
||||||
|
var aim_rate_h :float
|
||||||
|
|
||||||
|
var is_moving_on_stair :bool
|
||||||
|
|
||||||
|
|
||||||
|
var current_movement_data : MovementValues = MovementValues.new()
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
#animation
|
||||||
|
var animation_is_moving_backward_relative_to_camera : bool
|
||||||
|
var animation_velocity : Vector3
|
||||||
|
|
||||||
|
#status
|
||||||
|
var movement_state = Global.movement_state.grounded
|
||||||
|
var movement_action = Global.movement_action.none
|
||||||
|
@export_category("States")
|
||||||
|
@export var rotation_mode : Global.rotation_mode = Global.rotation_mode.velocity_direction :
|
||||||
|
get: return rotation_mode
|
||||||
|
set(Newrotation_mode):
|
||||||
|
rotation_mode = Newrotation_mode
|
||||||
|
update_character_movement()
|
||||||
|
|
||||||
|
|
||||||
|
@export var gait : Global.gait = Global.gait.walking :
|
||||||
|
get: return gait
|
||||||
|
set(Newgait):
|
||||||
|
gait = Newgait
|
||||||
|
update_character_movement()
|
||||||
|
@export var stance : Global.stance = Global.stance.standing :
|
||||||
|
set(Newstance):
|
||||||
|
stance = Newstance
|
||||||
|
update_character_movement()
|
||||||
|
@export var overlay_state = Global.overlay_state
|
||||||
|
|
||||||
|
@export_category("Animations")
|
||||||
|
@export var TurnLeftAnim : String = "TurnLeft":
|
||||||
|
set(value):
|
||||||
|
TurnLeftAnim = value
|
||||||
|
update_animations()
|
||||||
|
@export var TurnRightAnim : String = "TurnRight":
|
||||||
|
set(value):
|
||||||
|
TurnRightAnim = value
|
||||||
|
update_animations()
|
||||||
|
@export var FallingAnim : String = "Falling":
|
||||||
|
set(value):
|
||||||
|
FallingAnim = value
|
||||||
|
update_animations()
|
||||||
|
@export var IdleAnim : String = "Idle":
|
||||||
|
set(value):
|
||||||
|
IdleAnim = value
|
||||||
|
update_animations()
|
||||||
|
@export var WalkForwardAnim : String = "Walk":
|
||||||
|
set(value):
|
||||||
|
WalkForwardAnim = value
|
||||||
|
update_animations()
|
||||||
|
@export var WalkBackwardAnim : String = "WalkingBackward":
|
||||||
|
set(value):
|
||||||
|
WalkBackwardAnim = value
|
||||||
|
update_animations()
|
||||||
|
@export var JogForwardAnim : String = "JogForward":
|
||||||
|
set(value):
|
||||||
|
JogForwardAnim = value
|
||||||
|
update_animations()
|
||||||
|
@export var JogBackwardAnim : String = "Jogbackward":
|
||||||
|
set(value):
|
||||||
|
JogBackwardAnim = value
|
||||||
|
update_animations()
|
||||||
|
@export var RunAnim : String = "Run":
|
||||||
|
set(value):
|
||||||
|
RunAnim = value
|
||||||
|
update_animations()
|
||||||
|
@export var StopAnim : String = "RunToStop":
|
||||||
|
set(value):
|
||||||
|
StopAnim = value
|
||||||
|
update_animations()
|
||||||
|
@export var CrouchIdleAnim : String = "CrouchIdle":
|
||||||
|
set(value):
|
||||||
|
CrouchIdleAnim = value
|
||||||
|
update_animations()
|
||||||
|
@export var CrouchWalkAnim : String = "CrouchWalkingForward":
|
||||||
|
set(value):
|
||||||
|
CrouchWalkAnim = value
|
||||||
|
update_animations()
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
|
||||||
|
func update_animations():
|
||||||
|
if !anim_ref:
|
||||||
|
return
|
||||||
|
|
||||||
|
anim_ref.tree_root.get_node("AnimTurnLeft").animation = TurnLeftAnim
|
||||||
|
anim_ref.tree_root.get_node("AnimTurnRight").animation = TurnRightAnim
|
||||||
|
anim_ref.tree_root.get_node("FallAnimation").animation = FallingAnim
|
||||||
|
#var velocity_direction : AnimationNodeBlendTree = anim_ref.tree_root.get_node("VelocityDirection")
|
||||||
|
anim_ref.tree_root.get_node("Idle").animation = IdleAnim
|
||||||
|
anim_ref.tree_root.get_node("WalkForward").animation = WalkForwardAnim
|
||||||
|
anim_ref.tree_root.get_node("WalkBackward").animation = WalkBackwardAnim
|
||||||
|
anim_ref.tree_root.get_node("JogForward").animation = JogForwardAnim
|
||||||
|
anim_ref.tree_root.get_node("JogBackward").animation = JogBackwardAnim
|
||||||
|
anim_ref.tree_root.get_node("Run").animation = RunAnim
|
||||||
|
anim_ref.tree_root.get_node("StopAnim").animation = StopAnim
|
||||||
|
anim_ref.tree_root.get_node("CrouchIdle").animation = CrouchIdleAnim
|
||||||
|
anim_ref.tree_root.get_node("CrouchWalkingForward").animation = CrouchWalkAnim
|
||||||
|
func update_character_movement():
|
||||||
|
match rotation_mode:
|
||||||
|
Global.rotation_mode.velocity_direction:
|
||||||
|
# if skeleton_ref:
|
||||||
|
# skeleton_ref.modification_stack.enabled = false
|
||||||
|
tilt = false
|
||||||
|
match stance:
|
||||||
|
Global.stance.standing:
|
||||||
|
current_movement_data = velocity_direction_standing_data
|
||||||
|
Global.stance.crouching:
|
||||||
|
current_movement_data = velocity_direction_crouch_data
|
||||||
|
|
||||||
|
|
||||||
|
Global.rotation_mode.looking_direction:
|
||||||
|
# if skeleton_ref:
|
||||||
|
# skeleton_ref.modification_stack.enabled = false #Change to true when Godot fixes the bug.
|
||||||
|
tilt = true
|
||||||
|
match stance:
|
||||||
|
Global.stance.standing:
|
||||||
|
current_movement_data = looking_direction_standing_data
|
||||||
|
Global.stance.crouching:
|
||||||
|
current_movement_data = looking_direction_crouch_data
|
||||||
|
|
||||||
|
|
||||||
|
Global.rotation_mode.aiming:
|
||||||
|
match stance:
|
||||||
|
Global.stance.standing:
|
||||||
|
current_movement_data = aim_standing_data
|
||||||
|
Global.stance.crouching:
|
||||||
|
current_movement_data = aim_crouch_data
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
var previous_aim_rate_h :float
|
||||||
|
|
||||||
|
|
||||||
|
var test_sphere : MeshInstance3D = MeshInstance3D.new()
|
||||||
|
var test_sphere1 : MeshInstance3D = MeshInstance3D.new()
|
||||||
|
func _ready():
|
||||||
|
if not character_node is CharacterBody3D and not character_node is RigidBody3D:
|
||||||
|
assert(false, "Character Node Must be either CharacterBody3D or RigidBody3D, please choose the right node from the inspector.")
|
||||||
|
|
||||||
|
if character_node is RigidBody3D:
|
||||||
|
character_node.mass = 80
|
||||||
|
character_node.continuous_cd = true
|
||||||
|
character_node.max_contacts_reported = 1
|
||||||
|
character_node.contact_monitor = true
|
||||||
|
character_node.freeze_mode = RigidBody3D.FREEZE_MODE_KINEMATIC
|
||||||
|
character_node.axis_lock_angular_x = true
|
||||||
|
character_node.axis_lock_angular_y = true
|
||||||
|
character_node.axis_lock_angular_z = true
|
||||||
|
character_node.linear_damp = deacceleration
|
||||||
|
#--------- These tests are for stride warping ---------#
|
||||||
|
# test_sphere.mesh = SphereMesh.new()
|
||||||
|
# test_sphere1.mesh = SphereMesh.new()
|
||||||
|
# test_sphere.mesh.height = 0.2
|
||||||
|
# test_sphere.mesh.radius = 0.1
|
||||||
|
# test_sphere1.mesh.height = 0.2
|
||||||
|
# test_sphere1.mesh.radius = 0.1
|
||||||
|
# test_sphere.mesh.material = StandardMaterial3D.new()
|
||||||
|
# test_sphere1.mesh.material = StandardMaterial3D.new()
|
||||||
|
# test_sphere.mesh.material.albedo_color = Color.GREEN
|
||||||
|
# test_sphere1.mesh.material.albedo_color = Color.RED
|
||||||
|
|
||||||
|
update_animations()
|
||||||
|
update_character_movement()
|
||||||
|
#var pose_warping_instance = pose_warping.new()
|
||||||
|
func _process(delta):
|
||||||
|
|
||||||
|
|
||||||
|
calc_animation_data()
|
||||||
|
var orientation_warping_condition = rotation_mode != Global.rotation_mode.velocity_direction and movement_state == Global.movement_state.grounded and movement_action == Global.movement_action.none and gait != Global.gait.sprinting and input_is_moving
|
||||||
|
#pose_warping_instance.orientation_warping( orientation_warping_condition,camera_root.HObject,animation_velocity,skeleton_ref,"Hips",["Spine","Spine1","Spine2"],0.0,delta)
|
||||||
|
|
||||||
|
func _physics_process(delta):
|
||||||
|
#Debug()
|
||||||
|
#
|
||||||
|
aim_rate_h = abs((camera_root.HObject.rotation.y - previous_aim_rate_h) / delta)
|
||||||
|
previous_aim_rate_h = camera_root.HObject.rotation.y
|
||||||
|
#
|
||||||
|
# animation_stride_warping()
|
||||||
|
|
||||||
|
match movement_state:
|
||||||
|
Global.movement_state.none:
|
||||||
|
pass
|
||||||
|
Global.movement_state.grounded:
|
||||||
|
#------------------ Rotate Character Mesh ------------------#
|
||||||
|
match movement_action:
|
||||||
|
Global.movement_action.none:
|
||||||
|
match rotation_mode:
|
||||||
|
Global.rotation_mode.velocity_direction:
|
||||||
|
if (is_moving and input_is_moving) or (actual_velocity * Vector3(1.0,0.0,1.0)).length() > 0.5:
|
||||||
|
smooth_character_rotation(actual_velocity,calc_grounded_rotation_rate(),delta)
|
||||||
|
Global.rotation_mode.looking_direction:
|
||||||
|
if (is_moving and input_is_moving) or (actual_velocity * Vector3(1.0,0.0,1.0)).length() > 0.5:
|
||||||
|
smooth_character_rotation(-camera_root.HObject.transform.basis.z if gait != Global.gait.sprinting else actual_velocity,calc_grounded_rotation_rate(),delta)
|
||||||
|
rotate_in_place_check()
|
||||||
|
Global.rotation_mode.aiming:
|
||||||
|
if (is_moving and input_is_moving) or (actual_velocity * Vector3(1.0,0.0,1.0)).length() > 0.5:
|
||||||
|
smooth_character_rotation(-camera_root.HObject.transform.basis.z,calc_grounded_rotation_rate(),delta)
|
||||||
|
rotate_in_place_check()
|
||||||
|
Global.movement_action.rolling:
|
||||||
|
if input_is_moving == true:
|
||||||
|
smooth_character_rotation(input_acceleration ,2.0,delta)
|
||||||
|
|
||||||
|
Global.movement_state.in_air:
|
||||||
|
#------------------ Rotate Character Mesh In Air ------------------#
|
||||||
|
match rotation_mode:
|
||||||
|
Global.rotation_mode.velocity_direction:
|
||||||
|
smooth_character_rotation(actual_velocity if (actual_velocity * Vector3(1.0,0.0,1.0)).length() > 1.0 else -camera_root.HObject.transform.basis.z,5.0,delta)
|
||||||
|
Global.rotation_mode.looking_direction:
|
||||||
|
smooth_character_rotation(actual_velocity if (actual_velocity * Vector3(1.0,0.0,1.0)).length() > 1.0 else -camera_root.HObject.transform.basis.z,5.0,delta)
|
||||||
|
Global.rotation_mode.aiming:
|
||||||
|
smooth_character_rotation(-camera_root.HObject.transform.basis.z ,15.0,delta)
|
||||||
|
#------------------ Mantle Check ------------------#
|
||||||
|
if input_is_moving == true:
|
||||||
|
mantle_check()
|
||||||
|
Global.movement_state.mantling:
|
||||||
|
pass
|
||||||
|
Global.movement_state.ragdoll:
|
||||||
|
pass
|
||||||
|
|
||||||
|
#------------------ Crouch ------------------#
|
||||||
|
crouch_update(delta)
|
||||||
|
|
||||||
|
#------------------ Gravity ------------------#
|
||||||
|
if is_flying == false and character_node is CharacterBody3D:
|
||||||
|
character_node.velocity.y = lerp(character_node.velocity.y,vertical_velocity.y - character_node.get_floor_normal().y,delta * gravity)
|
||||||
|
character_node.move_and_slide()
|
||||||
|
if ground_check.is_colliding() and is_flying == false:
|
||||||
|
movement_state = Global.movement_state.grounded
|
||||||
|
else:
|
||||||
|
await get_tree().create_timer(0.1).timeout #wait a moment to see if the character lands fast (this means that the character didn't fall, but stepped down a bit.)
|
||||||
|
movement_state = Global.movement_state.in_air
|
||||||
|
if character_node is CharacterBody3D:
|
||||||
|
vertical_velocity += Vector3.DOWN * gravity * delta
|
||||||
|
if character_node is CharacterBody3D and character_node.is_on_ceiling():
|
||||||
|
vertical_velocity.y = 0
|
||||||
|
#------------------ Stair climb ------------------#
|
||||||
|
#stair movement must happen after gravity so it can override in air status
|
||||||
|
stair_move()
|
||||||
|
|
||||||
|
func crouch_update(delta):
|
||||||
|
var direct_state = character_node.get_world_3d().direct_space_state
|
||||||
|
var ray_info : PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.new()
|
||||||
|
ray_info.exclude = [RID(collision_shape_ref)]
|
||||||
|
|
||||||
|
ray_info.from = collision_shape_ref.global_transform.origin + Vector3(0,collision_shape_ref.shape.height/2,0)
|
||||||
|
ray_info.to = ray_info.from + Vector3(0, 0.2, 0)
|
||||||
|
var collision = direct_state.intersect_ray(ray_info)
|
||||||
|
if collision:
|
||||||
|
head_bonked = true
|
||||||
|
else:
|
||||||
|
head_bonked = false
|
||||||
|
|
||||||
|
ground_check.position.y = -(collision_shape_ref.shape.height/2)+collision_shape_ref.position.y + 0.2#Just a small margin
|
||||||
|
|
||||||
|
if stance == Global.stance.crouching:
|
||||||
|
collision_shape_ref.shape.height -= crouch_switch_speed * delta /2
|
||||||
|
mesh_ref.transform.origin.y += crouch_switch_speed * delta /1.5
|
||||||
|
elif stance == Global.stance.standing and not head_bonked:
|
||||||
|
collision_shape_ref.shape.height += crouch_switch_speed * delta /2
|
||||||
|
mesh_ref.transform.origin.y -= crouch_switch_speed * delta /1.5
|
||||||
|
elif head_bonked:
|
||||||
|
pass
|
||||||
|
mesh_ref.transform.origin.y = clamp(mesh_ref.transform.origin.y,0.0,0.5)
|
||||||
|
collision_shape_ref.shape.height = clamp(collision_shape_ref.shape.height,crouch_height,default_height)
|
||||||
|
|
||||||
|
|
||||||
|
func stair_move():
|
||||||
|
var direct_state = character_node.get_world_3d().direct_space_state
|
||||||
|
var obs_ray_info : PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.new()
|
||||||
|
obs_ray_info.exclude = [RID(character_node)]
|
||||||
|
obs_ray_info.from = mesh_ref.global_transform.origin
|
||||||
|
if movement_direction:
|
||||||
|
obs_ray_info.to = obs_ray_info.from + Vector3(0, 0, max_close_stair_distance).rotated(Vector3.UP,movement_direction)
|
||||||
|
|
||||||
|
#this is used to know if there is obstacle
|
||||||
|
var first_collision = direct_state.intersect_ray(obs_ray_info)
|
||||||
|
if first_collision and input_is_moving:
|
||||||
|
var climb_ray_info : PhysicsRayQueryParameters3D = PhysicsRayQueryParameters3D.new()
|
||||||
|
climb_ray_info.exclude = [RID(character_node)]
|
||||||
|
climb_ray_info.from = first_collision.collider.global_position + Vector3(0, max_stair_climb_height, 0)
|
||||||
|
climb_ray_info.to = first_collision.collider.global_position
|
||||||
|
var stair_top_collision = direct_state.intersect_ray(climb_ray_info)
|
||||||
|
if stair_top_collision:
|
||||||
|
if stair_top_collision.position.y - character_node.global_position.y > 0 and stair_top_collision.position.y - character_node.global_position.y < 0.15:
|
||||||
|
movement_state = Global.movement_state.grounded
|
||||||
|
is_moving_on_stair = true
|
||||||
|
character_node.position.y += stair_top_collision.position.y - character_node.global_position.y
|
||||||
|
character_node.global_position += Vector3(0, 0, 0.01).rotated(Vector3.UP,movement_direction)
|
||||||
|
else:
|
||||||
|
await get_tree().create_timer(0.4).timeout
|
||||||
|
is_moving_on_stair = false
|
||||||
|
else:
|
||||||
|
await get_tree().create_timer(0.4).timeout
|
||||||
|
is_moving_on_stair = false
|
||||||
|
else:
|
||||||
|
await get_tree().create_timer(0.4).timeout
|
||||||
|
is_moving_on_stair = false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func smooth_character_rotation(Target:Vector3,nodelerpspeed,delta):
|
||||||
|
mesh_ref.rotation.y = lerp_angle(mesh_ref.rotation.y, atan2(Target.x,Target.z) , delta * nodelerpspeed)
|
||||||
|
|
||||||
|
|
||||||
|
func set_bone_x_rotation(skeleton,bone_name, x_rot,CharacterRootNode):
|
||||||
|
var bone = skeleton.find_bone(bone_name)
|
||||||
|
var bone_transform : Transform3D = skeleton.global_pose_to_local_pose(bone,skeleton.get_bone_global_pose_no_override(bone))
|
||||||
|
var rotate_amount = x_rot
|
||||||
|
bone_transform = bone_transform.rotated(Vector3(1,0,0), rotate_amount)
|
||||||
|
skeleton.set_bone_local_pose_override(bone, bone_transform,1.0,true)
|
||||||
|
|
||||||
|
|
||||||
|
var prev :Transform3D
|
||||||
|
var current :Transform3D
|
||||||
|
var anim_speed
|
||||||
|
func animation_stride_warping(): #this is currently being worked on and tested, so I don't reccomend using it.
|
||||||
|
|
||||||
|
add_sibling(test_sphere)
|
||||||
|
add_sibling(test_sphere1)
|
||||||
|
|
||||||
|
skeleton_ref.clear_bones_local_pose_override()
|
||||||
|
var distance_in_each_frame = (actual_velocity*Vector3(1,0,1)).rotated(Vector3.UP,mesh_ref.transform.basis.get_euler().y).length()
|
||||||
|
var hips = skeleton_ref.find_bone("Hips")
|
||||||
|
var hips_transform = skeleton_ref.get_bone_pose(hips)
|
||||||
|
var Feet : Array = ["RightFoot","LeftFoot"]
|
||||||
|
var Thighs : Array = ["RightUpLeg","LeftUpLeg"]
|
||||||
|
|
||||||
|
var hips_distance_to_ground
|
||||||
|
var stride_scale : float = 1.0
|
||||||
|
for Foot in Feet:
|
||||||
|
#Get Bones
|
||||||
|
var bone = skeleton_ref.find_bone(Foot)
|
||||||
|
var bone_transform = skeleton_ref.get_bone_global_pose_no_override(bone)
|
||||||
|
|
||||||
|
var thigh_bone = skeleton_ref.find_bone(Thighs[Feet.find(Foot)])
|
||||||
|
var thigh_transform = skeleton_ref.get_bone_global_pose_no_override(thigh_bone)
|
||||||
|
var thigh_angle = thigh_transform.basis.get_euler().x
|
||||||
|
|
||||||
|
#Calculate
|
||||||
|
var stride_direction : Vector3 = Vector3.FORWARD # important to use in orientation warping
|
||||||
|
var stride_warping_plane_origin = Plane(character_node.get_floor_normal(),bone_transform.origin).intersects_ray(thigh_transform.origin,Vector3.DOWN)
|
||||||
|
# print(stride_warping_plane_origin)
|
||||||
|
if stride_warping_plane_origin == null:
|
||||||
|
return #Failed to get a plane origin/ we are probably in air
|
||||||
|
|
||||||
|
var scale_origin = Plane(stride_direction,stride_warping_plane_origin).project(bone_transform.origin)
|
||||||
|
var anim_speed = pow(hips_transform.origin.distance_to(bone_transform.origin),2) - pow(hips_transform.origin.y,2)
|
||||||
|
anim_speed = sqrt(abs(anim_speed))
|
||||||
|
stride_scale = clampf(distance_in_each_frame/anim_speed,0.0,2.0)
|
||||||
|
# print(test_sphere.global_position)
|
||||||
|
var foot_warped_location : Vector3 = scale_origin + (bone_transform.origin - scale_origin) * stride_scale
|
||||||
|
|
||||||
|
# Apply
|
||||||
|
|
||||||
|
#test
|
||||||
|
test_sphere.position = foot_warped_location.rotated(Vector3.UP,movement_direction)
|
||||||
|
test_sphere1.position = bone_transform.origin.rotated(Vector3.UP,movement_direction)
|
||||||
|
#I should replace this with leg IK system, and its target position is the foot_warped_location
|
||||||
|
|
||||||
|
|
||||||
|
func calc_grounded_rotation_rate():
|
||||||
|
|
||||||
|
if input_is_moving == true:
|
||||||
|
match gait:
|
||||||
|
Global.gait.walking:
|
||||||
|
return lerp(current_movement_data.idle_rotation_rate,current_movement_data.walk_rotation_rate, Global.map_range_clamped((actual_velocity * Vector3(1.0,0.0,1.0)).length(),0.0,current_movement_data.walk_speed,0.0,1.0)) * clamp(aim_rate_h,1.0,3.0)
|
||||||
|
Global.gait.running:
|
||||||
|
return lerp(current_movement_data.walk_rotation_rate,current_movement_data.run_rotation_rate, Global.map_range_clamped((actual_velocity * Vector3(1.0,0.0,1.0)).length(),current_movement_data.walk_speed,current_movement_data.run_speed,1.0,2.0)) * clamp(aim_rate_h,1.0,3.0)
|
||||||
|
Global.gait.sprinting:
|
||||||
|
return lerp(current_movement_data.run_rotation_rate,current_movement_data.sprint_rotation_rate, Global.map_range_clamped((actual_velocity * Vector3(1.0,0.0,1.0)).length(),current_movement_data.run_speed,current_movement_data.sprint_speed,2.0,3.0)) * clamp(aim_rate_h,1.0,2.5)
|
||||||
|
else:
|
||||||
|
return current_movement_data.idle_rotation_rate * clamp(aim_rate_h,1.0,3.0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func rotate_in_place_check():
|
||||||
|
is_rotating_in_place = false
|
||||||
|
if !input_is_moving:
|
||||||
|
|
||||||
|
var CameraAngle = Quaternion(Vector3(0,1,0),camera_root.HObject.rotation.y)
|
||||||
|
var MeshAngle = Quaternion(Vector3(0,1,0),mesh_ref.rotation.y)
|
||||||
|
|
||||||
|
rotation_difference_camera_mesh = rad_to_deg(MeshAngle.angle_to(CameraAngle) - PI)
|
||||||
|
if (CameraAngle.dot(MeshAngle)) > 0:
|
||||||
|
rotation_difference_camera_mesh *= -1
|
||||||
|
if floor(abs(rotation_difference_camera_mesh)) > rotation_in_place_min_angle:
|
||||||
|
is_rotating_in_place = true
|
||||||
|
smooth_character_rotation(-camera_root.HObject.transform.basis.z,calc_grounded_rotation_rate(),get_physics_process_delta_time())
|
||||||
|
|
||||||
|
|
||||||
|
func ik_look_at(position: Vector3):
|
||||||
|
if look_at_object:
|
||||||
|
look_at_object.position = position
|
||||||
|
|
||||||
|
|
||||||
|
var PrevVelocity :Vector3
|
||||||
|
|
||||||
|
## Adds input to move the character, should be called when Idle too, to execute deacceleration for CharacterBody3D or reset velocity for RigidBody3D.
|
||||||
|
## when Idle speed and direction should be passed as 0, and deacceleration passed, or leave them empty.
|
||||||
|
func add_movement_input(direction: Vector3 = Vector3.ZERO, Speed: float = 0, Acceleration: float = deacceleration if character_node is CharacterBody3D else 0) -> void:
|
||||||
|
var max_speed : float = Speed
|
||||||
|
input_direction = direction
|
||||||
|
|
||||||
|
if character_node is RigidBody3D:
|
||||||
|
if is_flying == false:
|
||||||
|
velocity.x = direction.x * Acceleration * character_node.mass * get_physics_process_delta_time()
|
||||||
|
velocity.z = direction.z * Acceleration * character_node.mass * get_physics_process_delta_time()
|
||||||
|
else:
|
||||||
|
velocity = direction * Acceleration * character_node.mass * get_physics_process_delta_time()
|
||||||
|
|
||||||
|
if is_inf(character_node.linear_velocity.length()):
|
||||||
|
character_node.linear_velocity = velocity
|
||||||
|
if character_node.linear_velocity.length() > max_speed:
|
||||||
|
velocity = direction
|
||||||
|
character_node.apply_central_impulse(velocity)
|
||||||
|
|
||||||
|
if character_node is CharacterBody3D:
|
||||||
|
if is_flying == false:
|
||||||
|
character_node.velocity.x = lerp(character_node.velocity.x,(direction*max_speed).x,Acceleration/(max_speed if max_speed != 0 else (abs(character_node.velocity.x) if character_node.velocity.x != 0 else 1.0))*get_physics_process_delta_time())
|
||||||
|
character_node.velocity.z = lerp(character_node.velocity.z,(direction*max_speed).z,Acceleration/(max_speed if max_speed != 0 else (abs(character_node.velocity.z) if character_node.velocity.z != 0 else 1.0))*get_physics_process_delta_time())
|
||||||
|
else:
|
||||||
|
character_node.velocity = character_node.velocity.lerp((direction*max_speed),Acceleration/(max_speed if max_speed != 0 else character_node.velocity.x if character_node.velocity.x != 0 else 1.0)*get_physics_process_delta_time())
|
||||||
|
character_node.move_and_slide()
|
||||||
|
# Get the velocity from the character node
|
||||||
|
var character_node_velocity = character_node.velocity if character_node is CharacterBody3D else character_node.linear_velocity
|
||||||
|
|
||||||
|
input_velocity = direction*max_speed if character_node is CharacterBody3D else velocity
|
||||||
|
movement_direction = atan2(input_velocity.x,input_velocity.z)
|
||||||
|
input_is_moving = input_velocity.length() > 0.0
|
||||||
|
input_acceleration = Acceleration * direction * (1 if max_speed != 0 else -1)
|
||||||
|
#
|
||||||
|
|
||||||
|
actual_acceleration = (character_node_velocity - PrevVelocity) / (get_physics_process_delta_time())
|
||||||
|
PrevVelocity = character_node_velocity
|
||||||
|
#
|
||||||
|
actual_velocity = character_node_velocity
|
||||||
|
#tiltCharacterMesh
|
||||||
|
if tilt == true:
|
||||||
|
var MovementDirectionRelativeToCamera = input_velocity.normalized().rotated(Vector3.UP,-camera_root.HObject.transform.basis.get_euler().y)
|
||||||
|
var IsMovingBackwardRelativeToCamera = false if input_velocity.rotated(Vector3.UP,-camera_root.HObject.transform.basis.get_euler().y).z >= -0.1 else true
|
||||||
|
if IsMovingBackwardRelativeToCamera:
|
||||||
|
MovementDirectionRelativeToCamera.x = MovementDirectionRelativeToCamera.x * -1
|
||||||
|
|
||||||
|
tiltVector = (MovementDirectionRelativeToCamera).rotated(Vector3.UP,-PI/2) / (8.0/tilt_power)
|
||||||
|
mesh_ref.rotation.x = lerp(mesh_ref.rotation.x,tiltVector.x,Acceleration * get_physics_process_delta_time())
|
||||||
|
mesh_ref.rotation.z = lerp(mesh_ref.rotation.z,tiltVector.z,Acceleration * get_physics_process_delta_time())
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
func calc_animation_data(): # it is used to modify the animation data to get the wanted animation result
|
||||||
|
animation_is_moving_backward_relative_to_camera = false if -actual_velocity.rotated(Vector3.UP,-camera_root.HObject.transform.basis.get_euler().y).z >= -0.1 else true
|
||||||
|
animation_velocity = actual_velocity
|
||||||
|
# a method to make the character' anim walk backward when moving left
|
||||||
|
# if is_equal_approx(input_velocity.normalized().rotated(Vector3.UP,-$CameraRoot.HObject.transform.basis.get_euler().y).x,-1.0):
|
||||||
|
# animation_velocity = velocity * -1
|
||||||
|
# animation_is_moving_backward_relative_to_camera = true
|
||||||
|
|
||||||
|
|
||||||
|
func mantle_check():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func jump() -> void:
|
||||||
|
if ground_check.is_colliding() and not head_bonked:
|
||||||
|
if character_node is RigidBody3D:
|
||||||
|
character_node.apply_impulse(Vector3.UP * jump_magnitude * character_node.mass)
|
||||||
|
else:
|
||||||
|
vertical_velocity = Vector3.UP * jump_magnitude
|
||||||
|
|
||||||
|
|
21
client/player/CombatSystem.gd
Normal file
21
client/player/CombatSystem.gd
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
extends Node
|
||||||
|
class_name CombatSystem
|
||||||
|
|
||||||
|
|
||||||
|
enum {NATURAL_OBJECT=0}
|
||||||
|
var team_id : int = 0
|
||||||
|
|
||||||
|
@export var attribute_map : AttributesManager
|
||||||
|
|
||||||
|
var last_attacker_id : int
|
||||||
|
|
||||||
|
@rpc("any_peer","reliable")
|
||||||
|
func damage(dmg:float,attacker_player_peer_id:int,impact_point:Vector3=Vector3.ZERO, impact_force:float=0.0, impact_bone_name:String=""):
|
||||||
|
last_attacker_id = attacker_player_peer_id
|
||||||
|
|
||||||
|
var health = attribute_map.attributes["health"].current_value
|
||||||
|
if dmg > health and health > 25.0:
|
||||||
|
attribute_map.attributes["health"].current_value = 1.0
|
||||||
|
else:
|
||||||
|
attribute_map.attributes["health"].current_value -= dmg
|
||||||
|
# print("player : " + str(multiplayer.get_unique_id()) + " health : " + str(health))
|
18
client/player/Global.gd
Normal file
18
client/player/Global.gd
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
#------------------ Player Enums ------------------#
|
||||||
|
enum gait {walking , running , sprinting}
|
||||||
|
enum movement_state {none , grounded , in_air , mantling, ragdoll}
|
||||||
|
enum movement_action {none ,low_mantle , high_mantle , rolling , getting_up}
|
||||||
|
enum overlay_state {default , rifle , pistol}
|
||||||
|
enum rotation_mode {velocity_direction , looking_direction , aiming}
|
||||||
|
enum stance {standing , crouching}
|
||||||
|
enum view_mode {third_person , first_person}
|
||||||
|
enum view_angle {right_shoulder , left_shoulder , head}
|
||||||
|
enum mantle_type {high_mantle , low_mantle, falling_catch}
|
||||||
|
enum movement_direction {forward , right, left, backward}
|
||||||
|
|
||||||
|
|
||||||
|
func map_range_clamped(value,InputMin,InputMax,OutputMin,OutputMax):
|
||||||
|
value = clamp(value,InputMin,InputMax)
|
||||||
|
return ((value - InputMin) / (InputMax - InputMin) * (OutputMax - OutputMin) + OutputMin)
|
70
client/player/LockSystem.gd
Normal file
70
client/player/LockSystem.gd
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
extends Node
|
||||||
|
class_name LockSystem
|
||||||
|
|
||||||
|
#The array of locks that are presently applied. The player can perform an action if this array is empty.
|
||||||
|
#The locks can be used for any manner of things: player movement in cutscenes, restricting dialogue choices, door open conditions etc
|
||||||
|
var _locks = []
|
||||||
|
|
||||||
|
var lock_count : int :
|
||||||
|
get:
|
||||||
|
return _locks.size()
|
||||||
|
|
||||||
|
#An event to hook into - primarily for debugging.
|
||||||
|
signal Lock_Added(lockName:String)
|
||||||
|
signal Lock_Removed(lockName:String)
|
||||||
|
|
||||||
|
#This one should only emit if is_locked would have changed.
|
||||||
|
signal Lock_Status_Changed(newStatus:bool)
|
||||||
|
|
||||||
|
#A getter to see if any locks are being applied
|
||||||
|
@export var is_locked : bool :
|
||||||
|
get:
|
||||||
|
return _check_is_locked()
|
||||||
|
|
||||||
|
#If a lock called lock_name hasn't already been added, adds one.
|
||||||
|
func add_lock(lock_name:String):
|
||||||
|
#Don't add duplicate locks
|
||||||
|
if(contains_lock(lock_name)):
|
||||||
|
print_debug("Lock %lock is already added." % lock_name)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
#Add locks and emit events
|
||||||
|
_locks.append(lock_name)
|
||||||
|
emit_signal("Lock_Added", lock_name)
|
||||||
|
#if this is the first and only lock, the locked status has changed to true
|
||||||
|
if(_locks.size() == 1):
|
||||||
|
Lock_Status_Changed.emit(true)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#Removes a lock with the name lock_name. Prints a message if it's not in there.
|
||||||
|
func remove_lock(lock_name:String):
|
||||||
|
if(contains_lock(lock_name)):
|
||||||
|
_locks.erase(lock_name)
|
||||||
|
#If there's now zero locks remaining, emit event
|
||||||
|
if(_locks.size() == 0):
|
||||||
|
Lock_Status_Changed.emit(false)
|
||||||
|
else:
|
||||||
|
print_debug("Lock %lock cannot be removed as it isn't there." % lock_name)
|
||||||
|
|
||||||
|
#Returns true if _locks has any entries added, false if no locks are being applied
|
||||||
|
func _check_is_locked():
|
||||||
|
return _locks.size() > 0;
|
||||||
|
|
||||||
|
#Returns true if a lock called lock_name is already added to _locks
|
||||||
|
func contains_lock(lock_name:String):
|
||||||
|
for lock in _locks:
|
||||||
|
if lock == lock_name:
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#Prints all current locks - useful for tracking down issues when locks haven't been lifted
|
||||||
|
func debug_locks():
|
||||||
|
var log = "Printing all locks"
|
||||||
|
for lock in _locks:
|
||||||
|
print_debug("\n" + str(lock))
|
||||||
|
|
||||||
|
#To be used for debug - for when the locks need to be bypassed to test.
|
||||||
|
func debug_release_all_locks():
|
||||||
|
for lock in _locks:
|
||||||
|
Lock_Removed.emit(lock)
|
||||||
|
_locks.clear();
|
33
client/player/MovementValues.gd
Normal file
33
client/player/MovementValues.gd
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
extends Resource
|
||||||
|
class_name MovementValues
|
||||||
|
|
||||||
|
@export var walk_speed : float = 1.75
|
||||||
|
@export var run_speed : float = 3.75
|
||||||
|
@export var sprint_speed : float = 6.5
|
||||||
|
|
||||||
|
@export var walk_acceleration : float = 20.0
|
||||||
|
@export var run_acceleration : float = 20.0
|
||||||
|
@export var sprint_acceleration : float = 20.0
|
||||||
|
|
||||||
|
@export var idle_rotation_rate : float = 0.5
|
||||||
|
@export var walk_rotation_rate : float = 4.0
|
||||||
|
@export var run_rotation_rate : float = 5.0
|
||||||
|
@export var sprint_rotation_rate : float = 20.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
func _init(_walk_speed: float = walk_speed, _run_speed: float = run_speed, _sprint_speed: float = sprint_speed,\
|
||||||
|
_walk_acceleration : float = walk_acceleration, _run_acceleration : float = run_acceleration, _sprint_acceleration : float = sprint_acceleration,\
|
||||||
|
_idle_rotation_rate : float = idle_rotation_rate, _walk_rotation_rate : float = walk_rotation_rate, _run_rotation_rate : float = run_rotation_rate, _sprint_rotation_rate : float = sprint_rotation_rate):
|
||||||
|
walk_speed = _walk_speed
|
||||||
|
run_speed = _run_speed
|
||||||
|
sprint_speed = _sprint_speed
|
||||||
|
|
||||||
|
walk_acceleration = _walk_acceleration
|
||||||
|
run_acceleration = _run_acceleration
|
||||||
|
sprint_acceleration = _sprint_acceleration
|
||||||
|
|
||||||
|
idle_rotation_rate = _idle_rotation_rate
|
||||||
|
walk_rotation_rate = _walk_rotation_rate
|
||||||
|
run_rotation_rate = _run_rotation_rate
|
||||||
|
sprint_rotation_rate = _sprint_rotation_rate
|
187
client/player/PlayerController.gd
Normal file
187
client/player/PlayerController.gd
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
extends Node
|
||||||
|
class_name PlayerController
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
#Controls Settings
|
||||||
|
@export var OnePressJump := false
|
||||||
|
@export var UsingSprintToggle := false
|
||||||
|
@export var UsingCrouchToggle := false
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
@export var character_component : PlayerGameplayComponent
|
||||||
|
@export var networking : PlayerNetworkingComponent
|
||||||
|
|
||||||
|
var controls_the_possessed_character:bool=false
|
||||||
|
var peer_id:int
|
||||||
|
var inputs :int
|
||||||
|
var input_vector :Vector2
|
||||||
|
var h_rotation :float
|
||||||
|
#var v_rotation :float
|
||||||
|
var previous_rotation_mode
|
||||||
|
var direction := Vector3.ZERO
|
||||||
|
|
||||||
|
#####################################
|
||||||
|
#Locks System
|
||||||
|
@export var lock_system : LockSystem
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
@export var mouse_sensitivity : float = 0.01
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
#Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
|
||||||
|
possess_character(character_component,true)
|
||||||
|
|
||||||
|
|
||||||
|
func possess_character(p_character_component:CharacterMovementComponent,control:bool):
|
||||||
|
if character_component:
|
||||||
|
character_component.camera_root.Camera.current = false
|
||||||
|
controls_the_possessed_character = control
|
||||||
|
character_component = p_character_component
|
||||||
|
character_component.camera_root.Camera.current = networking.is_local_authority()
|
||||||
|
|
||||||
|
|
||||||
|
func _physics_process(delta):
|
||||||
|
if !networking.is_local_authority():
|
||||||
|
return
|
||||||
|
if lock_system != null && lock_system.is_locked:
|
||||||
|
direction = Vector3.ZERO
|
||||||
|
character_component.add_movement_input()
|
||||||
|
return
|
||||||
|
|
||||||
|
#------------------ Input Movement ------------------#
|
||||||
|
h_rotation = character_component.camera_root.HObject.transform.basis.get_euler().y
|
||||||
|
var v_rotation = character_component.camera_root.VObject.transform.basis.get_euler().x
|
||||||
|
|
||||||
|
if Input.is_action_pressed("ui_up") || Input.is_action_pressed("ui_down") || Input.is_action_pressed("ui_right") || Input.is_action_pressed("ui_left") :
|
||||||
|
direction = Vector3(Input.get_action_strength("ui_right") - Input.get_action_strength("ui_left"),
|
||||||
|
remap(v_rotation,-PI/2,PI/2,-1.0,1.0) if character_component.is_flying == true else 0.0,
|
||||||
|
Input.get_action_strength("ui_down") - Input.get_action_strength("ui_up"))
|
||||||
|
direction = direction.rotated(Vector3.UP,h_rotation).normalized()
|
||||||
|
if character_component.gait == Global.gait.sprinting :
|
||||||
|
character_component.add_movement_input(direction, character_component.current_movement_data.sprint_speed,character_component.current_movement_data.sprint_acceleration)
|
||||||
|
elif character_component.gait == Global.gait.running:
|
||||||
|
character_component.add_movement_input(direction, character_component.current_movement_data.run_speed,character_component.current_movement_data.run_acceleration)
|
||||||
|
else:
|
||||||
|
character_component.add_movement_input(direction, character_component.current_movement_data.walk_speed,character_component.current_movement_data.walk_acceleration)
|
||||||
|
else:
|
||||||
|
direction = Vector3.ZERO
|
||||||
|
character_component.add_movement_input()
|
||||||
|
|
||||||
|
|
||||||
|
#------------------ Input Crouch ------------------#
|
||||||
|
if UsingCrouchToggle == false:
|
||||||
|
if Input.is_action_pressed("ui_crouch"):
|
||||||
|
if character_component.stance != Global.stance.crouching:
|
||||||
|
character_component.stance = Global.stance.crouching
|
||||||
|
else:
|
||||||
|
if character_component.stance != Global.stance.standing:
|
||||||
|
character_component.stance = Global.stance.standing
|
||||||
|
else:
|
||||||
|
if Input.is_action_just_pressed("ui_crouch"):
|
||||||
|
character_component.stance = Global.stance.standing if character_component.stance == Global.stance.crouching else Global.stance.crouching
|
||||||
|
#------------------ Sprint ------------------#
|
||||||
|
if UsingSprintToggle:
|
||||||
|
if Input.is_action_just_pressed("ui_sprint"):
|
||||||
|
if character_component.gait == Global.gait.walking:
|
||||||
|
character_component.gait = Global.gait.running
|
||||||
|
elif character_component.gait == Global.gait.running:
|
||||||
|
character_component.gait = Global.gait.sprinting
|
||||||
|
elif character_component.gait == Global.gait.sprinting:
|
||||||
|
character_component.gait = Global.gait.walking
|
||||||
|
else:
|
||||||
|
if Input.is_action_just_pressed("ui_sprint"):
|
||||||
|
if character_component.gait == Global.gait.walking:
|
||||||
|
character_component.gait = Global.gait.running
|
||||||
|
elif character_component.gait == Global.gait.running:
|
||||||
|
character_component.gait = Global.gait.sprinting
|
||||||
|
if Input.is_action_just_released("ui_sprint"):
|
||||||
|
if character_component.gait == Global.gait.sprinting or character_component.gait == Global.gait.walking:
|
||||||
|
character_component.gait = Global.gait.walking
|
||||||
|
elif character_component.gait == Global.gait.running:
|
||||||
|
await get_tree().create_timer(0.4).timeout
|
||||||
|
if character_component.gait == Global.gait.running:
|
||||||
|
character_component.gait = Global.gait.walking
|
||||||
|
#------------------ Input Aim ------------------#
|
||||||
|
if Input.is_action_pressed("ui_aim"):
|
||||||
|
if character_component.rotation_mode != Global.rotation_mode.aiming:
|
||||||
|
previous_rotation_mode = character_component.rotation_mode
|
||||||
|
character_component.rotation_mode = Global.rotation_mode.aiming
|
||||||
|
else:
|
||||||
|
if character_component.rotation_mode == Global.rotation_mode.aiming:
|
||||||
|
character_component.rotation_mode = previous_rotation_mode
|
||||||
|
#------------------ Jump ------------------#=
|
||||||
|
if OnePressJump == true:
|
||||||
|
if Input.is_action_just_pressed("ui_jump"):
|
||||||
|
if character_component.stance != Global.stance.standing:
|
||||||
|
character_component.stance = Global.stance.standing
|
||||||
|
else:
|
||||||
|
character_component.jump()
|
||||||
|
else:
|
||||||
|
if Input.is_action_pressed("ui_jump"):
|
||||||
|
if character_component.stance != Global.stance.standing:
|
||||||
|
character_component.stance = Global.stance.standing
|
||||||
|
else:
|
||||||
|
character_component.jump()
|
||||||
|
|
||||||
|
#------------------ Interaction ------------------#
|
||||||
|
if Input.is_action_just_pressed("ui_interaction"):
|
||||||
|
character_component.camera_root.Camera.get_node("InteractionRaycast").Interact()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var view_changed_recently = false
|
||||||
|
func _input(event):
|
||||||
|
if !networking.is_local_authority():
|
||||||
|
return
|
||||||
|
if Input.is_action_pressed("ui_rotate_player"):
|
||||||
|
if event is InputEventMouseMotion:
|
||||||
|
if !character_component or !controls_the_possessed_character:
|
||||||
|
return
|
||||||
|
character_component.camera_root.camera_h += -event.relative.x * mouse_sensitivity
|
||||||
|
character_component.camera_root.camera_v += -event.relative.y * mouse_sensitivity
|
||||||
|
#------------------ Motion Warping test------------------#
|
||||||
|
if event.is_action_pressed("ui_fire"):
|
||||||
|
character_component.anim_ref.active = false
|
||||||
|
get_node("../MotionWarping").add_sync_position(Vector3(4.762,1.574,-1.709),Vector3(0,PI,0),"kick_target",self,character_component.mesh_ref)
|
||||||
|
get_node("../AnimationPlayer").play("Kick")
|
||||||
|
await get_tree().create_timer(2.6).timeout
|
||||||
|
character_component.anim_ref.active = true
|
||||||
|
|
||||||
|
#------------------ Change Camera View ------------------#
|
||||||
|
if Input.is_action_just_released("ui_switch_camera_view"):
|
||||||
|
if view_changed_recently == false:
|
||||||
|
view_changed_recently = true
|
||||||
|
character_component.camera_root.view_angle = character_component.camera_root.view_angle + 1 if character_component.camera_root.view_angle < 2 else 0
|
||||||
|
await get_tree().create_timer(0.3).timeout
|
||||||
|
view_changed_recently = false
|
||||||
|
else:
|
||||||
|
view_changed_recently = false
|
||||||
|
if Input.is_action_just_pressed("ui_switch_camera_view"):
|
||||||
|
await get_tree().create_timer(0.2).timeout
|
||||||
|
if view_changed_recently == false:
|
||||||
|
character_component.camera_root.view_mode = character_component.camera_root.view_mode + 1 if character_component.camera_root.view_mode < 1 else 0
|
||||||
|
view_changed_recently = true
|
||||||
|
if networking.is_local_authority():
|
||||||
|
if event.is_action_pressed("ui_enable_sdfgi"):
|
||||||
|
var postprocess = preload("res://defaults/default_env.tres")
|
||||||
|
postprocess.sdfgi_enabled = not postprocess.sdfgi_enabled
|
||||||
|
postprocess.ssil_enabled = not postprocess.ssil_enabled
|
||||||
|
postprocess.ssao_enabled = not postprocess.ssao_enabled
|
||||||
|
postprocess.ssr_enabled = not postprocess.ssr_enabled
|
||||||
|
postprocess.glow_enabled = not postprocess.glow_enabled
|
||||||
|
if event.is_action_pressed("ui_ragdoll"):
|
||||||
|
character_component.ragdoll = true
|
||||||
|
|
||||||
|
|
||||||
|
if character_component.rotation_mode == Global.rotation_mode.velocity_direction:
|
||||||
|
if character_component.camera_root != null:
|
||||||
|
if character_component.camera_root.view_mode == Global.view_mode.first_person:
|
||||||
|
character_component.camera_root.view_mode = Global.view_mode.third_person
|
||||||
|
|
||||||
|
if(Input.is_action_pressed("ui_pause")):
|
||||||
|
if(lock_system.contains_lock("pauseGame")):
|
||||||
|
lock_system.remove_lock("pauseGame")
|
||||||
|
else:
|
||||||
|
lock_system.add_lock("pauseGame")
|
52
client/player/PlayerGameplayComponent.gd
Normal file
52
client/player/PlayerGameplayComponent.gd
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
extends CharacterMovementComponent
|
||||||
|
class_name PlayerGameplayComponent
|
||||||
|
|
||||||
|
@export_group("Stamina System", "stamina_")
|
||||||
|
@export var stamina_use: bool = false
|
||||||
|
@export var stamina_energy_consumption: float = 15.0#per second
|
||||||
|
@export var stamina_attribute: GameAttribute
|
||||||
|
|
||||||
|
@export var networking : PlayerNetworkingComponent
|
||||||
|
@export var targeting_component : TargetingComponent
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
targeting_component.connect("detected", func(p): print(p))
|
||||||
|
|
||||||
|
|
||||||
|
func _process(delta):
|
||||||
|
if gait != Global.gait.sprinting and stamina_use:
|
||||||
|
stamina_attribute.being_used = false
|
||||||
|
if gait == Global.gait.sprinting and stamina_use:
|
||||||
|
if !stamina_attribute.can_use or stamina_attribute.current_value < stamina_energy_consumption*delta:
|
||||||
|
gait = Global.gait.running
|
||||||
|
return
|
||||||
|
stamina_attribute.being_used = true
|
||||||
|
stamina_attribute.current_value -= stamina_energy_consumption*delta
|
||||||
|
|
||||||
|
func _physics_process(delta):
|
||||||
|
super._physics_process(delta)
|
||||||
|
# Debug()
|
||||||
|
if !networking.is_local_authority():
|
||||||
|
if input_is_moving:
|
||||||
|
if gait == Global.gait.sprinting:
|
||||||
|
add_movement_input(input_direction, current_movement_data.sprint_speed,current_movement_data.sprint_acceleration)
|
||||||
|
elif gait == Global.gait.running:
|
||||||
|
add_movement_input(input_direction, current_movement_data.run_speed,current_movement_data.run_acceleration)
|
||||||
|
else:
|
||||||
|
add_movement_input(input_direction, current_movement_data.walk_speed,current_movement_data.walk_acceleration)
|
||||||
|
else:
|
||||||
|
add_movement_input(input_direction,0,deacceleration)
|
||||||
|
|
||||||
|
return
|
||||||
|
#------------------ Look At ------------------#
|
||||||
|
match rotation_mode:
|
||||||
|
Global.rotation_mode.velocity_direction:
|
||||||
|
if input_is_moving:
|
||||||
|
ik_look_at(actual_velocity + Vector3(0.0,1.0,0.0))
|
||||||
|
Global.rotation_mode.looking_direction:
|
||||||
|
ik_look_at(camera_root.SpringArm.transform.basis.z * 2.0 + Vector3(0.0,1.5,0.0))
|
||||||
|
Global.rotation_mode.aiming:
|
||||||
|
ik_look_at(camera_root.SpringArm.transform.basis.z * 2.0 + Vector3(0.0,1.5,0.0))
|
||||||
|
#func Debug():
|
||||||
|
# $Status/Label.text = "InputSpeed : %s" % input_velocity.length()
|
||||||
|
# $Status/Label2.text = "ActualSpeed : %s" % get_velocity().length()
|
86
client/player/PlayerNetworkingComponent.gd
Normal file
86
client/player/PlayerNetworkingComponent.gd
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
extends Node
|
||||||
|
class_name PlayerNetworkingComponent
|
||||||
|
@export var character_movement_component : NodePath
|
||||||
|
@onready var PlayerRef = get_node(character_movement_component)
|
||||||
|
|
||||||
|
|
||||||
|
var sync_camera_h_transform : Transform3D
|
||||||
|
var sync_camera_v_transform : Transform3D
|
||||||
|
var sync_view_mode : Global.view_mode = Global.view_mode.third_person
|
||||||
|
var sync_CameraHOffset : float
|
||||||
|
var sync_position : Vector3:
|
||||||
|
set(value):
|
||||||
|
sync_position = value
|
||||||
|
processed_position = false
|
||||||
|
var sync_mesh_rotation : Vector3
|
||||||
|
var sync_direction : Vector3
|
||||||
|
var sync_input_is_moving : bool
|
||||||
|
var sync_gait : Global.gait = Global.gait.walking
|
||||||
|
var sync_rotation_mode : Global.rotation_mode = Global.rotation_mode.velocity_direction
|
||||||
|
var sync_stance : Global.stance = Global.stance.standing
|
||||||
|
var sync_movement_state : Global.movement_state = Global.movement_state.grounded
|
||||||
|
var sync_movement_action : Global.movement_action = Global.movement_action.none
|
||||||
|
var sync_velocity : Vector3
|
||||||
|
var processed_position : bool
|
||||||
|
|
||||||
|
|
||||||
|
@export var id:int = 0:
|
||||||
|
get:
|
||||||
|
return id
|
||||||
|
set(value):
|
||||||
|
id = value
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
#$MultiplayerSynchronizer.set_multiplayer_authority(str(get_parent().name).to_int())
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
func set_id(value:int):
|
||||||
|
id = value
|
||||||
|
|
||||||
|
|
||||||
|
func is_local_authority() -> bool:
|
||||||
|
if Multi.is_offline():
|
||||||
|
return true
|
||||||
|
else:
|
||||||
|
return id == Multi.get_id()
|
||||||
|
#return str(get_parent().name).to_int() == Multi.get_id()
|
||||||
|
# if multiplayer.multiplayer_peer is OfflineMultiplayerPeer:
|
||||||
|
# return true
|
||||||
|
# else:
|
||||||
|
# return str(get_parent().name).to_int() == multiplayer.get_unique_id()
|
||||||
|
|
||||||
|
#sync player on clients
|
||||||
|
func _physics_process(_delta):
|
||||||
|
if !is_local_authority():
|
||||||
|
if not processed_position:
|
||||||
|
PlayerRef.character_node.position = sync_position
|
||||||
|
processed_position = true
|
||||||
|
PlayerRef.mesh_ref.rotation = sync_mesh_rotation
|
||||||
|
PlayerRef.input_direction = sync_direction
|
||||||
|
PlayerRef.gait = sync_gait
|
||||||
|
PlayerRef.stance = sync_stance
|
||||||
|
PlayerRef.rotation_mode = sync_rotation_mode
|
||||||
|
PlayerRef.camera_root.VObject.transform = sync_camera_v_transform
|
||||||
|
PlayerRef.camera_root.HObject.transform = sync_camera_h_transform
|
||||||
|
PlayerRef.camera_root.view_mode = sync_CameraHOffset
|
||||||
|
PlayerRef.camera_root.CameraHOffset = sync_CameraHOffset
|
||||||
|
PlayerRef.movement_state = sync_movement_state
|
||||||
|
PlayerRef.movement_action = sync_movement_action
|
||||||
|
# PlayerRef.velocity = sync_velocity
|
||||||
|
PlayerRef.input_is_moving = sync_input_is_moving
|
||||||
|
return
|
||||||
|
sync_position = PlayerRef.character_node.position
|
||||||
|
sync_mesh_rotation = PlayerRef.mesh_ref.rotation
|
||||||
|
sync_direction = PlayerRef.input_direction
|
||||||
|
sync_gait = PlayerRef.gait
|
||||||
|
sync_stance = PlayerRef.stance
|
||||||
|
sync_rotation_mode = PlayerRef.rotation_mode
|
||||||
|
sync_camera_h_transform = PlayerRef.camera_root.HObject.transform
|
||||||
|
sync_camera_v_transform = PlayerRef.camera_root.VObject.transform
|
||||||
|
sync_movement_state = PlayerRef.movement_state
|
||||||
|
sync_movement_action = PlayerRef.movement_action
|
||||||
|
sync_input_is_moving = PlayerRef.input_is_moving
|
||||||
|
sync_view_mode = PlayerRef.camera_root.view_mode
|
||||||
|
sync_CameraHOffset = PlayerRef.camera_root.CameraHOffset
|
55
client/player/TargetingComponent.gd
Normal file
55
client/player/TargetingComponent.gd
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
extends Node
|
||||||
|
class_name TargetingComponent
|
||||||
|
|
||||||
|
@export var detection_raycast : RayCast3D
|
||||||
|
@export var combat_component : CombatSystem
|
||||||
|
|
||||||
|
@export var detectable_object_group : String = "detectable_object" # we can use the node group feature in Godot
|
||||||
|
@export var detectable_player_group : String = "player" # I am calling any Enemy/AI/Ally a player
|
||||||
|
|
||||||
|
|
||||||
|
var detected_object : Node3D
|
||||||
|
var detected_object_combat_component : CombatSystem
|
||||||
|
|
||||||
|
var detected_player : Node3D
|
||||||
|
var detected_player_combat_component : CombatSystem
|
||||||
|
|
||||||
|
|
||||||
|
signal object_detected(object: Node3D, object_combat_component:CombatSystem)
|
||||||
|
signal enemy_detected(object: Node3D, player_combat_component:CombatSystem)
|
||||||
|
signal ally_detected(object: Node3D, player_combat_component:CombatSystem)
|
||||||
|
signal player_detected(object: Node3D, player_combat_component:CombatSystem)
|
||||||
|
signal detected(object: Node3D) #this activates for all
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
detection_raycast.add_exception(get_parent())
|
||||||
|
|
||||||
|
func _process(delta):
|
||||||
|
if detection_raycast.is_colliding():
|
||||||
|
if detected_player == detection_raycast.get_collider() or detected_object == detection_raycast.get_collider():
|
||||||
|
return
|
||||||
|
|
||||||
|
if detection_raycast.get_collider().is_in_group(detectable_object_group):
|
||||||
|
detected_object = detection_raycast.get_collider()
|
||||||
|
detected.emit(detected_object)
|
||||||
|
|
||||||
|
detected_object_combat_component = detected_object.find_child("CombatSystem")
|
||||||
|
if !detected_object_combat_component:
|
||||||
|
object_detected.emit(detected_object, null)
|
||||||
|
return
|
||||||
|
object_detected.emit(detected_object, detected_object_combat_component)
|
||||||
|
return
|
||||||
|
|
||||||
|
if detection_raycast.get_collider().is_in_group(detectable_player_group):
|
||||||
|
detected_player = detection_raycast.get_collider()
|
||||||
|
detected.emit(detected_player)
|
||||||
|
detected_player_combat_component = detected_player.find_child("CombatSystem")
|
||||||
|
if !detected_player_combat_component:
|
||||||
|
player_detected.emit(detected_player, null)
|
||||||
|
return
|
||||||
|
player_detected.emit(detected_player, detected_player_combat_component)
|
||||||
|
if detected_player_combat_component.team_id != combat_component.NATURAL_OBJECT and detected_player_combat_component.team_id != combat_component.team_id:
|
||||||
|
enemy_detected.emit(detected_player, detected_player_combat_component)
|
||||||
|
if detected_player_combat_component.team_id == combat_component.team_id:
|
||||||
|
ally_detected.emit(detected_player, detected_player_combat_component)
|
||||||
|
return
|
37
client/player/character.gd
Normal file
37
client/player/character.gd
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
extends CharacterBody3D
|
||||||
|
|
||||||
|
|
||||||
|
@export var speed = 5.0
|
||||||
|
@export var jump_velocity = 4.5
|
||||||
|
|
||||||
|
var camrot_h:float = 0.0
|
||||||
|
var camrot_v:float = 0.0
|
||||||
|
@export var h_acceleration:float = 10.0
|
||||||
|
@export var v_acceleration:float = 10.0
|
||||||
|
@export var h_sensitivity:float = 0.5
|
||||||
|
@export var v_sensitivity:float = 0.5
|
||||||
|
|
||||||
|
|
||||||
|
# Get the gravity from the project settings to be synced with RigidBody nodes.
|
||||||
|
var gravity = ProjectSettings.get_setting("physics/3d/default_gravity")
|
||||||
|
@export var otherplayer:bool = true:
|
||||||
|
get:
|
||||||
|
return otherplayer
|
||||||
|
set(value):
|
||||||
|
otherplayer = value
|
||||||
|
|
||||||
|
|
||||||
|
func set_otherplayer(value:bool):
|
||||||
|
otherplayer = value
|
||||||
|
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
$SpringArm3D/Camera3D.set_current(false)
|
||||||
|
|
||||||
|
|
||||||
|
func set_current_camera():
|
||||||
|
$SpringArm3D/Camera3D.set_current(true)
|
||||||
|
|
||||||
|
|
||||||
|
func set_id(value:int):
|
||||||
|
$PlayerNetworkingComponent.set_id(value)
|
8165
client/player/character.tscn
Normal file
8165
client/player/character.tscn
Normal file
File diff suppressed because one or more lines are too long
16
client/player/crouch_mouvements_valuestres.tres
Normal file
16
client/player/crouch_mouvements_valuestres.tres
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[gd_resource type="Resource" script_class="MovementValues" load_steps=2 format=3 uid="uid://ci00blt7nkvkp"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://player/MovementValues.gd" id="1_w6h8d"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1_w6h8d")
|
||||||
|
walk_speed = 1.75
|
||||||
|
run_speed = 3.75
|
||||||
|
sprint_speed = 6.5
|
||||||
|
walk_acceleration = 20.0
|
||||||
|
run_acceleration = 20.0
|
||||||
|
sprint_acceleration = 20.0
|
||||||
|
idle_rotation_rate = 0.5
|
||||||
|
walk_rotation_rate = 4.0
|
||||||
|
run_rotation_rate = 5.0
|
||||||
|
sprint_rotation_rate = 20.0
|
16
client/player/standing_movement_values.tres
Normal file
16
client/player/standing_movement_values.tres
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[gd_resource type="Resource" script_class="MovementValues" load_steps=2 format=3 uid="uid://cl10j5xgiv3nt"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://player/MovementValues.gd" id="1_lg3kw"]
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
script = ExtResource("1_lg3kw")
|
||||||
|
walk_speed = 1.75
|
||||||
|
run_speed = 3.75
|
||||||
|
sprint_speed = 6.5
|
||||||
|
walk_acceleration = 20.0
|
||||||
|
run_acceleration = 20.0
|
||||||
|
sprint_acceleration = 20.0
|
||||||
|
idle_rotation_rate = 0.5
|
||||||
|
walk_rotation_rate = 4.0
|
||||||
|
run_rotation_rate = 5.0
|
||||||
|
sprint_rotation_rate = 20.0
|
|
@ -18,6 +18,7 @@ config/icon="res://icon.svg"
|
||||||
[autoload]
|
[autoload]
|
||||||
|
|
||||||
Multi="*res://scenes/multi.gd"
|
Multi="*res://scenes/multi.gd"
|
||||||
|
Global="*res://player/Global.gd"
|
||||||
|
|
||||||
[input]
|
[input]
|
||||||
|
|
||||||
|
@ -58,6 +59,51 @@ ui_rotate_player={
|
||||||
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
ui_aim={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
|
ui_sprint={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
|
ui_jump={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
|
ui_interaction={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
|
ui_crouch={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
|
ui_switch_camera_view={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
|
ui_ragdoll={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
|
ui_enable_sdfgi={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
|
ui_fire={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
|
ui_pause={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": []
|
||||||
|
}
|
||||||
|
ui_quit={
|
||||||
|
"deadzone": 0.5,
|
||||||
|
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"echo":false,"script":null)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
[rendering]
|
[rendering]
|
||||||
|
|
||||||
|
|
11
client/scenes/DebugWindow.gd
Normal file
11
client/scenes/DebugWindow.gd
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
extends Window
|
||||||
|
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
pass # Replace with function body.
|
||||||
|
|
||||||
|
|
||||||
|
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||||
|
func _process(delta):
|
||||||
|
pass
|
66
client/scenes/DebugWindow.tscn
Normal file
66
client/scenes/DebugWindow.tscn
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
[gd_scene load_steps=2 format=3 uid="uid://ddymq82ef22l2"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://scenes/DebugWindow.gd" id="1_f6n7f"]
|
||||||
|
|
||||||
|
[node name="DebugWindow" type="Window"]
|
||||||
|
title = "Debug"
|
||||||
|
initial_position = 3
|
||||||
|
size = Vector2i(512, 512)
|
||||||
|
current_screen = 0
|
||||||
|
script = ExtResource("1_f6n7f")
|
||||||
|
|
||||||
|
[node name="TabContainer" type="TabContainer" parent="."]
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="Perso" type="TabBar" parent="TabContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/Perso"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
|
||||||
|
[node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/Perso/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="TabContainer/Perso/VBoxContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
text = "Count"
|
||||||
|
|
||||||
|
[node name="Count" type="Label" parent="TabContainer/Perso/VBoxContainer/HBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "0"
|
||||||
|
|
||||||
|
[node name="HBoxContainer2" type="HBoxContainer" parent="TabContainer/Perso/VBoxContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="Label" type="Label" parent="TabContainer/Perso/VBoxContainer/HBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 0
|
||||||
|
text = "Id"
|
||||||
|
|
||||||
|
[node name="Id" type="Label" parent="TabContainer/Perso/VBoxContainer/HBoxContainer2"]
|
||||||
|
layout_mode = 2
|
||||||
|
size_flags_horizontal = 3
|
||||||
|
text = "0"
|
||||||
|
|
||||||
|
[node name="Network" type="TabBar" parent="TabContainer"]
|
||||||
|
visible = false
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/Network"]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
|
@ -6,16 +6,11 @@ var last_event = null
|
||||||
@export var listen_ip:String = ""
|
@export var listen_ip:String = ""
|
||||||
@export var listen_port:int = 33333
|
@export var listen_port:int = 33333
|
||||||
|
|
||||||
# Called when the node enters the scene tree for the first time.
|
|
||||||
func _ready():
|
func _ready():
|
||||||
pass # Replace with function body.
|
pass # Replace with function body.
|
||||||
|
|
||||||
|
|
||||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
|
||||||
func _process(_delta):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
func _on_button_pressed():
|
func _on_button_pressed():
|
||||||
if $VBoxContainer/TextEdit.get_text() != "":
|
if $VBoxContainer/TextEdit.get_text() != "":
|
||||||
self.hide()
|
self.hide()
|
||||||
|
|
|
@ -12,58 +12,106 @@ var player_name: String
|
||||||
# Server confirm our account
|
# Server confirm our account
|
||||||
#var account_confirmed:bool = false
|
#var account_confirmed:bool = false
|
||||||
|
|
||||||
const PLAYER = preload("res://scenes/player.tscn")
|
#const PLAYER = preload("res://scenes/player.tscn")
|
||||||
|
#const PLAYER = preload("res://player/character.tscn")
|
||||||
|
const player_path:String = "res://player/character.tscn"
|
||||||
|
@export var PlayerCharacter = preload(player_path)
|
||||||
|
#@export var debug_window: PackedScene
|
||||||
|
|
||||||
|
@onready var _MainWindow: Window = get_window()
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
_on_connexion_updated(Multi.Connexion.NONE)
|
_on_connexion_updated(Multi.Connexion.NONE)
|
||||||
Multi.set_player_position(self.get_node("CharacterBody3D"))
|
#Multi.set_player_position(self.get_node("CharacterBody3D"))
|
||||||
|
for child in $PlayerSpawnLocation.get_children():
|
||||||
|
child.queue_free()
|
||||||
|
var p = PlayerCharacter.instantiate()
|
||||||
|
$PlayerSpawnLocation.add_child(p)
|
||||||
|
$PlayerSpawnLocation.set_visible(false)
|
||||||
|
p.set_otherplayer(false)
|
||||||
|
Multi.set_player_position($PlayerSpawnLocation.get_child(0))
|
||||||
Multi.connexion_updated.connect(_on_connexion_updated)
|
Multi.connexion_updated.connect(_on_connexion_updated)
|
||||||
Multi.update_my_position.connect(_on_update_me)
|
Multi.update_my_position.connect(_on_update_me)
|
||||||
Multi.update_player_position.connect(_on_update_player)
|
Multi.update_player_position.connect(_on_update_player)
|
||||||
Multi.remove_player.connect(_on_remove_player)
|
Multi.remove_player.connect(_on_remove_player)
|
||||||
|
#_MainWindow.gui_embed_subwindows = false # Make subwindows actual system windows <- VERY IMPORTANT
|
||||||
|
|
||||||
|
|
||||||
func _on_connexion_updated(new_state):
|
func create_view_window():
|
||||||
|
pass
|
||||||
|
# var new_window: Window = view_window.instantiate()
|
||||||
|
# # Pass the main window's world to the new window
|
||||||
|
# # This is what makes it possible to show the same world in multiple windows
|
||||||
|
# new_window.world_2d = _MainWindow.world_2d
|
||||||
|
# new_window.world_3d = _MainWindow.world_3d
|
||||||
|
# # The new window needs to have the same world offset as the player
|
||||||
|
# new_window.world_offset = world_offset
|
||||||
|
# # Contrarily to the main window, hide the player and show the world
|
||||||
|
# new_window.set_canvas_cull_mask_bit(player_visibility_layer, false)
|
||||||
|
# new_window.set_canvas_cull_mask_bit(world_visibility_layer, true)
|
||||||
|
# add_child(new_window)
|
||||||
|
|
||||||
|
|
||||||
|
func _on_connexion_updated(new_state:Multi.Connexion):
|
||||||
if new_state == Multi.Connexion.NONE:
|
if new_state == Multi.Connexion.NONE:
|
||||||
self.get_node("CharacterBody3D").set_enable_event(false)
|
#self.get_node("CharacterBody3D").set_enable_event(false)
|
||||||
|
$CameraStarting.set_current(true)
|
||||||
$Panel/State.set_text("Not Connected")
|
$Panel/State.set_text("Not Connected")
|
||||||
$Panel.show()
|
$Panel.show()
|
||||||
if new_state == Multi.Connexion.ACCOUNT_REFUSED:
|
elif new_state == Multi.Connexion.ACCOUNT_REFUSED:
|
||||||
self.get_node("CharacterBody3D").set_enable_event(false)
|
#self.get_node("CharacterBody3D").set_enable_event(false)
|
||||||
|
$CameraStarting.set_current(true)
|
||||||
$Panel/State.set_text("Account Refused")
|
$Panel/State.set_text("Account Refused")
|
||||||
$Panel.show()
|
$Panel.show()
|
||||||
$Window.show()
|
$Window.show()
|
||||||
elif new_state == Multi.Connexion.CONNECTING:
|
elif new_state == Multi.Connexion.CONNECTING:
|
||||||
self.get_node("CharacterBody3D").set_enable_event(false)
|
#self.get_node("CharacterBody3D").set_enable_event(false)
|
||||||
|
$CameraStarting.set_current(true)
|
||||||
$Panel/State.set_text("Connecting")
|
$Panel/State.set_text("Connecting")
|
||||||
$Panel.show()
|
$Panel.show()
|
||||||
else:
|
elif new_state == Multi.Connexion.CONNECTED:
|
||||||
$Panel.hide()
|
$Panel.hide()
|
||||||
|
$PlayerSpawnLocation.set_visible(true)
|
||||||
|
$PlayerSpawnLocation.get_child(0).set_current_camera()
|
||||||
|
$PlayerSpawnLocation.get_child(0).set_name(str(Multi.get_id()))
|
||||||
|
$PlayerSpawnLocation.get_child(0).set_id(Multi.get_id())
|
||||||
|
$CameraStarting.set_current(false)
|
||||||
|
else:
|
||||||
|
$CameraStarting.set_current(true)
|
||||||
|
$Panel/State.set_text("Unknown")
|
||||||
|
$Panel.show()
|
||||||
|
|
||||||
|
|
||||||
func _on_update_me(pos:Vector3):
|
func _on_update_me(pos:Vector3):
|
||||||
self.set_player_position(pos)
|
self.set_player_position(pos)
|
||||||
self.get_node("CharacterBody3D").set_enable_event(true)
|
#self.get_node("CharacterBody3D").set_enable_event(true)
|
||||||
|
#for idx in $PlayerSpawnLocation.get_child_count():
|
||||||
|
# $PlayerSpawnLocation.queue_free()
|
||||||
|
#var p = PlayerCharacter.instantiate()
|
||||||
|
#$PlayerSpawnLocation.add_child(p)
|
||||||
|
#$CameraStarting.set_current(false)
|
||||||
|
#self.set_player_position(pos)
|
||||||
|
|
||||||
|
|
||||||
func _on_update_player(id:int, pos:Vector3):
|
func _on_update_player(id:int, pos:Vector3):
|
||||||
var child = $Players.find_child(str(id), false, false)
|
var child = $Players.find_child(str(id), false, false)
|
||||||
if child == null:
|
if child == null:
|
||||||
print("Add player : ", id)
|
print("Add player : ", id)
|
||||||
var scene = preload("res://scenes/player.tscn")
|
var scene = preload(player_path)
|
||||||
var instance = scene.instantiate()
|
var instance = scene.instantiate()
|
||||||
instance.set_name(str(id))
|
instance.set_name(str(id))
|
||||||
$Players.add_child(instance)
|
$Players.add_child(instance)
|
||||||
#maxplayer += 1
|
instance.set_visible(true)
|
||||||
|
instance.set_id(id)
|
||||||
var child2 = $Players.find_child(str(id), false, false)
|
var child2 = $Players.find_child(str(id), false, false)
|
||||||
child2.set_global_position(pos)
|
child2.set_global_position(pos)
|
||||||
else:
|
else:
|
||||||
|
print("Update player : ", id, " ", pos)
|
||||||
child.set_global_position(pos)
|
child.set_global_position(pos)
|
||||||
|
#child.set_visible(true)
|
||||||
|
|
||||||
|
|
||||||
func _on_remove_player(id:int):
|
func _on_remove_player(id:int):
|
||||||
#print("Remove player : ", mid)
|
|
||||||
var child = $Players.find_child(str(id), false, false)
|
var child = $Players.find_child(str(id), false, false)
|
||||||
if child != null:
|
if child != null:
|
||||||
print("Remove player : ", id)
|
print("Remove player : ", id)
|
||||||
|
@ -88,5 +136,17 @@ func _on_remove_player(id:int):
|
||||||
# print("==========================")
|
# print("==========================")
|
||||||
|
|
||||||
|
|
||||||
|
func _process(delta):
|
||||||
|
# if $PlayerSpawnLocation:
|
||||||
|
# print(">", $PlayerSpawnLocation.get_global_position())
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
func _input(event):
|
||||||
|
if event is InputEventKey:
|
||||||
|
if event.is_action_pressed("ui_quit"):
|
||||||
|
get_tree().quit()
|
||||||
|
|
||||||
|
|
||||||
func set_player_position(pos: Vector3):
|
func set_player_position(pos: Vector3):
|
||||||
self.get_node("CharacterBody3D").set_global_position(pos)
|
$PlayerSpawnLocation.set_global_position(pos)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
[gd_scene load_steps=11 format=3 uid="uid://bemavktwweaog"]
|
[gd_scene load_steps=10 format=3 uid="uid://bemavktwweaog"]
|
||||||
|
|
||||||
[ext_resource type="Shader" path="res://scenes/main.gdshader" id="1_caff6"]
|
[ext_resource type="Shader" path="res://scenes/main.gdshader" id="1_caff6"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cg5uqqd4ibdem" path="res://scenes/player.tscn" id="1_nc7b3"]
|
|
||||||
[ext_resource type="Script" path="res://scenes/main.gd" id="1_ts8of"]
|
[ext_resource type="Script" path="res://scenes/main.gd" id="1_ts8of"]
|
||||||
[ext_resource type="Script" path="res://scenes/Window.gd" id="3_uwnj8"]
|
[ext_resource type="Script" path="res://scenes/Window.gd" id="3_uwnj8"]
|
||||||
|
|
||||||
|
@ -45,9 +44,6 @@ transform = Transform3D(-0.866025, 0, -0.5, -0.25, 0.866025, 0.433013, 0.433013,
|
||||||
shadow_enabled = true
|
shadow_enabled = true
|
||||||
shadow_opacity = 0.5
|
shadow_opacity = 0.5
|
||||||
|
|
||||||
[node name="CharacterBody3D" parent="." instance=ExtResource("1_nc7b3")]
|
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 6, 0)
|
|
||||||
|
|
||||||
[node name="Players" type="Node3D" parent="."]
|
[node name="Players" type="Node3D" parent="."]
|
||||||
|
|
||||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||||
|
@ -112,6 +108,11 @@ text = "Not connected"
|
||||||
horizontal_alignment = 1
|
horizontal_alignment = 1
|
||||||
vertical_alignment = 1
|
vertical_alignment = 1
|
||||||
|
|
||||||
|
[node name="PlayerSpawnLocation" type="Node3D" parent="."]
|
||||||
|
|
||||||
|
[node name="CameraStarting" type="Camera3D" parent="."]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 5)
|
||||||
|
|
||||||
[connection signal="focus_entered" from="Window" to="Window" method="_on_focus_entered"]
|
[connection signal="focus_entered" from="Window" to="Window" method="_on_focus_entered"]
|
||||||
[connection signal="focus_exited" from="Window" to="Window" method="_on_focus_exited"]
|
[connection signal="focus_exited" from="Window" to="Window" method="_on_focus_exited"]
|
||||||
[connection signal="mouse_entered" from="Window" to="Window" method="_on_mouse_entered"]
|
[connection signal="mouse_entered" from="Window" to="Window" method="_on_mouse_entered"]
|
||||||
|
|
|
@ -32,7 +32,7 @@ func set_username(value):
|
||||||
set = set_player_position
|
set = set_player_position
|
||||||
|
|
||||||
|
|
||||||
func set_player_position(value):
|
func set_player_position(value:Node3D):
|
||||||
player_position = value
|
player_position = value
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,9 +44,13 @@ enum Connexion{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@export var state_connexion:Connexion
|
@export var state_connexion:Connexion = Connexion.NONE
|
||||||
|
|
||||||
@export var id:int = 0
|
@export var id:int = 0:
|
||||||
|
get:
|
||||||
|
return id
|
||||||
|
set(value):
|
||||||
|
id = value
|
||||||
|
|
||||||
|
|
||||||
signal connexion_updated(new_state)
|
signal connexion_updated(new_state)
|
||||||
|
@ -60,6 +64,14 @@ var dataEnet:ENetPacketPeer
|
||||||
var errorEnet:Error
|
var errorEnet:Error
|
||||||
|
|
||||||
|
|
||||||
|
func get_id() -> int:
|
||||||
|
return id
|
||||||
|
|
||||||
|
|
||||||
|
func is_offline() -> bool:
|
||||||
|
return state_connexion != Connexion.CONNECTED
|
||||||
|
|
||||||
|
|
||||||
func update_state(value):
|
func update_state(value):
|
||||||
state_connexion = value
|
state_connexion = value
|
||||||
connexion_updated.emit(state_connexion)
|
connexion_updated.emit(state_connexion)
|
||||||
|
@ -119,7 +131,8 @@ func get_event_received():
|
||||||
var x = data.decode_double(2+8)
|
var x = data.decode_double(2+8)
|
||||||
var y = data.decode_double(2+16)
|
var y = data.decode_double(2+16)
|
||||||
var z = data.decode_double(2+24)
|
var z = data.decode_double(2+24)
|
||||||
# print("id:", id, " x:", x, " y:", y, " z:", z)
|
print("MyID:", id)
|
||||||
|
#print("id:", id, " x:", x, " y:", y, " z:", z)
|
||||||
update_my_position.emit(Vector3(x, y, z))
|
update_my_position.emit(Vector3(x, y, z))
|
||||||
#self.set_player_position(Vector3(x, y, z))
|
#self.set_player_position(Vector3(x, y, z))
|
||||||
update_state(Connexion.CONNECTED)
|
update_state(Connexion.CONNECTED)
|
||||||
|
@ -227,3 +240,4 @@ func _process(_delta):
|
||||||
print("STATE_ZOMBIE")
|
print("STATE_ZOMBIE")
|
||||||
else:
|
else:
|
||||||
var _event = enet.service()
|
var _event = enet.service()
|
||||||
|
print("STATE_UNKNOWN")
|
||||||
|
|
Loading…
Reference in a new issue