diff --git a/godot/maps/two_towers/two_towers.tscn b/godot/maps/two_towers/two_towers.tscn index dfaed3c..03ac586 100644 --- a/godot/maps/two_towers/two_towers.tscn +++ b/godot/maps/two_towers/two_towers.tscn @@ -11,6 +11,9 @@ [sub_resource type="BoxMesh" id="BoxMesh_1cgct"] material = SubResource("StandardMaterial3D_vwb5y") +[sub_resource type="BoxShape3D" id="BoxShape3D_3g557"] +size = Vector3(5, 5, 5) + [node name="two_towers" type="Map" unique_id=590524284 node_paths=PackedStringArray("spawners", "ball_spawner")] spawners = [NodePath("two_towers_static/func_godot_map/entity_11_info_spawn_point"), NodePath("two_towers_static/func_godot_map/entity_5_info_spawn_point")] ball_spawner = NodePath("two_towers_static/func_godot_map/entity_1_info_spawn_point") @@ -21,17 +24,23 @@ script = ExtResource("4_y3aqj") [node name="two_towers_static" parent="." unique_id=86902040 instance=ExtResource("2_l5vmt")] [node name="triggerable" type="Triggerable" parent="." unique_id=1206596848 node_paths=PackedStringArray("mesh")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 33.152664, 3.0791912, 0) script = ExtResource("3_vwb5y") mesh = NodePath("mesh_instance_3d") [node name="shootable_trigger" type="ShootableTrigger" parent="triggerable" unique_id=306909670] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 42.184772, 10.981467, 7.8725615) [node name="collision_shape_3d" type="CollisionShape3D" parent="triggerable/shootable_trigger" unique_id=298869370] shape = SubResource("BoxShape3D_1cgct") [node name="mesh_instance_3d" type="MeshInstance3D" parent="triggerable" unique_id=174590790] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 42.184772, 10.981467, 7.8725615) mesh = SubResource("BoxMesh_1cgct") +[node name="proximity_trigger" type="ProximityTrigger" parent="triggerable" unique_id=774677471] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.7171593, -2.5604024, 0.8731904) + +[node name="collision_shape_3d" type="CollisionShape3D" parent="triggerable/proximity_trigger" unique_id=1090850563] +shape = SubResource("BoxShape3D_3g557") + [connection signal="on_shot" from="triggerable/shootable_trigger" to="triggerable" method="activate" unbinds=2] +[connection signal="on_trigger" from="triggerable/proximity_trigger" to="triggerable" method="activate"] diff --git a/rust/src/map/triggers.rs b/rust/src/map/triggers.rs index 7c819a7..601ee04 100644 --- a/rust/src/map/triggers.rs +++ b/rust/src/map/triggers.rs @@ -1,5 +1,7 @@ +use std::collections::HashSet; + use godot::{ - classes::{Area3D, StaticBody3D}, + classes::{Area3D, IArea3D, StaticBody3D}, prelude::*, }; @@ -7,7 +9,9 @@ use crate::{ game::Game, map::Map, net::network_manager::NetworkManager, - player::{DamageSource, shootable::Shootable}, + player::{ + DamageSource, local_player::LocalPlayer, remote_player::RemotePlayer, shootable::Shootable, + }, replay::StandaloneReplayManager, }; @@ -178,3 +182,60 @@ impl Shootable for ShootableTrigger { } } } + +#[derive(GodotClass)] +#[class(base=Area3D, init)] +pub struct ProximityTrigger { + colliders_inside: HashSet>, + base: Base, +} + +#[godot_api] +impl IArea3D for ProximityTrigger { + fn ready(&mut self) { + let base = self.base_mut().clone(); + base.signals() + .body_entered() + .connect_other(self, Self::on_enter); + base.signals() + .body_exited() + .connect_other(self, Self::on_leave); + } +} + +#[godot_api] +impl ProximityTrigger { + #[signal] + pub fn on_trigger(player: u16); + #[signal] + pub fn on_all_left(); + + fn on_enter(&mut self, node: Gd) { + if NetworkManager::singleton().bind().is_host() { + let was_empty = self.colliders_inside.is_empty(); + + let player_id = if let Ok(local_player) = node.clone().try_cast::() { + self.colliders_inside.insert(node); + Some(local_player.bind().player_id.unwrap_or(0)) + } else if let Ok(remote_player) = node.clone().try_cast::() { + if !remote_player.bind().replay_mode { + self.colliders_inside.insert(node); + } + Some(remote_player.bind().player_id.unwrap_or(0)) + } else { + None + }; + + if was_empty && let Some(player_id) = player_id { + self.signals().on_trigger().emit(player_id); + } + } + } + + fn on_leave(&mut self, node: Gd) { + self.colliders_inside.remove(&node); + if self.colliders_inside.is_empty() { + self.signals().on_all_left().emit(); + } + } +}