18 - Crouch #44
|
@ -6,7 +6,7 @@ func update_ammo(var weapon, var amount):
|
|||
func updateHealth(health: int):
|
||||
$Health/HealthBar.value = health
|
||||
$Health/HealthBar/HealthText.text = String(health)
|
||||
|
||||
|
||||
func update_crosshair(visible: bool, hit: bool):
|
||||
$Crosshair.visible = visible
|
||||
if hit:
|
||||
|
|
|
@ -57,6 +57,7 @@ __meta__ = {
|
|||
}
|
||||
|
||||
[node name="Health" parent="." instance=ExtResource( 2 )]
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="Weapon" type="MarginContainer" parent="."]
|
||||
anchor_left = 1.0
|
||||
|
@ -69,6 +70,7 @@ margin_right = -32.0
|
|||
margin_bottom = -32.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
@ -90,6 +92,7 @@ margin_right = 116.0
|
|||
margin_bottom = 64.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
mouse_filter = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="RoundsClips" type="Label" parent="Weapon/VBoxContainer"]
|
||||
|
@ -123,6 +126,7 @@ margin_left = -511.401
|
|||
margin_top = -301.225
|
||||
margin_right = 512.599
|
||||
margin_bottom = 298.775
|
||||
mouse_filter = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
@ -132,6 +136,7 @@ margin_left = 512.0
|
|||
margin_top = 300.0
|
||||
margin_right = 512.0
|
||||
margin_bottom = 300.0
|
||||
mouse_filter = 2
|
||||
|
||||
[node name="Line1" type="ColorRect" parent="Crosshair/CrosshairCenter"]
|
||||
margin_left = 8.0
|
||||
|
@ -139,6 +144,7 @@ margin_top = -1.0
|
|||
margin_right = 20.0
|
||||
margin_bottom = 1.0
|
||||
rect_pivot_offset = Vector2( -8, 1 )
|
||||
mouse_filter = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
@ -150,6 +156,7 @@ margin_right = 20.0
|
|||
margin_bottom = 1.0
|
||||
rect_rotation = 90.0
|
||||
rect_pivot_offset = Vector2( -8, 1 )
|
||||
mouse_filter = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
@ -161,6 +168,7 @@ margin_right = 20.0
|
|||
margin_bottom = 1.0
|
||||
rect_rotation = 180.0
|
||||
rect_pivot_offset = Vector2( -8, 1 )
|
||||
mouse_filter = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
@ -172,6 +180,7 @@ margin_right = 20.0
|
|||
margin_bottom = 1.0
|
||||
rect_rotation = -90.0
|
||||
rect_pivot_offset = Vector2( -8, 1 )
|
||||
mouse_filter = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
@ -182,6 +191,7 @@ margin_left = 512.0
|
|||
margin_top = 300.0
|
||||
margin_right = 512.0
|
||||
margin_bottom = 300.0
|
||||
mouse_filter = 2
|
||||
script = ExtResource( 3 )
|
||||
|
||||
[node name="HitConfirmationSound" type="AudioStreamPlayer" parent="Crosshair/HitConfirmation"]
|
||||
|
@ -198,6 +208,7 @@ margin_bottom = 1.0
|
|||
rect_rotation = 45.3067
|
||||
rect_scale = Vector2( 1, 0.5 )
|
||||
rect_pivot_offset = Vector2( -8, 1 )
|
||||
mouse_filter = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
@ -210,6 +221,7 @@ margin_bottom = 1.0
|
|||
rect_rotation = 135.307
|
||||
rect_scale = Vector2( 1, 0.5 )
|
||||
rect_pivot_offset = Vector2( -8, 1 )
|
||||
mouse_filter = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
@ -222,6 +234,7 @@ margin_bottom = 1.0
|
|||
rect_rotation = 225.306
|
||||
rect_scale = Vector2( 1, 0.5 )
|
||||
rect_pivot_offset = Vector2( -8, 1 )
|
||||
mouse_filter = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
@ -234,6 +247,7 @@ margin_bottom = 1.0
|
|||
rect_rotation = -44.6931
|
||||
rect_scale = Vector2( 1, 0.5 )
|
||||
rect_pivot_offset = Vector2( -8, 1 )
|
||||
mouse_filter = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
# This script moves the shape up half the amount it shrinks when crouching
|
||||
# This way the top of the capsule keeps the same relative position to the camera
|
||||
# Moving the camera instead would cause a camera move when crouching in the air
|
||||
# which is weird (I tested it).
|
||||
#
|
||||
# It also acts as a middleman to ensure crouching will work with all shape types
|
||||
|
||||
extends CollisionShape
|
||||
|
||||
var height: = 1.0 setget set_height, get_height
|
||||
|
||||
var _normal_height: float
|
||||
var _normal_y: float
|
||||
|
||||
func _ready() -> void:
|
||||
_normal_y = translation.y
|
||||
|
||||
match shape.get_class():
|
||||
"CapsuleShape":
|
||||
_normal_height = shape.height
|
||||
|
||||
"BoxShape":
|
||||
_normal_height = shape.extents.z
|
||||
|
||||
var another_class:
|
||||
push_error("Height logic not implemented for shape %s" % another_class)
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if _normal_height:
|
||||
# Using self. make so we call the setter even though we're inside the objecr
|
||||
translation.y = _normal_y + (_normal_height - self.height) / 2.0
|
||||
|
||||
func set_height(value: float) -> void:
|
||||
match shape.get_class():
|
||||
"CapsuleShape":
|
||||
shape.height = value
|
||||
|
||||
"BoxShape":
|
||||
shape.extents.z = value
|
||||
|
||||
func get_height() -> float:
|
||||
match shape.get_class():
|
||||
"CapsuleShape":
|
||||
return shape.height
|
||||
|
||||
"BoxShape":
|
||||
return shape.extents.z
|
||||
|
||||
var _:
|
||||
return 0.0
|
||||
|
|
@ -2,8 +2,13 @@ class_name Player
|
|||
extends KinematicBody
|
||||
|
||||
const GRAVITY = Vector3.DOWN * 9.8 * 1.5
|
||||
const UP = Vector3.UP
|
||||
const JUMP_VELOCITY = 8
|
||||
const WALK_VELOCITY = 8
|
||||
const CROUCH_WALK_VELOCITY = 2
|
||||
const CROUCH_VELOCITY = 5
|
||||
const HEIGHT = 1.1
|
||||
const CROUCH_HEIGHT = 0.55
|
||||
|
||||
const AIR_CONTROL = 0.1
|
||||
|
||||
|
@ -16,6 +21,7 @@ const MOUSE_SENSITIVITY = 1.0 / 1000
|
|||
export var show_healthbar = true
|
||||
export var max_health = 150
|
||||
onready var health = max_health setget set_health
|
||||
onready var collision_shape: = $CollisionShapeBody
|
||||
|
||||
onready var camera = $Camera
|
||||
onready var debug = $Debug
|
||||
|
@ -43,7 +49,7 @@ onready var active_weapon = weapons.switch_to_weapon(0)
|
|||
#onready var sfx_foosteps = [$"Sounds/Footstep-Concrete-01",
|
||||
# $"Sounds/Footstep-Concrete-02",
|
||||
# $"Sounds/Footstep-Concrete-03",
|
||||
# $"Sounds/Footstep-Concrete-04"]
|
||||
# $"Sounds/Footstep-Concrete-04"]
|
||||
|
||||
#var sfx_footsteps_last = 0
|
||||
#var sfx_footsteps_next = 0
|
||||
|
@ -88,21 +94,21 @@ remote func set_player_data(player):
|
|||
func get_closest_point(_A: Vector3, _B: Vector3):
|
||||
var A = transform.inverse().xform(_A)
|
||||
var B = transform.inverse().xform(_B)
|
||||
|
||||
|
||||
var diff = B - A
|
||||
var result = A - (A.dot(diff) * diff) / (diff.length_squared())
|
||||
return transform.xform(result)
|
||||
|
||||
func on_bullet_flyby(from, to):
|
||||
var closest_point = get_closest_point(from, to)
|
||||
|
||||
|
||||
var flyby_noise = preload("res://Classes/Audio/BulletFlyBySoundPlayer.tscn").instance()
|
||||
flyby_noise.translation = closest_point
|
||||
|
||||
|
||||
get_tree().root.call_deferred("add_child", flyby_noise)
|
||||
|
||||
remote func jump():
|
||||
if is_on_floor:
|
||||
if is_on_floor():
|
||||
velocity.y = JUMP_VELOCITY
|
||||
jump_timeout = 0.2
|
||||
$Sounds/Jump.play()
|
||||
|
@ -112,15 +118,15 @@ func jetpack(delta):
|
|||
# Swap these to try the different versions of the jetpack.
|
||||
#jetpack_grounded(delta)
|
||||
#jetpack_empty(delta)
|
||||
|
||||
|
||||
# activate visual jetpack effects when sound is playing:
|
||||
$Sounds/Jetpack.stream_paused = !jetpack_fireing
|
||||
|
||||
|
||||
$Effects/JetpackFlame.emitting = jetpack_fireing
|
||||
$Effects/JetpackSmoke.emitting = jetpack_fireing
|
||||
$Effects/JetpackLight.visible = jetpack_fireing
|
||||
#print(get_tree().get_network_unique_id())
|
||||
|
||||
|
||||
#$Effects/JetpackFlame.emitting = ! $Sounds/Jetpack.stream_paused
|
||||
#$Effects/JetpackSmoke.emitting = ! $Sounds/Jetpack.stream_paused
|
||||
#$Effects/JetpackLight.visible = ! $Sounds/Jetpack.stream_paused
|
||||
|
@ -129,22 +135,22 @@ func jetpack_empty(delta):
|
|||
debug.text = "JP fuel: %s\nJP active: %s\nJP used: %s\nJP sound: %s" % [
|
||||
jetpack_fuel, jetpack_active, jetpack_used, !$Sounds/Jetpack.stream_paused
|
||||
]
|
||||
|
||||
|
||||
# Enable jetpack when it is fully charged.
|
||||
if jetpack_fuel > (JETPACK_FUEL_MAX - 0.001):
|
||||
jetpack_used = false
|
||||
# Disable jetpack when it is empty.
|
||||
elif jetpack_fuel <= 0 and not jetpack_active:
|
||||
jetpack_used = true
|
||||
|
||||
|
||||
if jetpack_active and not jetpack_used and jetpack_fuel > 0:
|
||||
velocity.y += JETPACK_THRUST * delta
|
||||
jetpack_fuel -= delta
|
||||
|
||||
|
||||
$Sounds/Jetpack.stream_paused = false
|
||||
else:
|
||||
$Sounds/Jetpack.stream_paused = true
|
||||
|
||||
|
||||
# Only charge when fully empty.
|
||||
if jetpack_used:
|
||||
jetpack_fuel = clamp(
|
||||
|
@ -158,21 +164,21 @@ func jetpack_grounded(delta):
|
|||
debug.text = "JP fuel: %s\nJP active: %s\nJP sound: %s" % [
|
||||
jetpack_fuel, jetpack_active, !$Sounds/Jetpack.stream_paused
|
||||
]
|
||||
|
||||
|
||||
# Only charge when grounded.
|
||||
if is_on_floor:
|
||||
if is_on_floor():
|
||||
jetpack_fuel = clamp(
|
||||
jetpack_fuel + JETPACK_REFILL_RATE * delta,
|
||||
0.0,
|
||||
JETPACK_FUEL_MAX
|
||||
)
|
||||
|
||||
|
||||
jetpack_fireing = false
|
||||
|
||||
|
||||
# Only use jetpack in the air.
|
||||
else:
|
||||
if jetpack_active and jetpack_fuel > 0:
|
||||
|
||||
|
||||
velocity.y += JETPACK_THRUST * delta
|
||||
jetpack_fuel -= delta
|
||||
jetpack_fireing = true
|
||||
|
@ -187,106 +193,101 @@ remote func mouselook(rel):
|
|||
var sensitivity = MOUSE_SENSITIVITY * game.mouse_sensitivity_multiplier
|
||||
rotate_y(- rel.x * sensitivity)
|
||||
camera.rotation.x = clamp(camera.rotation.x-rel.y * sensitivity, -PI/2, PI/2)
|
||||
|
||||
|
||||
rpc_unreliable("mouselook_abs", camera.rotation.x, rotation.y)
|
||||
|
||||
func _physics_process(delta):
|
||||
if get_parent().name != "Players":
|
||||
return
|
||||
|
||||
check_floor_collision()
|
||||
|
||||
|
||||
walk(delta)
|
||||
fall(delta)
|
||||
jetpack_grounded(delta)
|
||||
|
||||
|
||||
|
||||
|
||||
if str(get_tree().get_network_unique_id()) != name:
|
||||
return
|
||||
|
||||
|
||||
var movement_vector = Vector3()
|
||||
if jump_timeout > 0:
|
||||
movement_vector = move_and_slide(velocity, Vector3.UP)
|
||||
else:
|
||||
var upvector = floor_normal
|
||||
movement_vector = move_and_slide_with_snap(velocity, Vector3.DOWN, upvector, true)
|
||||
|
||||
movement_vector = move_and_slide_with_snap(velocity, Vector3.DOWN, UP, true)
|
||||
|
||||
velocity = movement_vector
|
||||
|
||||
|
||||
rset("translation", translation)
|
||||
|
||||
func check_floor_collision():
|
||||
var space_state = get_world().direct_space_state
|
||||
|
||||
var from = global_transform.xform(Vector3(0, 0.0, 0))
|
||||
var to = global_transform.xform(Vector3(0, -0.3, 0.0))
|
||||
|
||||
var result = space_state.intersect_ray(from, to)
|
||||
|
||||
if jump_timeout > 0:
|
||||
is_on_floor = false
|
||||
elif result:
|
||||
is_on_floor = true
|
||||
floor_normal = result.normal
|
||||
else:
|
||||
is_on_floor = false
|
||||
|
||||
func walk(delta):
|
||||
var floor_normal = get_floor_normal()
|
||||
var is_on_floor = is_on_floor()
|
||||
|
||||
jump_timeout -= delta
|
||||
|
||||
|
||||
# Walk
|
||||
walk_direction = Vector2()
|
||||
|
||||
if Input.is_action_pressed("MoveForward"):
|
||||
walk_direction.y -= 1
|
||||
if Input.is_action_pressed("MoveBack"):
|
||||
walk_direction.y += 1
|
||||
if Input.is_action_pressed("MoveLeft"):
|
||||
walk_direction.x -= 1
|
||||
if Input.is_action_pressed("MoveRight"):
|
||||
walk_direction.x += 1
|
||||
|
||||
|
||||
if not get_tree().is_input_handled():
|
||||
if Input.is_action_pressed("MoveForward"):
|
||||
walk_direction.y -= 1
|
||||
if Input.is_action_pressed("MoveBack"):
|
||||
walk_direction.y += 1
|
||||
if Input.is_action_pressed("MoveLeft"):
|
||||
walk_direction.x -= 1
|
||||
if Input.is_action_pressed("MoveRight"):
|
||||
walk_direction.x += 1
|
||||
|
||||
walk_direction = walk_direction.normalized()
|
||||
|
||||
|
||||
var walking_speed = Vector2(velocity.x, velocity.z)
|
||||
|
||||
|
||||
walking_speed = walking_speed.rotated(rotation.y)
|
||||
|
||||
|
||||
if is_on_floor:
|
||||
walking_speed = lerp(walking_speed, walk_direction * WALK_VELOCITY, delta * WALK_ACCEL)
|
||||
var target_velocity: = WALK_VELOCITY if not Input.is_action_pressed("Crouch") else CROUCH_WALK_VELOCITY
|
||||
walking_speed = lerp(walking_speed, walk_direction * target_velocity, delta * WALK_ACCEL)
|
||||
else:
|
||||
walking_speed = lerp(walking_speed, walk_direction * JUMP_VELOCITY, delta * JUMP_ACCEL)
|
||||
walking_speed = walking_speed.rotated(-rotation.y)
|
||||
|
||||
|
||||
velocity.x = walking_speed.x
|
||||
velocity.z = walking_speed.y
|
||||
|
||||
|
||||
# Make walking perpendicular to the floor
|
||||
if is_on_floor:
|
||||
if is_on_floor and not Input.is_action_pressed("MoveJump") and floor_normal.y:
|
||||
velocity.y -= velocity.dot(floor_normal) / floor_normal.y
|
||||
|
||||
|
||||
if walking_speed.length() > 0 and is_on_floor:
|
||||
weapon_bob_anim.travel("Walk")
|
||||
elif walking_speed.length() == 0 and is_on_floor:
|
||||
weapon_bob_anim.travel("Idle")
|
||||
|
||||
# Crouch
|
||||
if not get_tree().is_input_handled():
|
||||
if Input.is_action_pressed("Crouch"):
|
||||
collision_shape.height = move_toward(collision_shape.height, CROUCH_HEIGHT, CROUCH_VELOCITY * delta)
|
||||
else:
|
||||
collision_shape.height = move_toward(collision_shape.height, HEIGHT, CROUCH_VELOCITY * delta)
|
||||
# collision_shape.shape.height = move_toward(collision_shape.shape.height, HEIGHT, CROUCH_VELOCITY * delta)
|
||||
|
||||
collision_shape.height = stepify(collision_shape.height, 0.01)
|
||||
|
||||
|
||||
func fall(delta):
|
||||
if is_on_floor:
|
||||
if is_on_floor():
|
||||
if not was_on_floor: # if this is the first frame of ground conotact after a frame of no ground contact - we've just ended a fall
|
||||
weapon_bob_anim.travel("Land")
|
||||
|
||||
else:
|
||||
velocity += delta * GRAVITY
|
||||
|
||||
was_on_floor = is_on_floor
|
||||
|
||||
|
||||
was_on_floor = is_on_floor()
|
||||
|
||||
|
||||
master func on_hit(damage, location):
|
||||
set_health(health - 30)
|
||||
|
||||
|
||||
rpc("blood_splatter", location)
|
||||
|
||||
|
||||
if health <= 0:
|
||||
rpc("kill")
|
||||
else:
|
||||
|
@ -300,42 +301,42 @@ sync func blood_splatter(location):
|
|||
master func kill():
|
||||
if is_dead:
|
||||
return
|
||||
|
||||
|
||||
$Sounds/Death.rpc("play")
|
||||
|
||||
|
||||
is_dead = true
|
||||
|
||||
|
||||
set_health(0)
|
||||
$CollisionShapeBody.disabled = true
|
||||
|
||||
|
||||
$Camera/Hand.hide()
|
||||
#$HUD.update_crosshair(false, false)
|
||||
|
||||
|
||||
yield(get_tree().create_timer(3), "timeout")
|
||||
|
||||
|
||||
spawn()
|
||||
|
||||
|
||||
yield(get_tree().create_timer(3), "timeout")
|
||||
|
||||
|
||||
# for i in gibs.get_children():
|
||||
# i.queue_free()
|
||||
# yield(get_tree().create_timer(rand_range(0.1, 1)), "timeout")
|
||||
|
||||
|
||||
# gibs.queue_free()
|
||||
|
||||
func spawn():
|
||||
rpc("unset_death")
|
||||
set_health(max_health)
|
||||
|
||||
|
||||
velocity = Vector3()
|
||||
|
||||
|
||||
game.get_spawn_point().spawn(self)
|
||||
|
||||
|
||||
$Camera/Hand.show()
|
||||
$HUD.show()
|
||||
|
||||
|
||||
$CollisionShapeBody.disabled = false
|
||||
|
||||
|
||||
$Camera.rotation = Vector3.ZERO
|
||||
rotation = Vector3.ZERO
|
||||
|
||||
|
@ -357,39 +358,39 @@ sync func switch_to_next_weapon():
|
|||
sync func switch_to_prev_weapon():
|
||||
active_weapon = weapons.prev_weapon()
|
||||
|
||||
func _input(event):
|
||||
func _unhandled_input(event):
|
||||
if is_dead:
|
||||
return
|
||||
|
||||
|
||||
if str(get_tree().get_network_unique_id()) != name:
|
||||
return
|
||||
|
||||
|
||||
if game.GAME_MODE != "PLAYING":
|
||||
return
|
||||
|
||||
|
||||
# Moouselook
|
||||
if event is InputEventMouseMotion:
|
||||
var rel = event.relative
|
||||
|
||||
|
||||
mouselook(rel)
|
||||
|
||||
|
||||
# Jump
|
||||
if event.is_action_pressed("MoveJump"):
|
||||
rpc("jump")
|
||||
jump()
|
||||
|
||||
|
||||
# Jetpack
|
||||
if event.is_action_pressed("MoveJetpack"):
|
||||
rpc("set_jetpack_active", true)
|
||||
if event.is_action_released("MoveJetpack"):
|
||||
rpc("set_jetpack_active", false)
|
||||
|
||||
|
||||
# Weapon
|
||||
if event.is_action_pressed("WeaponPrimary"):
|
||||
shoot()
|
||||
if event.is_action_pressed("WeaponReload"):
|
||||
reload()
|
||||
|
||||
|
||||
if event.is_action_pressed("WeaponNext"):
|
||||
rpc("switch_to_next_weapon")
|
||||
if event.is_action_pressed("WeaponPrev"):
|
||||
|
@ -407,30 +408,30 @@ func set_local_player():
|
|||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
$HUD/Health/HealthBar.max_value = max_health
|
||||
|
||||
|
||||
# Set player class
|
||||
var path = get_script().get_path()
|
||||
|
||||
|
||||
if path.find("res://Assets/Characters/") != -1:
|
||||
player_class = path.replace("res://Assets/Characters/", "").split("/")[0]
|
||||
|
||||
|
||||
set_health(max_health)
|
||||
# disabled the ragdoll collider
|
||||
#for i in $Player/Gibs.get_children():
|
||||
# i.get_child(1).disabled = true
|
||||
#disabled = true
|
||||
#$"Player/Gibs/PlayerGibs _cell /shape0".set_disabled(true)
|
||||
|
||||
|
||||
rset_config("translation", MultiplayerAPI.RPC_MODE_SYNC)
|
||||
if !show_healthbar:
|
||||
$Billboard.hide()
|
||||
|
||||
|
||||
# only show the debug label on local machine
|
||||
if name != String(get_tree().get_network_unique_id()):
|
||||
debug.hide()
|
||||
|
||||
|
||||
# initialize sound looping
|
||||
|
||||
|
||||
#$Sounds/Jetpack.stream.
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[gd_scene load_steps=44 format=2]
|
||||
[gd_scene load_steps=45 format=2]
|
||||
|
||||
[ext_resource path="res://Classes/UI/Health.tscn" type="PackedScene" id=1]
|
||||
[ext_resource path="res://Classes/UI/Billboard.gd" type="Script" id=2]
|
||||
|
@ -12,6 +12,7 @@
|
|||
[ext_resource path="res://Assets/Weapons/GrenadeLauncher/GrenadeLauncher.tscn" type="PackedScene" id=10]
|
||||
[ext_resource path="res://Assets/Effects/CircleSoft.svg" type="Texture" id=11]
|
||||
[ext_resource path="res://Assets/Maps/DM1/OmniFlicker.gd" type="Script" id=12]
|
||||
[ext_resource path="res://Classes/Player/CollisionShapeBody.gd" type="Script" id=14]
|
||||
|
||||
[sub_resource type="AnimationNodeAnimation" id=1]
|
||||
animation = "Idle"
|
||||
|
@ -220,7 +221,7 @@ script = ExtResource( 8 )
|
|||
transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.53592, -0.0651628 )
|
||||
|
||||
[node name="Hand" type="Spatial" parent="Camera"]
|
||||
transform = Transform( -4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 0.335, -0.392298, -0.559 )
|
||||
transform = Transform( -4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 0.335, -0.391038, -0.559 )
|
||||
|
||||
[node name="WeaponBobAnimationTree" type="AnimationTree" parent="Camera/Hand"]
|
||||
tree_root = SubResource( 12 )
|
||||
|
@ -286,6 +287,7 @@ margin_bottom = 104.0
|
|||
[node name="CollisionShapeBody" type="CollisionShape" parent="."]
|
||||
transform = Transform( 1, 0, 0, 0, -1.62921e-07, 1, 0, -1, -1.62921e-07, 0, 0.882822, 0 )
|
||||
shape = SubResource( 19 )
|
||||
script = ExtResource( 14 )
|
||||
|
||||
[node name="Debug" type="Label" parent="."]
|
||||
margin_right = 41.0
|
||||
|
@ -356,3 +358,4 @@ stream_paused = true
|
|||
|
||||
[node name="HUD" parent="." instance=ExtResource( 7 )]
|
||||
visible = false
|
||||
mouse_filter = 2
|
||||
|
|
|
@ -7,22 +7,22 @@ func _ready():
|
|||
var dir = Directory.new()
|
||||
dir.open("res://Assets/Characters/")
|
||||
dir.list_dir_begin()
|
||||
|
||||
|
||||
var file = dir.get_next()
|
||||
while file != "":
|
||||
if not file.begins_with("."):
|
||||
# Add character
|
||||
add_character(file)
|
||||
|
||||
|
||||
file = dir.get_next()
|
||||
|
||||
func add_character(character_name):
|
||||
var path = "res://Assets/Characters/" + character_name + "/" + character_name + ".tscn"
|
||||
var packed_character = load(path)
|
||||
|
||||
|
||||
var character_option = preload("res://Classes/UI/CharacterOption.tscn").instance()
|
||||
$CenterContainer/VBoxContainer/CharacterList.add_child(character_option)
|
||||
|
||||
|
||||
character_option.set_character(packed_character)
|
||||
character_option.connect("character_selected", self, "character_selected", [character_name, packed_character])
|
||||
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
extends Control
|
||||
|
||||
signal typing_toggled(is_typing)
|
||||
|
||||
const TOGGLE_KEY = KEY_ENTER
|
||||
const MESSAGE_FORMAT = "%s: %s"
|
||||
|
||||
sync var chat_text: = "" setget set_chat_text
|
||||
|
||||
var player_name: = "Unknown"
|
||||
|
||||
onready var line_edit: LineEdit = $LineEdit
|
||||
onready var chat_history: RichTextLabel = $Panel/ChatHistory
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
pass
|
||||
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if is_typing():
|
||||
get_tree().set_input_as_handled()
|
||||
|
||||
if event.is_action_pressed("ToggleChatWrite"):
|
||||
toggle_typing()
|
||||
|
||||
func toggle() -> bool:
|
||||
visible = not visible
|
||||
|
||||
if not visible:
|
||||
$LineEdit.hide()
|
||||
|
||||
return visible
|
||||
|
||||
func toggle_typing() -> bool:
|
||||
$LineEdit.visible = not $LineEdit.visible and visible
|
||||
|
||||
return $LineEdit.visible
|
||||
|
||||
func is_typing() -> bool:
|
||||
return $LineEdit.visible
|
||||
|
||||
func _on_LineEdit_text_entered(new_text: String) -> void:
|
||||
toggle_typing()
|
||||
if new_text:
|
||||
var formatted_message = MESSAGE_FORMAT % [player_name, new_text]
|
||||
line_edit.text = ""
|
||||
rset("chat_text", chat_text + formatted_message)
|
||||
|
||||
func _on_LineEdit_visibility_changed() -> void:
|
||||
if line_edit.visible:
|
||||
line_edit.grab_focus()
|
||||
else:
|
||||
line_edit.release_focus()
|
||||
|
||||
func set_chat_text(value: String) -> void:
|
||||
visible = true
|
||||
chat_text = "%s\n" % value
|
||||
chat_history.text = chat_text
|
||||
|
||||
|
||||
func _on_LineEdit_gui_input(event: InputEvent) -> void:
|
||||
get_tree().set_input_as_handled()
|
||||
pass
|
|
@ -0,0 +1,52 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://Classes/UI/TextChat.gd" type="Script" id=1]
|
||||
|
||||
[node name="TextChat" type="Control"]
|
||||
anchor_top = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 8.0
|
||||
margin_top = -192.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = -8.0
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Panel" type="Panel" parent="."]
|
||||
self_modulate = Color( 1, 1, 1, 0.670588 )
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_bottom = -32.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="ChatHistory" type="RichTextLabel" parent="Panel"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 8.0
|
||||
margin_top = 8.0
|
||||
margin_right = -8.0
|
||||
margin_bottom = -8.0
|
||||
focus_mode = 2
|
||||
text = "
|
||||
"
|
||||
scroll_following = true
|
||||
selection_enabled = true
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="LineEdit" type="LineEdit" parent="."]
|
||||
visible = false
|
||||
anchor_top = 1.0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_top = -24.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
[connection signal="text_entered" from="LineEdit" to="." method="_on_LineEdit_text_entered"]
|
||||
[connection signal="visibility_changed" from="LineEdit" to="." method="_on_LineEdit_visibility_changed"]
|
103
Game/Game.gd
103
Game/Game.gd
|
@ -24,44 +24,44 @@ onready var menu_stack = [$MenuContainer/MainMenu]
|
|||
func set_local_player(player):
|
||||
if local_player != null:
|
||||
$Players.remove_child(local_player)
|
||||
|
||||
|
||||
local_player = player
|
||||
|
||||
|
||||
var id = peer.get_unique_id()
|
||||
player.name = str(id)
|
||||
player.set_network_master(id)
|
||||
$Players.add_child(local_player)
|
||||
player.set_local_player()
|
||||
|
||||
|
||||
var nickname = $MenuContainer/MainMenu/Name.text
|
||||
set_nickname(nickname)
|
||||
player.set_nickname(nickname)
|
||||
|
||||
|
||||
var player_data = get_player_data()
|
||||
|
||||
|
||||
rpc("set_player_data", player_data)
|
||||
|
||||
|
||||
$PlayerListContainer.update_player_list()
|
||||
|
||||
|
||||
player.hide()
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready():
|
||||
$MenuContainer/ConnectMenu/Destination/IPAdress.set_text(SERVER_IP)
|
||||
$MenuContainer/ConnectMenu/Destination/Port.set_text(str(SERVER_PORT))
|
||||
|
||||
|
||||
load_settings()
|
||||
|
||||
|
||||
if auto_host:
|
||||
initialize_server(false)
|
||||
|
||||
func load_settings():
|
||||
var load_settings = File.new()
|
||||
load_settings.open("user://settings.save", File.READ)
|
||||
|
||||
|
||||
if load_settings.is_open():
|
||||
var settings = parse_json(load_settings.get_as_text())
|
||||
|
||||
|
||||
for setting in settings:
|
||||
load_setting(setting, settings[setting])
|
||||
|
||||
|
@ -71,7 +71,7 @@ func load_setting(setting, value):
|
|||
func save_setting(setting, value):
|
||||
var save_settings = File.new()
|
||||
save_settings.open("user://settings.save", File.READ_WRITE)
|
||||
|
||||
|
||||
if save_settings.is_open():
|
||||
var settings = parse_json(save_settings.get_as_text())
|
||||
settings[setting] = value
|
||||
|
@ -97,15 +97,19 @@ func _input(event):
|
|||
for button in buttons:
|
||||
if button.name == "Back":
|
||||
button.emit_signal("pressed")
|
||||
|
||||
|
||||
if event.is_action_pressed("ShowPlayerList") and !$MenuContainer.visible:
|
||||
$PlayerListContainer.show()
|
||||
|
||||
|
||||
if event.is_action_released("ShowPlayerList"):
|
||||
$PlayerListContainer.hide()
|
||||
|
||||
if event.is_action_pressed("ToggleChatVisibility") and not $TextChat.is_typing() and GAME_MODE == "PLAYING":
|
||||
$TextChat.toggle()
|
||||
|
||||
func open_menus():
|
||||
GAME_MODE = "MENU"
|
||||
$TextChat.hide()
|
||||
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
|
||||
$MenuContainer.show()
|
||||
|
||||
|
@ -119,7 +123,7 @@ func return_to_menu(type=null):
|
|||
if type == null:
|
||||
menu_stack.pop_back()
|
||||
type = menu_stack[-1].name
|
||||
|
||||
|
||||
for menu in $MenuContainer.get_children():
|
||||
if menu.name == type:
|
||||
if type != null:
|
||||
|
@ -164,7 +168,7 @@ func set_mouse_sensitivity(sensitivity_multiplier, save=true):
|
|||
mouse_sensitivity_multiplier = sensitivity_multiplier
|
||||
else:
|
||||
return
|
||||
|
||||
|
||||
if save:
|
||||
save_setting("mouse_sensitivity", sensitivity_multiplier)
|
||||
else:
|
||||
|
@ -175,7 +179,7 @@ func set_fullscreen(is_fullscreen, save=true):
|
|||
OS.window_fullscreen = is_fullscreen
|
||||
else:
|
||||
return
|
||||
|
||||
|
||||
if save:
|
||||
save_setting("is_fullscreen", is_fullscreen)
|
||||
else:
|
||||
|
@ -187,6 +191,8 @@ func set_nickname(nickname, save=true):
|
|||
else:
|
||||
$MenuContainer/MainMenu/Name.text = nickname
|
||||
|
||||
$TextChat.player_name = nickname
|
||||
|
||||
func debug_connection_status():
|
||||
if (get_tree().network_peer.get_connection_status() == NetworkedMultiplayerPeer.CONNECTION_CONNECTING):
|
||||
print("We are trying to connect")
|
||||
|
@ -202,9 +208,9 @@ func initialize_server(join=true):
|
|||
get_tree().connect("network_peer_connected", self, "on_peer_connected")
|
||||
get_tree().connect("network_peer_disconnected", self, "on_peer_disconnected")
|
||||
get_tree().network_peer = peer
|
||||
|
||||
|
||||
initialize()
|
||||
|
||||
|
||||
if join:
|
||||
join_game()
|
||||
#add_player(peer.get_unique_id(), false)
|
||||
|
@ -214,32 +220,32 @@ func initialize_client():
|
|||
get_tree().connect("connected_to_server", self, "on_connection_established")
|
||||
get_tree().connect("connection_failed", self, "on_connection_failed")
|
||||
get_tree().network_peer = peer
|
||||
|
||||
|
||||
initialize()
|
||||
|
||||
func initialize():
|
||||
return_to_menu("MainMenu")
|
||||
|
||||
|
||||
#$MenuContainer/MainMenu/Connect.hide()
|
||||
#$MenuContainer/MainMenu/Disconnect.show()
|
||||
|
||||
|
||||
#close_menus()
|
||||
|
||||
func free_client():
|
||||
$MenuContainer/MainMenu/Connect.show()
|
||||
$MenuContainer/MainMenu/Disconnect.hide()
|
||||
|
||||
|
||||
for player in $Players.get_children():
|
||||
player.queue_free()
|
||||
|
||||
|
||||
for player_list_item in $PlayerListContainer/Panel/PlayerList.get_children():
|
||||
player_list_item.queue_free()
|
||||
|
||||
|
||||
peer.close_connection()
|
||||
|
||||
|
||||
get_tree().network_peer = null
|
||||
local_player = null
|
||||
|
||||
|
||||
return_to_menu("MainMenu")
|
||||
|
||||
func quit():
|
||||
|
@ -247,15 +253,15 @@ func quit():
|
|||
|
||||
func get_player_data():
|
||||
var players = $Players.get_children()
|
||||
|
||||
|
||||
var player_data = {}
|
||||
for player in players:
|
||||
var data = {}
|
||||
data["nickname"] = player.nickname
|
||||
data["char_class"] = player.player_class
|
||||
|
||||
|
||||
player_data[player.name] = data
|
||||
|
||||
|
||||
return player_data
|
||||
|
||||
func get_character_scene(character_name):
|
||||
|
@ -266,37 +272,37 @@ func get_character_scene(character_name):
|
|||
remote func check_players(player_data):
|
||||
for player_name in player_data:
|
||||
var data = player_data[player_name]
|
||||
|
||||
|
||||
if $Players.has_node(player_name):
|
||||
var p = $Players.get_node(player_name)
|
||||
if data["char_class"] != p.player_class:
|
||||
$Players.remove_child(p)
|
||||
|
||||
|
||||
if not $Players.has_node(player_name):
|
||||
var player = get_character_scene(data["char_class"]).instance()
|
||||
|
||||
|
||||
player.name = player_name
|
||||
player.set_network_master(int(player_name))
|
||||
|
||||
|
||||
$Players.add_child(player)
|
||||
player.translation += Vector3(0.0, 3.0, 0.0)
|
||||
|
||||
|
||||
player.set_nickname(data["nickname"])
|
||||
|
||||
|
||||
$PlayerListContainer.update_player_list()
|
||||
|
||||
func join_game():
|
||||
var player = player_scene.instance()
|
||||
|
||||
|
||||
set_local_player(player)
|
||||
|
||||
|
||||
open_menu("CharacterSelectScreen")
|
||||
|
||||
sync func spawn(player_id):
|
||||
var spawning_player = $Players.get_node(str(player_id))
|
||||
|
||||
|
||||
$Level.show()
|
||||
|
||||
|
||||
spawning_player.spawn()
|
||||
spawning_player.show()
|
||||
close_menus()
|
||||
|
@ -305,7 +311,7 @@ sync func remove_player(id):
|
|||
for player in $Players.get_children():
|
||||
if player.name == str(id):
|
||||
player.free()
|
||||
|
||||
|
||||
$PlayerListContainer.update_player_list()
|
||||
|
||||
|
||||
|
@ -317,14 +323,14 @@ func on_peer_connected(id):
|
|||
|
||||
master func set_player_data(player_data):
|
||||
check_players(player_data)
|
||||
|
||||
|
||||
var new_player_data = get_player_data()
|
||||
|
||||
|
||||
rpc("check_players", new_player_data)
|
||||
|
||||
func on_peer_disconnected(id):
|
||||
print("Peer disconnected with id ", id)
|
||||
|
||||
|
||||
rpc("remove_player", id)
|
||||
|
||||
func on_connection_established():
|
||||
|
@ -333,3 +339,12 @@ func on_connection_established():
|
|||
|
||||
func on_connection_failed():
|
||||
print("Connection has failed")
|
||||
|
||||
|
||||
func _on_TextChat_typing_toggled(is_typing) -> void:
|
||||
if is_typing:
|
||||
GAME_MODE = "MENU"
|
||||
|
||||
else:
|
||||
GAME_MODE = "PLAYING"
|
||||
pass
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
[gd_scene load_steps=6 format=2]
|
||||
[gd_scene load_steps=7 format=2]
|
||||
|
||||
[ext_resource path="res://Classes/UI/theme.tres" type="Theme" id=1]
|
||||
[ext_resource path="res://Game.gd" type="Script" id=2]
|
||||
[ext_resource path="res://Assets/Maps/DM1/DM1.tscn" type="PackedScene" id=3]
|
||||
[ext_resource path="res://Classes/UI/CharacterSelect.tscn" type="PackedScene" id=4]
|
||||
[ext_resource path="res://PlayerListContainer.gd" type="Script" id=5]
|
||||
[ext_resource path="res://Classes/UI/TextChat.tscn" type="PackedScene" id=6]
|
||||
|
||||
[node name="Game" type="Node"]
|
||||
script = ExtResource( 2 )
|
||||
|
@ -317,6 +318,11 @@ theme = ExtResource( 1 )
|
|||
[node name="PlayerList" type="VBoxContainer" parent="PlayerListContainer/Panel"]
|
||||
theme = ExtResource( 1 )
|
||||
alignment = 1
|
||||
|
||||
[node name="TextChat" parent="." instance=ExtResource( 6 )]
|
||||
visible = false
|
||||
margin_top = -264.542
|
||||
margin_bottom = -80.5416
|
||||
[connection signal="pressed" from="MenuContainer/MainMenu/QuickConnect" to="." method="join_test_server"]
|
||||
[connection signal="pressed" from="MenuContainer/MainMenu/Connect" to="." method="open_menu" binds= [ "ConnectMenu" ]]
|
||||
[connection signal="pressed" from="MenuContainer/MainMenu/Disconnect" to="." method="free_client"]
|
||||
|
@ -339,5 +345,6 @@ alignment = 1
|
|||
[connection signal="value_changed" from="MenuContainer/ControlsMenu/HBoxContainer/SensitivitySlider" to="." method="set_mouse_sensitivity"]
|
||||
[connection signal="pressed" from="MenuContainer/GraphicsMenu/Back" to="." method="return_to_menu" binds= [ "OptionsMenu" ]]
|
||||
[connection signal="toggled" from="MenuContainer/GraphicsMenu/Fullscreen" to="." method="set_fullscreen"]
|
||||
[connection signal="typing_toggled" from="TextChat" to="." method="_on_TextChat_typing_toggled"]
|
||||
|
||||
[editable path="MenuContainer/CharacterSelectScreen"]
|
||||
|
|
|
@ -4,12 +4,12 @@ var tracked_players = []
|
|||
|
||||
func update_player_list():
|
||||
var players = get_parent().get_node("Players").get_children()
|
||||
|
||||
|
||||
for child in $Panel/PlayerList.get_children():
|
||||
$Panel/PlayerList.remove_child(child)
|
||||
|
||||
|
||||
for player in players:
|
||||
var player_list_item = preload("res://Classes/UI/PlayerListItem.tscn").instance()
|
||||
$Panel/PlayerList.add_child(player_list_item)
|
||||
player_list_item.player = player
|
||||
|
||||
|
||||
|
|
|
@ -104,6 +104,21 @@ WeaponPrev={
|
|||
"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":5,"pressed":false,"doubleclick":false,"script":null)
|
||||
]
|
||||
}
|
||||
ToggleChatWrite={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777221,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
ToggleChatVisibility={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":89,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
Crouch={
|
||||
"deadzone": 0.5,
|
||||
"events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777238,"unicode":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[rendering]
|
||||
|
||||
|
|
Reference in New Issue