diff --git a/client/animations/kick_1.tres b/client/animations/kick_1.tres
index b7e098a6671addb04cdd2d5b37c842c301cae876..8c4759d557b0f06af182833a2c2a27935fb48c9a 100644
--- a/client/animations/kick_1.tres
+++ b/client/animations/kick_1.tres
@@ -2,7 +2,7 @@
 
 [resource]
 resource_name = "ArmatureAction"
-length = 0.6
+length = 0.75
 tracks/0/type = "transform"
 tracks/0/path = NodePath(".:belly_0")
 tracks/0/interp = 1
diff --git a/client/animations/punch_1.tres b/client/animations/punch_1.tres
index ad7e2368ff367e45b21935c825a9870faaf831c8..d8643f315df4aea80b0ed2765e9f1da0ed47f47a 100644
--- a/client/animations/punch_1.tres
+++ b/client/animations/punch_1.tres
@@ -2,7 +2,7 @@
 
 [resource]
 resource_name = "ArmatureAction"
-length = 0.55
+length = 0.6
 tracks/0/type = "transform"
 tracks/0/path = NodePath(".:belly_0")
 tracks/0/interp = 1
diff --git a/client/levels/test/game.gd b/client/levels/test/game.gd
index 2bb3e909d73deef6d429c19a2a1814d7dac9b45a..614d3e1f5f4e0b498444bfc8552fa59f1d27112f 100644
--- a/client/levels/test/game.gd
+++ b/client/levels/test/game.gd
@@ -8,7 +8,11 @@ var jumpId:int = 0              # Distinguish 2 different jumps
 var sprintInput:bool = false
 
 # Attacks
-enum {NONE=0, PRIMARY=1, SECONDARY=2}
+enum {
+	NONE=0,
+	PUNCH=1,
+	KICK=2
+}
 
 func _physics_process(_delta):
 	getPlayerInput()
@@ -36,10 +40,10 @@ func getPlayerInput():
 		sprintInput = false
 
 	if Input.is_action_pressed("primaryAttack"):
-		attackStateInput = PRIMARY
+		attackStateInput = PUNCH
 
 	elif Input.is_action_pressed("secondaryAttack"):
-		attackStateInput = SECONDARY
+		attackStateInput = KICK
 
 	# Sent without safety resend
 	rpc_unreliable_id(1, "sendPlayerInputs", movementInput, jumpInput, jumpId, sprintInput, attackStateInput)
diff --git a/server/autoloads/gamestate.gd b/server/autoloads/gamestate.gd
index 12fa5c5cc13dadc16bd0e053b1a6ba26c7cd0509..86335ac197a32f6d378329e86b9a4f6df192dc8b 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/Class1/class1.gd b/server/entities/characters/Class1/class1.gd
index 8eaeed2abf9c5dcb02ba26cd32d9fef3ef6decae..056b0051516876400a570c2168d7bb8a22b9aba9 100644
--- a/server/entities/characters/Class1/class1.gd
+++ b/server/entities/characters/Class1/class1.gd
@@ -7,5 +7,5 @@ func _ready():
 
 
 # Called every frame. 'delta' is the elapsed time since the previous frame.
-#func _process(delta):
-#	pass
\ No newline at end of file
+# func _process(delta):
+#	  pass
diff --git a/server/entities/characters/player.gd b/server/entities/characters/player.gd
index 25a3a4c54ac14257a31c133cd1ceeb4fd828ac6e..96bad2f44a3b3475e2f76ac734da418429fdf5c0 100644
--- a/server/entities/characters/player.gd
+++ b/server/entities/characters/player.gd
@@ -44,30 +44,48 @@ var isAttacking:bool = false
 onready var attackTimer:Tween = $attackTween
 
 # attack type
-enum {NONE=0, PRIMARY=1, SECONDARY=2}
+enum {
+	NONE = 0,
+	PUNCH = 1,
+	KICK = 2
+}
+enum {
+	ID_PUNCH_1 = 0,
+	ID_PUNCH_2 = 1,
+	ID_KICK_1 = 2,
+	ID_KICK_2 = 3,
+	ID_KICK_JUMP_SIDE = 4
+}
 var lastPunchId:int = 0     # Detect a new punch (of any type)
