mirror of
https://gitlab.com/open-fpsz/open-fpsz.git
synced 2026-07-15 16:34:48 +00:00
✨ Implement Teams and disallow team damage in Rabbit
This commit is contained in:
parent
1a19e5edfa
commit
ac8bd2d07c
10 changed files with 46 additions and 23 deletions
|
|
@ -27,6 +27,6 @@ func _physics_process(_delta : float) -> void:
|
||||||
|
|
||||||
for area in get_overlapping_areas():
|
for area in get_overlapping_areas():
|
||||||
if area is HealthComponent and is_multiplayer_authority():
|
if area is HealthComponent and is_multiplayer_authority():
|
||||||
area.damage.rpc(damage, damage_dealer.player_id)
|
(area as HealthComponent).damage.rpc(damage, damage_dealer.player_id, damage_dealer.team_id)
|
||||||
|
|
||||||
set_physics_process(false)
|
set_physics_process(false)
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,9 @@ func _grab(flag : Flag) -> void:
|
||||||
_carried_flag = flag
|
_carried_flag = flag
|
||||||
show()
|
show()
|
||||||
|
|
||||||
func _release(inherited_velocity : Vector3, throw_speed : float) -> void:
|
func _release(inherited_velocity : Vector3, throw_speed : float, dropper : Player) -> void:
|
||||||
if _is_carrying():
|
if _is_carrying():
|
||||||
_carried_flag.drop()
|
_carried_flag.drop(dropper)
|
||||||
_carried_flag.rotation_degrees.x = 0.0
|
_carried_flag.rotation_degrees.x = 0.0
|
||||||
_carried_flag.linear_velocity = inherited_velocity + (global_basis.z * throw_speed)
|
_carried_flag.linear_velocity = inherited_velocity + (global_basis.z * throw_speed)
|
||||||
# Throw the flag from some distance in front of the player to avoid regrabbing mid-air
|
# Throw the flag from some distance in front of the player to avoid regrabbing mid-air
|
||||||
|
|
@ -55,8 +55,8 @@ func _sensor_on_body_entered(collider : Flag) -> void:
|
||||||
if collider is Flag:
|
if collider is Flag:
|
||||||
_grab(collider)
|
_grab(collider)
|
||||||
|
|
||||||
func drop() -> void:
|
func drop(dropper : Player) -> void:
|
||||||
_release(Vector3.ZERO, 0.0)
|
_release(Vector3.ZERO, 0.0, dropper)
|
||||||
|
|
||||||
func throw(inherited_velocity : Vector3) -> void:
|
func throw(inherited_velocity : Vector3, dropper : Player) -> void:
|
||||||
_release(inherited_velocity, max_throw_speed)
|
_release(inherited_velocity, max_throw_speed, dropper)
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ class_name HealthComponent extends Area3D
|
||||||
set(value):
|
set(value):
|
||||||
health = value
|
health = value
|
||||||
health_changed.emit(value)
|
health_changed.emit(value)
|
||||||
|
@export var _player : Player
|
||||||
|
|
||||||
signal health_zeroed(killer_id : int)
|
signal health_zeroed(killer_id : int)
|
||||||
signal health_changed(value : float)
|
signal health_changed(value : float)
|
||||||
|
|
@ -26,13 +27,16 @@ signal health_changed(value : float)
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
heal_full()
|
heal_full()
|
||||||
|
|
||||||
@rpc("call_local")
|
@rpc("call_local", "reliable")
|
||||||
func damage(amount : float, damage_dealer_id : int) -> void:
|
func damage(amount : float, damage_dealer_id : int, damage_dealer_team_id : int) -> void:
|
||||||
|
if damage_dealer_team_id == _player.team_id:
|
||||||
|
return
|
||||||
|
|
||||||
health = clampf(health - amount, 0.0, max_health)
|
health = clampf(health - amount, 0.0, max_health)
|
||||||
if health == 0.0:
|
if health == 0.0:
|
||||||
health_zeroed.emit(damage_dealer_id)
|
health_zeroed.emit(damage_dealer_id)
|
||||||
|
|
||||||
@rpc("call_local")
|
@rpc("call_local", "reliable")
|
||||||
func _heal(amount : float) -> void:
|
func _heal(amount : float) -> void:
|
||||||
health = clampf(health + amount, 0.0, max_health)
|
health = clampf(health + amount, 0.0, max_health)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ enum FlagState { FLAG_STATE_ON_STAND, FLAG_STATE_DROPPED, FLAG_STATE_TAKEN }
|
||||||
|
|
||||||
signal grabbed(grabber : Player)
|
signal grabbed(grabber : Player)
|
||||||
signal regrabbed
|
signal regrabbed
|
||||||
signal dropped
|
signal dropped(dropper : Player)
|
||||||
|
|
||||||
var last_carrier : Player = null
|
var last_carrier : Player = null
|
||||||
@onready var _mesh : Node = $Smoothing/Mesh
|
@onready var _mesh : Node = $Smoothing/Mesh
|
||||||
|
|
@ -24,9 +24,9 @@ func grab(grabber : Player) -> void:
|
||||||
else:
|
else:
|
||||||
regrabbed.emit()
|
regrabbed.emit()
|
||||||
|
|
||||||
func drop() -> void:
|
func drop(dropper : Player) -> void:
|
||||||
if flag_state == FlagState.FLAG_STATE_TAKEN:
|
if flag_state == FlagState.FLAG_STATE_TAKEN:
|
||||||
_mesh.show()
|
_mesh.show()
|
||||||
flag_state = FlagState.FLAG_STATE_DROPPED
|
flag_state = FlagState.FLAG_STATE_DROPPED
|
||||||
dropped.emit()
|
dropped.emit(dropper)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ enum PlayerState { PLAYER_ALIVE, PLAYER_DEAD }
|
||||||
set(id):
|
set(id):
|
||||||
player_id = id
|
player_id = id
|
||||||
$PlayerInput.set_multiplayer_authority(id)
|
$PlayerInput.set_multiplayer_authority(id)
|
||||||
|
@export var team_id : int = 1
|
||||||
@export var nickname : String
|
@export var nickname : String
|
||||||
|
|
||||||
@onready var input : PlayerInput = $PlayerInput
|
@onready var input : PlayerInput = $PlayerInput
|
||||||
|
|
@ -113,7 +114,7 @@ func _jump() -> void:
|
||||||
_jumping = true
|
_jumping = true
|
||||||
|
|
||||||
func _throw_flag() -> void:
|
func _throw_flag() -> void:
|
||||||
flag_carry_component.throw(linear_velocity)
|
flag_carry_component.throw(linear_velocity, self)
|
||||||
|
|
||||||
func is_on_floor() -> bool:
|
func is_on_floor() -> bool:
|
||||||
if shape_cast.is_colliding():
|
if shape_cast.is_colliding():
|
||||||
|
|
@ -228,12 +229,13 @@ func _is_player_dead() -> bool:
|
||||||
return player_state != PlayerState.PLAYER_ALIVE
|
return player_state != PlayerState.PLAYER_ALIVE
|
||||||
|
|
||||||
func die(killer_id : int) -> void:
|
func die(killer_id : int) -> void:
|
||||||
flag_carry_component.drop()
|
flag_carry_component.drop(self)
|
||||||
player_state = PlayerState.PLAYER_DEAD
|
player_state = PlayerState.PLAYER_DEAD
|
||||||
if _is_pawn():
|
if _is_pawn():
|
||||||
animation_player.play("death")
|
animation_player.play("death")
|
||||||
died.emit(self, killer_id)
|
died.emit(self, killer_id)
|
||||||
|
|
||||||
|
@rpc("call_local", "reliable")
|
||||||
func respawn(location : Vector3) -> void:
|
func respawn(location : Vector3) -> void:
|
||||||
animation_player.stop()
|
animation_player.stop()
|
||||||
player_state = PlayerState.PLAYER_ALIVE
|
player_state = PlayerState.PLAYER_ALIVE
|
||||||
|
|
@ -243,7 +245,7 @@ func respawn(location : Vector3) -> void:
|
||||||
|
|
||||||
func _exit_tree() -> void:
|
func _exit_tree() -> void:
|
||||||
player_state = PlayerState.PLAYER_DEAD
|
player_state = PlayerState.PLAYER_DEAD
|
||||||
flag_carry_component.drop()
|
flag_carry_component.drop(self)
|
||||||
|
|
||||||
func display_jetpack_particles() -> void:
|
func display_jetpack_particles() -> void:
|
||||||
for particle: GPUParticles3D in jetpack_particles:
|
for particle: GPUParticles3D in jetpack_particles:
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,9 @@ properties/4/replication_mode = 2
|
||||||
properties/5/path = NodePath(".:nickname")
|
properties/5/path = NodePath(".:nickname")
|
||||||
properties/5/spawn = true
|
properties/5/spawn = true
|
||||||
properties/5/replication_mode = 2
|
properties/5/replication_mode = 2
|
||||||
|
properties/6/path = NodePath(".:team_id")
|
||||||
|
properties/6/spawn = true
|
||||||
|
properties/6/replication_mode = 2
|
||||||
|
|
||||||
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_5j4ew"]
|
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_5j4ew"]
|
||||||
properties/0/path = NodePath(".:direction")
|
properties/0/path = NodePath(".:direction")
|
||||||
|
|
@ -237,7 +240,8 @@ shape = ExtResource("2_vjqny")
|
||||||
|
|
||||||
[node name="HUD" parent="." instance=ExtResource("3_ccety")]
|
[node name="HUD" parent="." instance=ExtResource("3_ccety")]
|
||||||
|
|
||||||
[node name="HealthComponent" parent="." instance=ExtResource("5_t6i6e")]
|
[node name="HealthComponent" parent="." node_paths=PackedStringArray("_player") instance=ExtResource("5_t6i6e")]
|
||||||
|
_player = NodePath("..")
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="HealthComponent"]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="HealthComponent"]
|
||||||
shape = ExtResource("2_vjqny")
|
shape = ExtResource("2_vjqny")
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
[ext_resource type="PackedScene" uid="uid://boviiugcnfyrj" path="res://modes/demo.tscn" id="1_50a80"]
|
[ext_resource type="PackedScene" uid="uid://boviiugcnfyrj" path="res://modes/demo.tscn" id="1_50a80"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bjctlqvs33nqy" path="res://interfaces/menus/boot/boot.tscn" id="1_acy5o"]
|
[ext_resource type="PackedScene" uid="uid://bjctlqvs33nqy" path="res://interfaces/menus/boot/boot.tscn" id="1_acy5o"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bvwxfgygm2xb8" path="res://modes/multiplayer.tscn" id="2_g8xeb"]
|
[ext_resource type="PackedScene" uid="uid://bvwxfgygm2xb8" path="res://modes/multiplayer.tscn" id="2_g8xeb"]
|
||||||
[ext_resource type="Resource" path="res://maps/maps.tres" id="3_1ipir"]
|
[ext_resource type="Resource" uid="uid://dut5f1sq0wfeb" path="res://maps/maps.tres" id="3_1ipir"]
|
||||||
|
|
||||||
[sub_resource type="GDScript" id="GDScript_e61dq"]
|
[sub_resource type="GDScript" id="GDScript_e61dq"]
|
||||||
script/source = "class_name Game extends Node3D
|
script/source = "class_name Game extends Node3D
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,9 @@ var _map_manager : Map
|
||||||
var _flag : Flag
|
var _flag : Flag
|
||||||
var _flag_carrier_scoring_timer : Timer = Timer.new()
|
var _flag_carrier_scoring_timer : Timer = Timer.new()
|
||||||
|
|
||||||
|
var team_chasers : Team
|
||||||
|
var team_rabbit : Team
|
||||||
|
|
||||||
signal connected_to_server
|
signal connected_to_server
|
||||||
signal connection_failed
|
signal connection_failed
|
||||||
|
|
||||||
|
|
@ -36,6 +39,10 @@ func _ready() -> void:
|
||||||
_flag_carrier_scoring_timer.wait_time = 10.0
|
_flag_carrier_scoring_timer.wait_time = 10.0
|
||||||
_flag_carrier_scoring_timer.timeout.connect(_on_flag_carrier_scoring_timer_timeout)
|
_flag_carrier_scoring_timer.timeout.connect(_on_flag_carrier_scoring_timer_timeout)
|
||||||
add_child(_flag_carrier_scoring_timer)
|
add_child(_flag_carrier_scoring_timer)
|
||||||
|
team_chasers = Team.new()
|
||||||
|
team_chasers.team_id = 0
|
||||||
|
team_rabbit = Team.new()
|
||||||
|
team_rabbit.team_id = 1
|
||||||
|
|
||||||
func start_server(config : Dictionary) -> void:
|
func start_server(config : Dictionary) -> void:
|
||||||
# Check if required parameters are missing
|
# Check if required parameters are missing
|
||||||
|
|
@ -79,12 +86,13 @@ func _on_player_died(player : Player, killer_id : int) -> void:
|
||||||
|
|
||||||
func respawn_player(player : Player) -> void:
|
func respawn_player(player : Player) -> void:
|
||||||
var spawn_location : Vector3 = _map_manager.get_player_spawn().position
|
var spawn_location : Vector3 = _map_manager.get_player_spawn().position
|
||||||
player.respawn(spawn_location)
|
player.respawn.rpc(spawn_location)
|
||||||
|
|
||||||
func add_player(peer_id : int, nickname : String) -> void:
|
func add_player(peer_id : int, nickname : String) -> void:
|
||||||
var player : Player = PLAYER.instantiate()
|
var player : Player = PLAYER.instantiate()
|
||||||
player.name = str(peer_id)
|
player.name = str(peer_id)
|
||||||
player.player_id = peer_id
|
player.player_id = peer_id
|
||||||
|
player.team_id = team_chasers.team_id
|
||||||
player.nickname = nickname
|
player.nickname = nickname
|
||||||
player.global_position = _map_manager.get_player_spawn().position
|
player.global_position = _map_manager.get_player_spawn().position
|
||||||
players.add_child(player)
|
players.add_child(player)
|
||||||
|
|
@ -122,10 +130,12 @@ func _join_match(nickname : String) -> void:
|
||||||
add_player(multiplayer.get_remote_sender_id(), nickname)
|
add_player(multiplayer.get_remote_sender_id(), nickname)
|
||||||
|
|
||||||
func _on_flag_grabbed(grabber : Player) -> void:
|
func _on_flag_grabbed(grabber : Player) -> void:
|
||||||
|
grabber.team_id = team_rabbit.team_id
|
||||||
scoreboard.add_score_to_player(grabber, 10)
|
scoreboard.add_score_to_player(grabber, 10)
|
||||||
_flag_carrier_scoring_timer.start()
|
_flag_carrier_scoring_timer.start()
|
||||||
|
|
||||||
func _on_flag_dropped() -> void:
|
func _on_flag_dropped(dropper : Player) -> void:
|
||||||
|
dropper.team_id = team_chasers.team_id
|
||||||
_flag_carrier_scoring_timer.stop()
|
_flag_carrier_scoring_timer.stop()
|
||||||
|
|
||||||
func _on_flag_carrier_scoring_timer_timeout() -> void:
|
func _on_flag_carrier_scoring_timer_timeout() -> void:
|
||||||
|
|
|
||||||
3
modes/team.gd
Normal file
3
modes/team.gd
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
class_name Team extends Object
|
||||||
|
|
||||||
|
var team_id : int
|
||||||
|
|
@ -31,15 +31,15 @@ func test_that_it_has_max_health_when_ready() -> void:
|
||||||
|
|
||||||
func test_that_it_takes_damage() -> void:
|
func test_that_it_takes_damage() -> void:
|
||||||
var damage_amount : float = 10
|
var damage_amount : float = 10
|
||||||
_subject.damage(damage_amount, -1)
|
_subject.damage(damage_amount, -1, 0)
|
||||||
assert_eq(_subject.health, TEST_MAX_HEALTH - damage_amount)
|
assert_eq(_subject.health, TEST_MAX_HEALTH - damage_amount)
|
||||||
|
|
||||||
func test_that_it_emits_health_changed_after_damage() -> void:
|
func test_that_it_emits_health_changed_after_damage() -> void:
|
||||||
_subject.damage(1, -1)
|
_subject.damage(1, -1, 0)
|
||||||
assert_signal_emitted(_subject, 'health_changed')
|
assert_signal_emitted(_subject, 'health_changed')
|
||||||
|
|
||||||
func test_that_it_emits_health_zeroed() -> void:
|
func test_that_it_emits_health_zeroed() -> void:
|
||||||
_subject.damage(TEST_MAX_HEALTH, -1)
|
_subject.damage(TEST_MAX_HEALTH, -1, 0)
|
||||||
assert_signal_emitted_with_parameters(_subject, 'health_zeroed', [-1])
|
assert_signal_emitted_with_parameters(_subject, 'health_zeroed', [-1])
|
||||||
|
|
||||||
func test_that_it_heals_fully() -> void:
|
func test_that_it_heals_fully() -> void:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue