From 0cb96e1b7563982bc62979ee94f4704635fa3257 Mon Sep 17 00:00:00 2001 From: Sofia Date: Thu, 6 Aug 2026 17:22:35 +0300 Subject: [PATCH] Add test triggerable --- godot/maps/scripts/test.gd | 27 +++++++++++++++ godot/maps/scripts/test.gd.uid | 1 + godot/maps/two_towers/two_towers.tscn | 23 +++++++++---- rust/src/game/mod.rs | 6 ++-- rust/src/map/triggers.rs | 48 +++++++++++++++++++++------ rust/src/replay.rs | 2 +- 6 files changed, 88 insertions(+), 19 deletions(-) create mode 100644 godot/maps/scripts/test.gd create mode 100644 godot/maps/scripts/test.gd.uid diff --git a/godot/maps/scripts/test.gd b/godot/maps/scripts/test.gd new file mode 100644 index 0000000..a2c79fc --- /dev/null +++ b/godot/maps/scripts/test.gd @@ -0,0 +1,27 @@ +extends Triggerable + +@export var mesh: MeshInstance3D + +func update_appearance(time: float) -> void: + var progress = clamp(time, 0.0, 1.0); + var new_color = Color.RED * (1.0 - progress) + Color.WHITE * progress + if mesh != null: + mesh.get_active_material(0).set("albedo_color", new_color) + +func _activate_visual(player_id: int, time_since_activation: float) -> void: + update_appearance(time_since_activation) + +func _deactivate_visual() -> void: + update_appearance(1.0) + +func _on_activate() -> bool: + return false + +func _process(delta: float) -> void: + if is_server_active(): + if server_active_for() > 1.0: + deactivate() + if is_active(): + update_appearance(active_for()) + else: + update_appearance(1.0) diff --git a/godot/maps/scripts/test.gd.uid b/godot/maps/scripts/test.gd.uid new file mode 100644 index 0000000..78453de --- /dev/null +++ b/godot/maps/scripts/test.gd.uid @@ -0,0 +1 @@ +uid://cijpblptlwvs diff --git a/godot/maps/two_towers/two_towers.tscn b/godot/maps/two_towers/two_towers.tscn index 26e2cf7..dfaed3c 100644 --- a/godot/maps/two_towers/two_towers.tscn +++ b/godot/maps/two_towers/two_towers.tscn @@ -1,12 +1,16 @@ [gd_scene format=3 uid="uid://c5p0ft870i1sk"] [ext_resource type="PackedScene" uid="uid://dpqqe7hjktit8" path="res://maps/two_towers/two_towers_static.scn" id="2_l5vmt"] +[ext_resource type="Script" uid="uid://cijpblptlwvs" path="res://maps/scripts/test.gd" id="3_vwb5y"] [ext_resource type="Script" uid="uid://diepa0rcedh5f" path="res://maps/meta/map_rebuilder.gd" id="4_y3aqj"] -[sub_resource type="BoxMesh" id="BoxMesh_1cgct"] - [sub_resource type="BoxShape3D" id="BoxShape3D_1cgct"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_vwb5y"] + +[sub_resource type="BoxMesh" id="BoxMesh_1cgct"] +material = SubResource("StandardMaterial3D_vwb5y") + [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") @@ -16,11 +20,18 @@ script = ExtResource("4_y3aqj") [node name="two_towers_static" parent="." unique_id=86902040 instance=ExtResource("2_l5vmt")] -[node name="shootable_trigger" type="ShootableTrigger" parent="." unique_id=306909670] +[node name="triggerable" type="Triggerable" parent="." unique_id=1206596848 node_paths=PackedStringArray("mesh")] +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="mesh_instance_3d" type="MeshInstance3D" parent="shootable_trigger" unique_id=174590790] +[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="collision_shape_3d" type="CollisionShape3D" parent="shootable_trigger" unique_id=298869370] -shape = SubResource("BoxShape3D_1cgct") +[connection signal="on_shot" from="triggerable/shootable_trigger" to="triggerable" method="activate" unbinds=2] diff --git a/rust/src/game/mod.rs b/rust/src/game/mod.rs index 2d85bf5..85912f7 100644 --- a/rust/src/game/mod.rs +++ b/rust/src/game/mod.rs @@ -1352,7 +1352,8 @@ impl Game { pub fn on_trigger_activate(&mut self, id: u8, player_id: u16) { self.run_deferred(move |s| { - if let Some(map) = &mut s.current_map + if s.current_replay_playback.is_none() + && let Some(map) = &mut s.current_map && let Some(triggerable) = map.bind_mut().triggerables.get_mut(&id) { triggerable.bind_mut().activate_visual(player_id, 0.); @@ -1374,7 +1375,8 @@ impl Game { pub fn on_trigger_deactivate(&mut self, id: u8) { self.run_deferred(move |s| { - if let Some(map) = &mut s.current_map + if s.current_replay_playback.is_none() + && let Some(map) = &mut s.current_map && let Some(triggerable) = map.bind_mut().triggerables.get_mut(&id) { triggerable.bind_mut().deactivate_visual(); diff --git a/rust/src/map/triggers.rs b/rust/src/map/triggers.rs index ea027e2..d1e1d33 100644 --- a/rust/src/map/triggers.rs +++ b/rust/src/map/triggers.rs @@ -1,7 +1,4 @@ -use godot::{ - classes::{Area3D, IArea3D}, - prelude::*, -}; +use godot::{classes::Area3D, prelude::*}; use crate::{ game::Game, @@ -17,7 +14,10 @@ pub struct Triggerable { triggerable_id: Option, /// Contains the activator player's ID if active. active: Option, - pub active_for: f64, + active_for: f64, + + visual_active: Option, + visual_active_for: f64, base: Base, } @@ -37,12 +37,18 @@ impl INode3D for Triggerable { } } - fn process(&mut self, delta: f64) { + fn physics_process(&mut self, delta: f64) { if self.active.is_some() { self.active_for += delta; } else { self.active_for = 0.; } + + if self.visual_active.is_some() { + self.visual_active_for += delta; + } else { + self.visual_active_for = 0.; + } } } @@ -51,11 +57,11 @@ impl Triggerable { /// Called whenever this triggerable's visuals should be immediately /// activated. #[func(virtual)] - pub fn activate_visual(&mut self, player_id: u16, time_since_activation: f64) {} + pub fn on_activate_visual(&mut self, player_id: u16, time_since_activation: f64) {} /// Called whenever this triggerable's visuals should be immediately /// deactivated. #[func(virtual)] - pub fn deactivate_visual(&mut self) {} + pub fn on_deactivate_visual(&mut self) {} /// Called whenever this triggerable is activated on the server-side. /// Returns a bool indicating if this triggerable should be immediately @@ -68,6 +74,18 @@ impl Triggerable { #[func(virtual)] pub fn on_deactivate(&mut self) {} + pub fn activate_visual(&mut self, player_id: u16, time_since_activation: f64) { + self.visual_active = Some(player_id); + self.visual_active_for = time_since_activation; + self.on_activate_visual(player_id, time_since_activation); + } + + pub fn deactivate_visual(&mut self) { + self.visual_active = None; + self.visual_active_for = 0.; + self.on_deactivate_visual(); + } + /// Activates this trigger. Active triggerables can not be re-activated /// without being deactivated first. Only executes on the server-side. #[func] @@ -98,15 +116,25 @@ impl Triggerable { } #[func] - pub fn is_active(&self) -> bool { + pub fn is_server_active(&self) -> bool { self.active.is_some() } #[func] - pub fn active_for(&self) -> f64 { + pub fn server_active_for(&self) -> f64 { self.active_for } + #[func] + pub fn is_active(&self) -> bool { + self.visual_active.is_some() + } + + #[func] + pub fn active_for(&self) -> f64 { + self.visual_active_for + } + pub fn get_active(&self) -> Option { self.active } diff --git a/rust/src/replay.rs b/rust/src/replay.rs index 5373a65..80be635 100644 --- a/rust/src/replay.rs +++ b/rust/src/replay.rs @@ -720,7 +720,7 @@ impl ReplayRecorder { *id, ReplayTriggerableState { active: triggerable.bind().get_active(), - active_for: triggerable.bind().active_for(), + active_for: triggerable.bind().server_active_for(), }, ); }