diff --git a/levels/prototype_scene.tscn b/levels/prototype_scene.tscn index c3dff7b..92b5816 100644 --- a/levels/prototype_scene.tscn +++ b/levels/prototype_scene.tscn @@ -38,10 +38,10 @@ size = Vector3(15.324341, 0.96273804, 21.381592) size = Vector3(0.8275013, 0.96273804, 1.0796204) [sub_resource type="BoxShape3D" id="BoxShape3D_1wlgq"] -size = Vector3(34.28946, 8.172485, 33.813843) +size = Vector3(58.51023, 8.172485, 33.813843) [sub_resource type="BoxShape3D" id="BoxShape3D_5uqia"] -size = Vector3(9.06966, 8.172485, 13.86731) +size = Vector3(9.06966, 8.172485, 17.716736) [node name="PrototypeScene" type="Node3D"] @@ -165,8 +165,8 @@ size = Vector3(18.856493, 3.737772, 4.796875) material = ExtResource("5_bno23") [node name="CSGBox3D4" type="CSGBox3D" parent="CSGCombiner3D"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 7.0154533, 9.821699, -20.33673) -size = Vector3(5.681938, 18.808083, 7.111515) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.018553, 9.821699, -20.33673) +size = Vector3(7.688137, 18.808083, 7.111515) material = ExtResource("6_foctg") [node name="CSGBox3D21" type="CSGBox3D" parent="CSGCombiner3D"] @@ -255,7 +255,7 @@ team = 1 spawn_radius = 5.0 [node name="SpectatorSpawn" type="Marker3D" parent="PlayersContainer"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -1.0165482, 17.832424, 2.9756432) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.1422176, 39.792877, -1.3889732) script = ExtResource("4_pi0y7") team = 2 spawn_radius = 10.0 @@ -317,11 +317,11 @@ script = ExtResource("9_1wlgq") bound_plant = NodePath("../PlantA") [node name="CollisionShape3D" type="CollisionShape3D" parent="PlantADeadzone"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.292345, -7.2330484, 1.2828445) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.282812, -7.2330484, 1.2828445) shape = SubResource("BoxShape3D_1wlgq") [node name="CollisionShape3D2" type="CollisionShape3D" parent="PlantADeadzone"] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.8295212, -7.2330484, 25.29969) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.8295212, -7.2330484, 27.224403) shape = SubResource("BoxShape3D_5uqia") [node name="DefaultCamera" type="Camera3D" parent="."] diff --git a/project.godot b/project.godot index 1063b70..d6197d7 100644 --- a/project.godot +++ b/project.godot @@ -159,3 +159,4 @@ spc_down={ 3d_physics/layer_4="Projectiles" 3d_physics/layer_5="Players Attack Team" 3d_physics/layer_6="Players Defence Team" +3d_physics/layer_7="Interactible" diff --git a/scenes/weapons/active_bomb.tscn b/scenes/weapons/active_bomb.tscn index d77a6bc..6ac0b2a 100644 --- a/scenes/weapons/active_bomb.tscn +++ b/scenes/weapons/active_bomb.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=4 format=3 uid="uid://dtbpyfdawb02b"] +[gd_scene load_steps=5 format=3 uid="uid://dtbpyfdawb02b"] [ext_resource type="Script" uid="uid://boftqgpgqf56g" path="res://scripts/weapon_system/bomb/active_bomb.gd" id="1_avh0g"] [ext_resource type="PackedScene" uid="uid://dftij0fdq3lbr" path="res://models/weapons/Bomb.glb" id="1_yh58y"] @@ -8,7 +8,12 @@ properties/0/path = NodePath(".:position") properties/0/spawn = true properties/0/replication_mode = 2 -[node name="ActiveBomb" type="Node3D"] +[sub_resource type="BoxShape3D" id="BoxShape3D_avh0g"] +size = Vector3(1, 0.23214722, 0.8808594) + +[node name="ActiveBomb" type="CharacterBody3D"] +collision_layer = 64 +collision_mask = 0 script = ExtResource("1_avh0g") [node name="Bomb" parent="." instance=ExtResource("1_yh58y")] @@ -16,3 +21,13 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1307683, 0) [node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."] replication_config = SubResource("SceneReplicationConfig_yh58y") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1431427, 0.06738281) +shape = SubResource("BoxShape3D_avh0g") + +[node name="DefuseTimer" type="Timer" parent="."] +wait_time = 10.0 +one_shot = true + +[connection signal="timeout" from="DefuseTimer" to="." method="on_defuse_timeout"] diff --git a/scripts/interaction_system/interactible.gd b/scripts/interaction_system/interactible.gd new file mode 100644 index 0000000..80e9245 --- /dev/null +++ b/scripts/interaction_system/interactible.gd @@ -0,0 +1,30 @@ +extends CharacterBody3D + +class_name Interactible + +signal interacted(with: int) +signal stopped_interacting(with: int) + +var interacted_id: int = -1 + +func _ready() -> void: + if not multiplayer.is_server(): + return + Session.player_stopped_interacting.connect(player_stopped_interacting) + +func interaction_start(player_id: int): + if not multiplayer.is_server(): + return + interacted.emit(player_id) + + interacted_id = player_id + +func player_stopped_interacting(id: int): + if interacted_id == id: + interaction_end() + +func interaction_end(): + if not multiplayer.is_server(): + return + stopped_interacting.emit(interacted_id) + interacted_id = -1 diff --git a/scripts/interaction_system/interactible.gd.uid b/scripts/interaction_system/interactible.gd.uid new file mode 100644 index 0000000..d171d8c --- /dev/null +++ b/scripts/interaction_system/interactible.gd.uid @@ -0,0 +1 @@ +uid://d1c4u4aul8oc1 diff --git a/scripts/multiplayer/session.gd b/scripts/multiplayer/session.gd index 4d776fb..b8137bd 100644 --- a/scripts/multiplayer/session.gd +++ b/scripts/multiplayer/session.gd @@ -21,6 +21,7 @@ const DEFENCE_LAYER: int = 0b100000 signal round_started signal round_state_changed(state: int) +signal player_stopped_interacting(id: int) var player_nodes: Dictionary[int,Player] = {} var object_containers: Array[ObjectContainer] @@ -59,7 +60,7 @@ func _ready() -> void: round_timer.timeout.connect(end_round.bind(TEAMS.DEFENCE)) buy_timer = Timer.new() - buy_timer.wait_time = 15 + buy_timer.wait_time = 1 buy_timer.one_shot = true buy_timer.timeout.connect(begin_main_stage) @@ -170,6 +171,12 @@ func begin_bomb_stage() -> void: round_state = ROUND_STATES.AFTER_PLANT round_state_changed.emit(round_state) +func defuse_win() -> void: + if not multiplayer.is_server(): + return + bomb_timer.stop() + end_round(TEAMS.DEFENCE) + @rpc("any_peer","call_local","reliable") func add_dead(team: int): if multiplayer.is_server() == false: @@ -250,6 +257,43 @@ func shoot_internal(id:int , damage: int) -> void: if collision != {} and collision["collider"] is Player: collision["collider"].take_damage.rpc_id(int(collision["collider"].name),damage) +func interact() -> void: + if multiplayer.get_unique_id() == 1: + interact_internal(1) + else: + interact_internal.rpc_id(1,multiplayer.get_unique_id()) + +@rpc("any_peer","call_local","reliable") +func interact_internal(id:int) -> void: + if multiplayer.is_server() == false: + return + + var player: Player = player_nodes[id] + var player_camera: Camera3D = player.get_node("Camera3D") + var space: PhysicsDirectSpaceState3D = player.get_world_3d().direct_space_state + var endpoint: Vector3 = player_camera.global_position - player_camera.global_basis.z * 3 + + var ray = PhysicsRayQueryParameters3D.create(player_camera.global_position,endpoint,1) + ray.exclude = [player.get_rid()] + ray.collide_with_areas = false + ray.collision_mask |= 64 + + var collision = space.intersect_ray(ray) + if collision != {} and collision["collider"] is Interactible: + collision["collider"].interaction_start(id) + +func stop_interact(): + if multiplayer.get_unique_id() == 1: + stop_interact_internal(1) + else: + stop_interact_internal.rpc_id(1,multiplayer.get_unique_id()) + +@rpc("any_peer","call_local","reliable") +func stop_interact_internal(id: int) -> void: + if multiplayer.is_server() == false: + return + player_stopped_interacting.emit(id) + func is_on_site() -> bool: for plant in plants: if plant.is_player_on_site(multiplayer.get_unique_id()): diff --git a/scripts/player/player.gd b/scripts/player/player.gd index 109162b..d55c7f5 100644 --- a/scripts/player/player.gd +++ b/scripts/player/player.gd @@ -5,6 +5,8 @@ class_name Player @export var team: Session.TEAMS @export var weapon_models: Dictionary[StringName,Node3D] +var passived: bool = false + signal spawned signal health_changed(to: int) signal died @@ -38,6 +40,15 @@ func die() -> void: return Session.add_dead.rpc(team) died.emit() + passived = true + +@rpc("any_peer","call_local","reliable") +func passive() -> void: + passived = true + +@rpc("any_peer","call_local","reliable") +func depassive() -> void: + passived = false @rpc("any_peer","call_local","reliable") func kill_request() -> void: @@ -55,3 +66,11 @@ func set_after_spawn(start_position: Vector3,new_team: int): @rpc("any_peer","call_local","reliable") func take_damage(damage: int): hp -= damage + +func _input(event: InputEvent) -> void: + if not is_multiplayer_authority(): + return + if event.is_action_pressed("plr_interact"): + Session.interact() + if event.is_action_released("plr_interact"): + Session.stop_interact() diff --git a/scripts/player/player_movement.gd b/scripts/player/player_movement.gd index 7183722..bfa6031 100644 --- a/scripts/player/player_movement.gd +++ b/scripts/player/player_movement.gd @@ -3,11 +3,12 @@ extends Node class_name PlayerMovement @export var player: Player +var disabled: bool func process_movement(max_speed: float,acceleration: float,deceleration: float,delta: float) -> void: if is_multiplayer_authority() == false: return - if Session.round_state == Session.ROUND_STATES.BUY: + if Session.round_state == Session.ROUND_STATES.BUY or disabled or player.passived: player.velocity.x = 0 player.velocity.z = 0 return diff --git a/scripts/weapon_system/bomb/active_bomb.gd b/scripts/weapon_system/bomb/active_bomb.gd index d926420..c032644 100644 --- a/scripts/weapon_system/bomb/active_bomb.gd +++ b/scripts/weapon_system/bomb/active_bomb.gd @@ -1,8 +1,10 @@ -extends Node3D +extends Interactible var plant: StringName +@onready var defuse_timer: Timer = $DefuseTimer func _ready() -> void: + super() if multiplayer.is_server(): Session.bomb_timer.timeout.connect(on_timeout) Session.begin_bomb_stage() @@ -12,3 +14,19 @@ func on_timeout(): return Session.kill_site(plant) + +func on_defuse_timeout(): + Session.defuse_win() + +func interaction_start(player_id: int): + if Session.player_nodes[player_id].team != Session.TEAMS.DEFENCE: + return + super(player_id) + defuse_timer.start() + Session.player_nodes[player_id].passive.rpc_id(player_id) + +func interaction_end(): + Session.player_nodes[interacted_id].depassive.rpc_id(interacted_id) + + super() + defuse_timer.stop() diff --git a/scripts/weapon_system/weapon_system.gd b/scripts/weapon_system/weapon_system.gd index 7bc3611..7dcaeb6 100644 --- a/scripts/weapon_system/weapon_system.gd +++ b/scripts/weapon_system/weapon_system.gd @@ -174,7 +174,7 @@ func _physics_process(delta: float) -> void: current_state.physics_update(delta) func _input(event: InputEvent) -> void: - if is_multiplayer_authority() == false or disabled or Session.round_state == Session.ROUND_STATES.BUY: return + if is_multiplayer_authority() == false or disabled: return if current_state != null: current_state.state_input(event) @@ -196,14 +196,15 @@ func _input(event: InputEvent) -> void: elif event.is_action_pressed("plr_knife"): switch("knife") - if event.is_action_pressed("plr_fire"): - current_state.use_begin.rpc() - if event.is_action_released("plr_fire"): - current_state.use_end.rpc() - if event.is_action_pressed("plr_scope"): - current_state.alternate_state() - if event.is_action_pressed("plr_firemode"): - current_state.switch_mode() + if not Session.round_state == Session.ROUND_STATES.BUY and not player.passived: + if event.is_action_pressed("plr_fire"): + current_state.use_begin.rpc() + if event.is_action_released("plr_fire"): + current_state.use_end.rpc() + if event.is_action_pressed("plr_scope"): + current_state.alternate_state() + if event.is_action_pressed("plr_firemode"): + current_state.switch_mode() if event.is_action_pressed("plr_drop"): drop_current()