-var idleTime:float = 0      # Stun when hitted + prevent spam
-
-# Primary attack parameters
-onready var primaryHitArea:Area = $primaryHitArea
-var primaryAttackDmg:float = 15.0
-var primaryAttackDist:float = 1.2
-var primaryAttackDuration:float = 0.5
+var idleTime:float = 0      # Stun when hit + prevent spam
+
+# Punch attack parameters
+onready var punchHitArea:Area = $punchHitArea
+var punchAttackDmg:float = 5.0
+var punchAttackDist:float = 1.2
+var punchAttackWait:float = 0.6
+var punch1AttackDuration:float = 0.1
+var punch2AttackDuration:float = 0.4
 # General direction (normalized anyway)
-var primaryAttackDirection:Vector3 = Vector3(3,1,0)
+var punchAttackDirection:Vector3 = Vector3(1,1.5,0)
 # Strength of the attack (multiply the normalized vector)
-var primaryAttackStrength:float = 1.5
-
-# Secondary attack parameters
-onready var secondaryHitArea:Area = $secondaryHitArea
-var secondaryAttackDmg:float = 5.0
-var secondaryAttackDist:float = 1.2
-var secondaryAttackDuration:float = 0.5
-var secondaryAttackDirection:Vector3 = Vector3(1,5,0)
-var secondaryAttackStrength:float = 0.8
+var punchAttackStrength:float = 0.5
+
+# Kick attack parameters
+onready var kickHitArea:Area = $kickHitArea
+var kickAttackDmg:float = 10.0
+var kick1AttackDist:float = 1.7
+var kick2AttackDist:float = 1.4
+var kickJumpSideAttackDist:float = 1.2
+var kickAttackWait:float = 0.75
+var kick1AttackDuration:float = 0.2
+var kick2AttackDuration:float = 0.3
+var kickJumpSideAttackDuration:float = 0.3
+var kickAttackDirection:Vector3 = Vector3(1.2,1,0)
+var kickAttackStrength:float = 1
 
 # Health points related values
-var hp:float = 0.0
+var hp:int = 0
 
 ######## ANIMATIONS ########
 
@@ -207,7 +225,9 @@ func processMovement(delta:float):
 
 # Send the position of the player
 func broadcastMovement():
-	rpc("getRemoteMovement", self.get_translation())
+	var position = self.get_translation()
+	position.z = 0
+	rpc("getRemoteMovement", position)
 
 
 # Check and trigger the type of attack requested
@@ -217,58 +237,77 @@ func processAttack(attackType:int):
 
 	# Use the right function
 	match attackType:
-		PRIMARY:
-			primaryAttack()
+		PUNCH:
 			if self.is_on_floor():
 				if (!animSequence):
 					broadcastAnimation(ANIM_PUNCH_1)
 					animSequence = 1
+					attack(ID_PUNCH_1)
 				else:
 					broadcastAnimation(ANIM_PUNCH_2)
 					animSequence = 0
+					attack(ID_PUNCH_2)
 			else:
 				broadcastAnimation(ANIM_JUMP_KICK_SIDE)
-		SECONDARY:
-			secondaryAttack()
+				attack(ID_KICK_JUMP_SIDE)
+		KICK:
 			if self.is_on_floor():
 				if (!animSequence):
 					broadcastAnimation(ANIM_KICK_1)
 					animSequence = 1
+					attack(ID_KICK_1)
 				else:
 					broadcastAnimation(ANIM_KICK_2)
 					animSequence = 0
+					attack(ID_KICK_2)
+			else:
+				broadcastAnimation(ANIM_JUMP_KICK_SIDE)
+				attack(ID_KICK_JUMP_SIDE)
+
 
+func attack(idAttack:int):
+	var hitArea:Area
+	var distance:float
+	var wait:float
+	var duration:float
 
-func primaryAttack():
+	if (idAttack == ID_PUNCH_1 || idAttack == ID_PUNCH_2):
+		hitArea = punchHitArea
+		distance = punchAttackDist
+		wait = punchAttackWait
+		if (idAttack == ID_PUNCH_1):
+			duration = punch1AttackDuration
+		else:
+			duration = punch2AttackDuration
+	else:
+		hitArea = kickHitArea
+		wait = kickAttackWait
+		if (idAttack == ID_KICK_1):
+			distance = kick1AttackDist
+			duration = kick1AttackDuration
+		elif (idAttack == ID_KICK_2):
+			distance = kick2AttackDist
+			duration = kick2AttackDuration
+		else:
+			distance = kickJumpSideAttackDist
+			duration = kickJumpSideAttackDuration
+	
 	# Set active the hitbox of the attack, its visual feedback on server
