From c3226364f3930c8d95f9ebe5f71745b4fb8e3ed9 Mon Sep 17 00:00:00 2001 From: unfa Date: Mon, 23 Aug 2021 01:57:47 +0200 Subject: [PATCH] Started implementing actual shooting and damage, added placeholder particle effects --- Game/Assets/Characters/Player.gd | 13 +++++ Game/Assets/Effects/Impact.gd | 20 ++++++++ Game/Assets/Effects/ImpactPlayer.tscn | 74 +++++++++++++++++++++++++++ Game/Assets/Effects/ImpactWall.tscn | 73 ++++++++++++++++++++++++++ Game/Assets/Weapons/Weapon.gd | 37 ++++++++++++-- Game/Main.gd | 2 +- 6 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 Game/Assets/Effects/Impact.gd create mode 100644 Game/Assets/Effects/ImpactPlayer.tscn create mode 100644 Game/Assets/Effects/ImpactWall.tscn diff --git a/Game/Assets/Characters/Player.gd b/Game/Assets/Characters/Player.gd index 36c458e..d5774a4 100644 --- a/Game/Assets/Characters/Player.gd +++ b/Game/Assets/Characters/Player.gd @@ -143,6 +143,14 @@ func _process(delta): elif not view_zoom_direction and view_zoom > view_zoom_target: view_zoom = max(view_zoom_target, view_zoom - delta * 4) +func damage(hp: int): + main.player_list.players[get_tree().network_peer.get_unique_id()].health -= hp + + if main.player_list.players[get_tree().network_peer.get_unique_id()].health <= 0: + die() + +func die(): + main.chat.rpc(&'chat_notification', "Player " + main.player_list.players[get_tree().network_peer.get_unique_id()].name + " is dead") func _physics_process(delta): # rpc_unreliable(&'set_global_transform', global_transform) @@ -197,6 +205,11 @@ func _physics_process(delta): gravity_vec.y = linear_velocity.y # update puppets +# if get_tree().network_peer.get_unique_id() == 1: +# rpc(&'update_movement', global_transform, head.get_rotation()) +# else: +# rpc_id(1, &'update_movement', global_transform, head.get_rotation()) +# rpc(&'update_movement', global_transform, head.get_rotation()) # (stair) climbing diff --git a/Game/Assets/Effects/Impact.gd b/Game/Assets/Effects/Impact.gd new file mode 100644 index 0000000..816f398 --- /dev/null +++ b/Game/Assets/Effects/Impact.gd @@ -0,0 +1,20 @@ +extends Node3D + + +# Declare member variables here. Examples: +# var a = 2 +# var b = "text" + + +# Called when the node enters the scene tree for the first time. +func _ready(): + $CPUParticles3D.emitting = true + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +#func _process(delta): +# pass + + +func _on_Timer_timeout(): + queue_free() diff --git a/Game/Assets/Effects/ImpactPlayer.tscn b/Game/Assets/Effects/ImpactPlayer.tscn new file mode 100644 index 0000000..d2302a8 --- /dev/null +++ b/Game/Assets/Effects/ImpactPlayer.tscn @@ -0,0 +1,74 @@ +[gd_scene load_steps=9 format=2] + +[ext_resource path="res://Assets/Effects/Impact.gd" type="Script" id=1] +[ext_resource path="res://Assets/Effects/Flame.png" type="Texture2D" id=2] + +[sub_resource type="StandardMaterial3D" id=7] +blend_mode = 3 +shading_mode = 0 +vertex_color_use_as_albedo = true +albedo_texture = ExtResource( 2 ) +billboard_mode = 3 +particles_anim_h_frames = 2 +particles_anim_v_frames = 2 +particles_anim_loop = false + +[sub_resource type="QuadMesh" id=2] +material = SubResource( 7 ) +size = Vector2(0.2, 0.2) + +[sub_resource type="Curve" id=3] +_data = [Vector2(0, 0.981818), 0.0, -1.7826, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] + +[sub_resource type="Gradient" id=8] +colors = PackedColorArray(1, 0, 0, 1, 1, 1, 1, 1) + +[sub_resource type="StandardMaterial3D" id=5] +blend_mode = 1 +shading_mode = 0 +albedo_color = Color(1, 0, 0.00784314, 1) +albedo_texture = ExtResource( 2 ) +uv1_scale = Vector3(0.5, 0.5, 1) + +[sub_resource type="QuadMesh" id=6] +material = SubResource( 5 ) +size = Vector2(0.25, 0.25) + +[node name="Impact" type="Node3D"] +script = ExtResource( 1 ) + +[node name="CPUParticles3D" type="CPUParticles3D" parent="."] +emitting = false +amount = 32 +lifetime = 3.0 +one_shot = true +explosiveness = 1.0 +local_coords = false +mesh = SubResource( 2 ) +particle_flag_rotate_y = true +direction = Vector3(0, 1, 0) +spread = 180.0 +initial_velocity = 8.0 +damping = 5.0 +angle = 360.0 +angle_random = 1.0 +scale_amount = 1.5 +scale_amount_random = 1.0 +scale_amount_curve = SubResource( 3 ) +color_ramp = SubResource( 8 ) +script = null + +[node name="Timer" type="Timer" parent="."] +wait_time = 15.0 +one_shot = true +autostart = true +script = null + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0.00379224, 0) +visible = false +mesh = SubResource( 6 ) +surface_material_override/0 = null +script = null + +[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] diff --git a/Game/Assets/Effects/ImpactWall.tscn b/Game/Assets/Effects/ImpactWall.tscn new file mode 100644 index 0000000..f7faeac --- /dev/null +++ b/Game/Assets/Effects/ImpactWall.tscn @@ -0,0 +1,73 @@ +[gd_scene load_steps=9 format=2] + +[ext_resource path="res://Assets/Effects/Impact.gd" type="Script" id=1] +[ext_resource path="res://Assets/Effects/Flame.png" type="Texture2D" id=2] + +[sub_resource type="StandardMaterial3D" id=1] +blend_mode = 1 +shading_mode = 0 +vertex_color_use_as_albedo = true +albedo_texture = ExtResource( 2 ) +billboard_mode = 3 +particles_anim_h_frames = 2 +particles_anim_v_frames = 2 +particles_anim_loop = false + +[sub_resource type="QuadMesh" id=2] +material = SubResource( 1 ) +size = Vector2(0.2, 0.2) + +[sub_resource type="Curve" id=3] +_data = [Vector2(0, 0.981818), 0.0, -1.7826, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] + +[sub_resource type="Gradient" id=4] +offsets = PackedFloat32Array(0, 0.06, 0.14, 0.26, 0.675, 1) +colors = PackedColorArray(1, 1, 1, 1, 1, 0.96283, 0.660156, 1, 1, 0.827423, 0.238281, 1, 1, 0.509949, 0.152344, 1, 0.34375, 0.0725098, 0, 1, 0.035, 0.035, 0.035, 1) + +[sub_resource type="StandardMaterial3D" id=5] +blend_mode = 1 +shading_mode = 0 +albedo_color = Color(1, 0, 0.00784314, 1) +albedo_texture = ExtResource( 2 ) +uv1_scale = Vector3(0.5, 0.5, 1) + +[sub_resource type="QuadMesh" id=6] +material = SubResource( 5 ) +size = Vector2(0.25, 0.25) + +[node name="Impact" type="Node3D"] +script = ExtResource( 1 ) + +[node name="CPUParticles3D" type="CPUParticles3D" parent="."] +emitting = false +amount = 32 +one_shot = true +explosiveness = 1.0 +local_coords = false +mesh = SubResource( 2 ) +particle_flag_rotate_y = true +direction = Vector3(0, 1, 0) +spread = 180.0 +initial_velocity = 8.0 +damping = 5.0 +angle = 360.0 +angle_random = 1.0 +scale_amount = 1.5 +scale_amount_random = 1.0 +scale_amount_curve = SubResource( 3 ) +color_ramp = SubResource( 4 ) +script = null + +[node name="Timer" type="Timer" parent="."] +wait_time = 15.0 +one_shot = true +autostart = true +script = null + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0.00379224, 0) +mesh = SubResource( 6 ) +surface_material_override/0 = null +script = null + +[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"] diff --git a/Game/Assets/Weapons/Weapon.gd b/Game/Assets/Weapons/Weapon.gd index 8f7866e..e46793e 100644 --- a/Game/Assets/Weapons/Weapon.gd +++ b/Game/Assets/Weapons/Weapon.gd @@ -1,11 +1,14 @@ extends Node3D #Hand Camera Head Player @onready var player = get_parent().get_parent().get_parent().get_parent() +@onready var camera = get_parent().get_parent() @onready var ejector = find_node("Ejector") @onready var muzzle = find_node("Muzzle") var casing = preload("res://Assets/Weapons/Handgun/Casing.tscn") var flash = preload("res://Assets/Weapons/Handgun/Flash.tscn") +var impact_wall = preload("res://Assets/Effects/ImpactWall.tscn") +var impact_player = preload("res://Assets/Effects/ImpactPlayer.tscn") # Declare member variables here. Examples: # var a = 2 @@ -13,10 +16,38 @@ var flash = preload("res://Assets/Weapons/Handgun/Flash.tscn") #enum Trigger {TRIGGER_PRIMARY, TRIGGER_SECONDARY} +@remotesync func shoot(): + var space_state = get_world_3d().direct_space_state + + var from = camera.get_global_transform().origin + var aim = - camera.get_global_transform().basis[2] + var to = from + (aim * 1000) + + var ray = space_state.intersect_ray(from, to, [player]) + + var impact_vfx + + if ray['collider'].has_method(&'damage'): + if get_tree().network_peer.get_unique_id() == 1: # make sure this can only run on the server + ray['collider'].damage(10) + impact_vfx = impact_player.instantiate() + else: + impact_vfx = impact_wall.instantiate() + + impact_vfx.global_transform = impact_vfx.global_transform.looking_at(ray['normal']) + impact_vfx.global_transform.origin = ray['position'] + + get_tree().root.add_child(impact_vfx) + + print(ray) + @puppetsync func trigger(index: int, active: bool) -> void: #print("Weapon " + str(name) + ", Trigger " + str(index) + ", active: " + str(active)) - if index == 0 and active: + if index == 0 and active and $Handgun/AnimationPlayer.is_playing() == false: + + rpc(&'shoot') # server will evaluate if I hit my target + $Handgun/AnimationPlayer.play("Shoot", 0, 2.5) @@ -40,9 +71,9 @@ var flash = preload("res://Assets/Weapons/Handgun/Flash.tscn") casing_instance.global_transform = ejector.global_transform.translated(player.linear_velocity / 30) #approximating delta #casing_instance.rotate_object_local(Vector3.FORWARD, deg2rad(90)) #casing_instance.angular_velocity = - ejector.global_transform.basis[2] * randf_range(13, 17) + + # TODO correct the ejection angle - right now it shoots straight up relative to the gun casing_instance.linear_velocity = ejector.global_transform.basis[0] * randf_range(6.2, 8.5)# - ejector.global_transform.basis[2] * randf_range(-1.2, -1.7) + player.linear_velocity - - # Called when the node enters the scene tree for the first time. func _ready(): diff --git a/Game/Main.gd b/Game/Main.gd index 6e42bc5..2b08e55 100644 --- a/Game/Main.gd +++ b/Game/Main.gd @@ -162,7 +162,7 @@ func _input(_event) -> void: elif get_tree().network_peer.get_unique_id() == 1: for i in player_list.players.keys(): #notify existing players the new one has joined # if i != pid: - chat.rpc(i, &'chat_notification', "Player [b]" + new_info.name + "[/b] joined") + chat.rpc_id(i, &'chat_notification', "Player [b]" + new_info.name + "[/b] joined") if get_tree().network_peer.get_unique_id() == 1: # if we're server, we should store this pid = get_tree().get_rpc_sender_id() #disallow clients setting player_info for other players than themselves