From 3e3067733805c7a3910d7a67d260dfdfff771c9c Mon Sep 17 00:00:00 2001
From: Canopteks <thomas.duhamel@protonmail.com>
Date: Sun, 23 Feb 2020 23:42:10 +0100
Subject: [PATCH] moving hitboxes and feedbacks on serv and clients

---
 client/autoloads/gamestate.gd          | 14 ++--
 client/entities/characters/player.gd   |  7 +-
 client/entities/characters/player.tscn |  1 +
 client/levels/lobby/lobby.gd           |  4 +-
 client/levels/test/game.gd             | 13 +++-
 client/project.godot                   | 10 +++
 server/autoloads/gamestate.gd          |  2 +-
 server/entities/characters/player.gd   | 99 ++++++++++++++++++++++++--
 server/entities/characters/player.tscn | 45 +++++++++++-
 server/levels/test/bloc/bloc.tscn      |  1 +
 server/levels/test/game.gd             |  4 +-
 server/levels/test/game.tscn           |  2 -
 server/project.godot                   |  5 ++
 13 files changed, 180 insertions(+), 27 deletions(-)

diff --git a/client/autoloads/gamestate.gd b/client/autoloads/gamestate.gd
index 2d65ccd..86ce275 100644
--- a/client/autoloads/gamestate.gd
+++ b/client/autoloads/gamestate.gd
@@ -11,11 +11,11 @@ signal server_disconnected
 
 func joinServer(ip, port):
 	# Create the network client
-	var peer_join = NetworkedMultiplayerENet.new()
+	var peer_join:NetworkedMultiplayerENet = NetworkedMultiplayerENet.new()
 	peer_join.create_client(ip, int(port))
 	get_tree().set_network_peer(peer_join)
 	
-	print("Trying to join the server ", ip, ":", port) 
+	print("Trying to join the server ", ip, ":", port, " with id: ", get_tree().get_network_unique_id()) 
 
 
 puppet func registerPlayer(id): 
@@ -37,8 +37,8 @@ puppet func startGame():
 
 	get_node("/root/lobby").hide()
 	
-	var game = preload("res://levels/test/game.tscn").instance()
-	var player_scene = preload("res://entities/characters/player.tscn")
+	var game:Node = preload("res://levels/test/game.tscn").instance()
+	var player_scene:PackedScene = preload("res://entities/characters/player.tscn")
 	get_tree().get_root().add_child(game)
 	
 	# TODO: check (and perhaps) the scene changing functionality
@@ -47,16 +47,16 @@ puppet func startGame():
 	#Next evey player will spa every other player including the server's own client! Try to move this to server only 
 	var i = 1
 	for peer_id in players:
-		var player = player_scene.instance()
+		var player:Node = player_scene.instance()
 		
 		player.set_name(str(peer_id))
 		get_node(GAMEPATH).add_child(player)
 			
 		
-		var spawnPosition = get_node("/root/game/spawnCollection/spawn"+str(i)).get_translation()
+		var spawnPosition:Vector3 = get_node("/root/game/spawnCollection/spawn"+str(i)).get_translation()
 		player.translate(spawnPosition)
 		
 		i+=1
 		
-	var playerArrow = preload("res://entities/characters/playerArrow.tscn").instance()
+	var playerArrow:Node = preload("res://entities/characters/playerArrow.tscn").instance()
 	get_node(GAMEPATH+str(get_tree().get_network_unique_id())).add_child(playerArrow)
\ No newline at end of file
diff --git a/client/entities/characters/player.gd b/client/entities/characters/player.gd
index b1de2aa..71c73b5 100644
--- a/client/entities/characters/player.gd
+++ b/client/entities/characters/player.gd
@@ -1,5 +1,8 @@
 extends KinematicBody
 
 # Update the player's position based on the position computed by the remote scene on the server
-puppet func getRemoteMovement(position):
-	self.set_translation(position)
\ No newline at end of file
+puppet func getRemoteMovement(position:Vector3):
+	self.set_translation(position)
+	
+puppet func hurt(damages:int):
+	print("You suffered a hit and lost "+str(damages)+" HPs !")
\ No newline at end of file
diff --git a/client/entities/characters/player.tscn b/client/entities/characters/player.tscn
index 27fb14f..1d62a17 100644
--- a/client/entities/characters/player.tscn
+++ b/client/entities/characters/player.tscn
@@ -6,6 +6,7 @@
 script = ExtResource( 1 )
 
 [node name="Model" type="Spatial" parent="."]