-	primaryHitArea.set_monitoring(true)
-	primaryHitArea.set_visible(true)
+	hitArea.set_monitoring(true)
+	hitArea.set_visible(true)
 
 	# Prepare the translation as an interpolation over time (end position, duration and function used)
-	attackTimer.interpolate_property(primaryHitArea, "translation:x", 0, primaryAttackDist, primaryAttackDuration, Tween.TRANS_LINEAR, Tween.EASE_IN)
+	attackTimer.interpolate_property(hitArea, "translation:x", 0, distance, duration, Tween.TRANS_LINEAR, Tween.EASE_OUT)
 	attackTimer.start()
-
-	# Once the movement is finished, turn off the hitbox and visual feedback
 	yield(attackTimer, "tween_completed")
-	isAttacking = false
-	primaryHitArea.set_monitoring(false)
-	primaryHitArea.set_visible(false)
-
-
-func secondaryAttack():
-	# Set active the hitbox of the attack, its visual feedback on server
-	secondaryHitArea.set_monitoring(true)
-	secondaryHitArea.set_visible(true)
-
-	# Prepare the translation as an interpolation over time (end position, duration and function used)
-	attackTimer.interpolate_property(secondaryHitArea, "translation:x", 0, secondaryAttackDist, secondaryAttackDuration, Tween.TRANS_LINEAR, Tween.EASE_IN)
+	hitArea.set_monitoring(false)
+	attackTimer.interpolate_property(hitArea, "translation:x", distance, 0, wait-duration, Tween.TRANS_LINEAR, Tween.EASE_OUT)
 	attackTimer.start()
 
 	# Once the movement is finished, turn off the hitbox and visual feedback
 	yield(attackTimer, "tween_completed")
-	secondaryHitArea.set_monitoring(false)
-	secondaryHitArea.set_visible(false)
 	isAttacking = false
+	hitArea.set_visible(false)
 
 
 # Called when detected by an attack's hitbox
@@ -292,11 +331,11 @@ func hurt(damages:int, sourceId:int, direction:Vector3, strength:float):
 	lastStrikerId = sourceId
 
 	# Feedback on the player's client
-	broadcastHp(hp)
+	broadcastHp()
 
 
 # Send Hp
-func broadcastHp(hp:int):
+func broadcastHp():
 	rpc("hurt", hp)
 
 # Make player die
@@ -315,7 +354,8 @@ func broadcastAnimation(animationType:int):
 ######## SIGNALS ########
 
 # General function on attack's hitboxes
-func _on_generalHitArea_entered(damageVar:int, directionVar:Vector3, strengthVar:float, body:Node):
+func _on_generalHitArea_entered(damageVar:int, directionVar:Vector3,
+strengthVar:float, body:Node):
 	# Don't hurt yourself
 	if int(body.name)==ownId:
 		return