+editor/display_folded = true
 
 [node name="CSGBox" type="CSGBox" parent="Model"]
 transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.513621, 0 )
diff --git a/client/levels/lobby/lobby.gd b/client/levels/lobby/lobby.gd
index 0603a64..3c453e0 100644
--- a/client/levels/lobby/lobby.gd
+++ b/client/levels/lobby/lobby.gd
@@ -10,13 +10,13 @@ func _ready():
 func _on_joinButton_pressed():
 	
 	# Get and check the Ip
-	var ip = get_node("menu/ipLineEdit").text
+	var ip:String = get_node("menu/ipLineEdit").text
 	if not ip.is_valid_ip_address():
 		get_node("menu/errorLabel").text = "Invalid IPv4 address!"
 		return
 
 	# Get and check the port
-	var port = get_node("menu/portLineEdit").text
+	var port:String = get_node("menu/portLineEdit").text
 	if port == "":
 		get_node("menu/errorLabel").text = "Invalid port!"
 		return
diff --git a/client/levels/test/game.gd b/client/levels/test/game.gd
index 4209e3a..fbe0ce8 100644
--- a/client/levels/test/game.gd
+++ b/client/levels/test/game.gd
@@ -1,14 +1,19 @@
 extends Node
 
+# Movements
 var movementInput:int = 0
 var jumpInput:bool = false
 var sprintInput:bool = false
 
+# Attacks
+enum {NONE=0, PRIMARY=1, SECONDARY=2}
+
 func _physics_process(delta):
 	getPlayerInput()
 	
 func getPlayerInput():
 	movementInput = 0
+	var attackStateInput:int = NONE
 		
 	if Input.is_action_pressed("movementLeft"):
 		movementInput -= 1
@@ -24,6 +29,12 @@ func getPlayerInput():
 		sprintInput = true
 	else:
 		sprintInput = false
+		
+	if Input.is_action_pressed("primaryAttack"):
+		attackStateInput = PRIMARY
+	
+	elif Input.is_action_pressed("secondaryAttack"):
+		attackStateInput = SECONDARY
 	
 	# Sent without safety resend
-	rpc_unreliable_id(1, "sendPlayerInputs", movementInput, sprintInput, jumpInput)
\ No newline at end of file
+	rpc_unreliable_id(1, "sendPlayerInputs", movementInput, sprintInput, jumpInput, attackStateInput)
\ No newline at end of file
diff --git a/client/project.godot b/client/project.godot
index 8048c79..936fcb6 100644
--- a/client/project.godot
+++ b/client/project.godot
@@ -48,6 +48,16 @@ movementSprint={
 "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":16777237,"unicode":0,"echo":false,"script":null)
  ]
 }
+primaryAttack={
+"deadzone": 0.5,
+"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"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":1,"pressed":false,"doubleclick":false,"script":null)
+ ]
+}
+secondaryAttack={
+"deadzone": 0.5,
+"events": [ Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"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":2,"pressed":false,"doubleclick":false,"script":null)
+ ]
+}
 
 [rendering]
 
diff --git a/server/autoloads/gamestate.gd b/server/autoloads/gamestate.gd
index d28868e..af0a0e0 100644
--- a/server/autoloads/gamestate.gd
+++ b/server/autoloads/gamestate.gd
@@ -3,7 +3,7 @@ extends Node
 const GAMEPATH = "/root/game/"
 
 const PORT = 10001
-const MAX_CLIENTS = 1
+const MAX_CLIENTS = 2
 
 var players = {}
 
diff --git a/server/entities/characters/player.gd b/server/entities/characters/player.gd
index 81c4de8..88004aa 100644
--- a/server/entities/characters/player.gd
+++ b/server/entities/characters/player.gd
@@ -1,5 +1,12 @@
 extends KinematicBody
 
+onready var ownId = self.name
+
+######## MOVEMENT AND POSITION VARS ########
+
+# The side faced by the player
+var orientation:int = 1
+
 # Speed values
 const MAX_SPEED:float = 8.0
 const MAX_SPRINT_SPEED:float = 12.0
@@ -23,19 +30,39 @@ var vel:Vector3 = Vector3()
 # move_and_slide need that
 const FLOOR_NORMAL:Vector3 = Vector3(0,1,0)
 
+######### ATTACKS VARS ########
+
+# l2r
+var isAttacking:bool = false
+# attack type
+enum {NONE=0, PRIMARY=1, SECONDARY=2}
+# attacks related nodes
+onready var attackTimer:Tween = $attackTween
+onready var primaryHitArea:Area = $primaryHitArea
+onready var secondaryHitArea:Area = $secondaryHitArea
+
+######## FUNCTIONS ########
 
 # called by the engine
 func _physics_process(delta):
 	processMovement(delta)
-	broadcastMovement(delta)
+	broadcastMovement()
 
 # Called from the game script to update the vars
-func getPlayerInputs(movementInput, sprintInput, jumpInput):
+func getPlayerInputs(movementInput, sprintInput, jumpInput, attackTypeInput):
 	motion = movementInput
+	orientation = movementInput if movementInput!=0 else orientation
 	isSprinting = sprintInput
 	isJumping = jumpInput
+	if !isAttacking && attackTypeInput:
+		processAttack(attackTypeInput)
 	
 func processMovement(delta):
+	if orientation == 1:
+		set_rotation_degrees(Vector3(0,0,0))
+	else: 
+		set_rotation_degrees(Vector3(0,180,0))
+	
 	if self.is_on_floor():
 		if isJumping:
 			vel.y = JUMP_SPEED
@@ -44,7 +71,7 @@ func processMovement(delta):
 	vel.y += delta * GRAVITY
 	
 	# Speed of the player
-	var target = Vector3(motion, 0, 0)
+	var target:Vector3 = Vector3(motion, 0, 0)
 	
 	if isSprinting:
 		target *= MAX_SPRINT_SPEED
@@ -52,7 +79,7 @@ func processMovement(delta):
 		target *= MAX_SPEED
 	
 	# Acceleration of the player if he is moving horizontally
-	var accel
+	var accel:float
 	var hvel:Vector3 = Vector3(vel.x,0,0)
 	if target.dot(hvel)>0:
 		if isSprinting:
@@ -68,6 +95,64 @@ func processMovement(delta):
 	# Update the velocity after the collisions (physical engine ftw)
 	vel = self.move_and_slide(vel, FLOOR_NORMAL)
 	
-func broadcastMovement(delta):
-	# Send the position of the player
-	rpc("getRemoteMovement", self.get_translation())
\ No newline at end of file
+# Send the position of the player
+func broadcastMovement():
+	rpc("getRemoteMovement", self.get_translation())
+	
+# Check and trigger the type of attack requested
+func processAttack(attackType):
+	isAttacking = true
+	match attackType:
+		PRIMARY:
+			primaryAttack()
+		SECONDARY:
+			secondaryAttack()
+
+func primaryAttack():
+	primaryHitArea.set_monitoring(true)
+	primaryHitArea.set_visible(true)
+	var duration:float = 0.6
+	var distance:float = 1.2
+	
+	attackTimer.interpolate_property(primaryHitArea, "translation:x", 0, distance, duration, Tween.TRANS_BACK, Tween.EASE_IN)
+	attackTimer.start()
+	yield(attackTimer, "tween_completed")
+	
+	primaryHitArea.set_monitoring(false)
+	primaryHitArea.set_visible(false)
+	isAttacking = false
+	
+func secondaryAttack():
+	secondaryHitArea.set_monitoring(true)
+	secondaryHitArea.set_visible(true)
+	var duration:float = 0.3
+	var distance:float = 1.2
+	
+	attackTimer.interpolate_property(secondaryHitArea, "translation:x", 0, distance, duration, Tween.TRANS_BACK, Tween.EASE_IN)
+	attackTimer.start()
+	yield(attackTimer, "tween_completed")
+	
+	secondaryHitArea.set_monitoring(false)
+	secondaryHitArea.set_visible(false)
+	isAttacking = false
+	
+func hurt(damages):
+	rpc_id(int(ownId), "hurt", str(damages));
+
+######## SIGNALS ########
+
+# Primary hit has landed on something
+func _on_primaryHitArea_body_entered(body):
+	if body.name==ownId:
+		return
+	
+	print("body named "+body.name+" hit: primary")
+	body.hurt(30)
+
+# Secondary hit has landed on something
+func _on_secondaryHitArea_body_entered(body):
+	if body.name==ownId:
+		return
+	
+	print("body named "+body.name+" hit: secondary")
+
diff --git a/server/entities/characters/player.tscn b/server/entities/characters/player.tscn
index f8eba0f..e734fd8 100644
--- a/server/entities/characters/player.tscn
+++ b/server/entities/characters/player.tscn
@@ -1,13 +1,16 @@
-[gd_scene load_steps=3 format=2]
+[gd_scene load_steps=4 format=2]
 
 [ext_resource path="res://entities/characters/player.gd" type="Script" id=1]
 