@@ -326,17 +366,19 @@ func _on_generalHitArea_entered(damageVar:int, directionVar:Vector3, strengthVar
 	# Rotate the vector depending on the player orientation
 	direction.x*=bodyRotation
 
-	print("body named " + body.name + " hit: primary")
+	print("body named " + body.name + " hit: punch")
 
 	# Call the function on the affected player
 	body.hurt(damageVar, ownId, direction, strengthVar)
 
 
-# Primary hit has landed on something
-func _on_primaryHitArea_body_entered(body:Node):
-	_on_generalHitArea_entered(primaryAttackDmg, primaryAttackDirection, primaryAttackStrength, body)
+# punch hit has landed on something
+func _on_punchHitArea_body_entered(body:Node):
+	_on_generalHitArea_entered(punchAttackDmg, punchAttackDirection,
+	punchAttackStrength, body)
 
 
-# Secondary hit has landed on something
-func _on_secondaryHitArea_body_entered(body:Node):
-	_on_generalHitArea_entered(secondaryAttackDmg, secondaryAttackDirection, secondaryAttackStrength, body)
+# kick hit has landed on something
+func _on_kickHitArea_body_entered(body:Node):
+	_on_generalHitArea_entered(kickAttackDmg, kickAttackDirection,
+	kickAttackStrength, body)
diff --git a/server/entities/characters/player.tscn b/server/entities/characters/player.tscn
index 244644766cdd4e0216e022a8cb51cd11c394212c..8473d5a1a977178bcc4227f120ec632ead6f1005 100644
--- a/server/entities/characters/player.tscn
+++ b/server/entities/characters/player.tscn
@@ -1,12 +1,21 @@
-[gd_scene load_steps=4 format=2]
+[gd_scene load_steps=8 format=2]
 
 [ext_resource path="res://entities/characters/Class1/class1.gd" type="Script" id=1]
 
 [sub_resource type="BoxShape" id=1]
-extents = Vector3( 0.175, 0.275, 0.7 )
+extents = Vector3( 0.176075, 0.674417, 0.351434 )
 
-[sub_resource type="BoxShape" id=2]
-extents = Vector3( 0.544245, 0.192381, 0.312851 )
+[sub_resource type="CubeMesh" id=2]
+
+[sub_resource type="SphereMesh" id=3]
+
+[sub_resource type="CubeMesh" id=4]
+
+[sub_resource type="ConvexPolygonShape" id=5]
+points = PoolVector3Array( -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1 )
+
+[sub_resource type="ConvexPolygonShape" id=6]
+points = PoolVector3Array( -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1 )
 
 [node name="player" type="KinematicBody"]
 transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -0.0033226, -0.0126846, 0.0060811 )
@@ -15,54 +24,54 @@ collision_mask = 3
 script = ExtResource( 1 )
 
 [node name="collisionShape" type="CollisionShape" parent="."]
-transform = Transform( 1, 0, 0, 0, 0, -1, 0, 1, 0, 0, 0.65, 0 )
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.678055, 0 )
 shape = SubResource( 1 )
 
 [node name="model" type="Spatial" parent="."]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.67638e-08, 0 )
 
-[node name="CSGBox" type="CSGBox" parent="model"]
-transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.513621, 0 )
-width = 0.35
-height = 1.05787
-depth = 0.684
+[node name="body" type="MeshInstance" parent="model"]
+transform = Transform( 0.174564, 0, 0, 0, 0.532433, 0, 0, 0, 0.360351, 0, 0.545559, 0 )
+mesh = SubResource( 2 )
+material/0 = null
 
-[node name="CSGSphere" type="CSGSphere" parent="model"]
-transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.17856, 0 )
-radius = 0.2
-radial_segments = 24
+[node name="head" type="MeshInstance" parent="model"]
+transform = Transform( 0.177349, 0, 0, 0, 0.177349, 0, 0, 0, 0.177349, 0, 1.19631, 0 )
+mesh = SubResource( 3 )
+material/0 = null
 
-[node name="primaryHitArea" type="Area" parent="."]
+[node name="punchHitArea" type="Area" parent="."]
+transform = Transform( 1, 0, 0, 0, 0.640341, 0, 0, 0, 1, 0, 0.892016, 0 )
 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="punchMesh" type="MeshInstance" parent="punchHitArea"]
+transform = Transform( 0.130706, 0, 0, 0, 0.179953, 0, 0, 0, 0.320349, 0, 0, 0 )
+mesh = SubResource( 4 )
+material/0 = null
 
-[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="punchCollider" type="CollisionShape" parent="punchHitArea"]
+transform = Transform( 0.130706, 0, 0, 0, 0.179953, 0, 0, 0, 0.320349, 0, 0, 0 )
+shape = SubResource( 5 )
 
-[node name="secondaryHitArea" type="Area" parent="."]
+[node name="kickHitArea" type="Area" parent="."]
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.730753, 0 )
 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="kickMesh" type="MeshInstance" parent="kickHitArea"]
+transform = Transform( 0.130706, 0, 0, 0, 0.115231, 0, 0, 0, 0.320349, 0, 0, 0 )
+mesh = SubResource( 4 )
+material/0 = null
 
-[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="kickCollider" type="CollisionShape" parent="kickHitArea"]
+transform = Transform( 0.130706, 0, 0, 0, 0.115231, 0, 0, 0, 0.320349, 0, 0.161263, 0 )
+shape = SubResource( 6 )
 
 [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"]
+[connection signal="body_entered" from="punchHitArea" to="." method="_on_punchHitArea_body_entered"]
+[connection signal="body_entered" from="kickHitArea" to="." method="_on_kickHitArea_body_entered"]