-
-
 [sub_resource type="BoxShape" id=1]
 extents = Vector3( 0.175, 0.275, 0.7 )
 
+[sub_resource type="BoxShape" id=2]
+extents = Vector3( 0.544245, 0.192381, 0.312851 )
+
 [node name="Player" type="KinematicBody"]
+collision_layer = 2
+collision_mask = 3
 script = ExtResource( 1 )
 
 [node name="Body_CollisionShape" type="CollisionShape" parent="."]
@@ -26,3 +29,39 @@ depth = 0.684
 transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.17856, 0 )
 radius = 0.2
 radial_segments = 24
+
+[node name="primaryHitArea" type="Area" parent="."]
+visible = false
+monitoring = false
+collision_layer = 0
+collision_mask = 2
+
+[node name="primaryHitCol" type="CollisionShape" parent="primaryHitArea"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.420072, 0.815, 0 )
+shape = SubResource( 2 )
+
+[node name="primaryHitCSG" type="CSGBox" parent="primaryHitArea"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.419673, 0.815, 0 )
+width = 1.09437
+height = 0.400067
+depth = 0.618424
+
+[node name="secondaryHitArea" type="Area" parent="."]
+visible = false
+monitoring = false
+collision_layer = 0
+collision_mask = 2
+
+[node name="secondaryHitCol" type="CollisionShape" parent="secondaryHitArea"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.42, 0.2, 0 )
+shape = SubResource( 2 )
+
+[node name="secondaryHitCSG" type="CSGBox" parent="secondaryHitArea"]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0.42, 0.2, 0 )
+width = 1.09437
+height = 0.400067
+depth = 0.618424
+
+[node name="attackTween" type="Tween" parent="."]
+[connection signal="body_entered" from="primaryHitArea" to="." method="_on_primaryHitArea_body_entered"]
+[connection signal="body_entered" from="secondaryHitArea" to="." method="_on_secondaryHitArea_body_entered"]
diff --git a/server/levels/test/bloc/bloc.tscn b/server/levels/test/bloc/bloc.tscn
index 6d021e8..af80b4d 100644
--- a/server/levels/test/bloc/bloc.tscn
+++ b/server/levels/test/bloc/bloc.tscn
@@ -12,6 +12,7 @@ mesh = SubResource( 1 )
 material/0 = null
 
 [node name="StaticBody" type="StaticBody" parent="MeshInstance"]
+collision_mask = 2
 
 [node name="CollisionShape" type="CollisionShape" parent="MeshInstance/StaticBody"]
 shape = SubResource( 2 )
diff --git a/server/levels/test/game.gd b/server/levels/test/game.gd
index 6eb3b6b..0703762 100644
--- a/server/levels/test/game.gd
+++ b/server/levels/test/game.gd
@@ -1,7 +1,7 @@
 extends Node
 
-master func sendPlayerInputs(movementInput, jumpInput, sprintInput):
+master func sendPlayerInputs(movementInput, jumpInput, sprintInput, attackStateInput):
 	
 	# Get the input from a client and send it to the matchig remote player
 	var senderId = get_tree().get_rpc_sender_id()
-	gamestate.get_node("/root/game/"+str(senderId)).getPlayerInputs(movementInput, jumpInput, sprintInput)
\ No newline at end of file
+	gamestate.get_node("/root/game/"+str(senderId)).getPlayerInputs(movementInput, jumpInput, sprintInput, attackStateInput)
\ No newline at end of file
diff --git a/server/levels/test/game.tscn b/server/levels/test/game.tscn
index 6eff247..59b44e0 100644
--- a/server/levels/test/game.tscn
+++ b/server/levels/test/game.tscn
@@ -3,8 +3,6 @@
 [ext_resource path="res://levels/test/game.gd" type="Script" id=1]
 [ext_resource path="res://levels/test/bloc/bloc.tscn" type="PackedScene" id=2]
 
-
-
 [node name="game" type="Spatial"]
 script = ExtResource( 1 )
 
diff --git a/server/project.godot b/server/project.godot
index 73c0570..29dcf55 100644
--- a/server/project.godot
+++ b/server/project.godot
@@ -23,6 +23,11 @@ config/icon="res://icon.png"
 
 gamestate="*res://autoloads/gamestate.gd"
 
+[layer_names]
+
+3d_physics/layer_1="environment"
+3d_physics/layer_2="players"
+
 [rendering]
 
 environment/default_environment="res://default_env.tres"
-- 
GitLab