From e6793fde6151dce760e09fca28dfb6b8c6f58681 Mon Sep 17 00:00:00 2001 From: Sofia Date: Mon, 27 Jul 2026 19:46:12 +0300 Subject: [PATCH] Add pickup visibility for replays --- rust/src/map.rs | 2 -- rust/src/pickup.rs | 31 ++++++++++++++++++++++++++++--- rust/src/player/local_player.rs | 1 - rust/src/replay.rs | 27 +++++++++++++++++++++++++++ rust/src/ui/player_listing.rs | 1 - 5 files changed, 55 insertions(+), 7 deletions(-) diff --git a/rust/src/map.rs b/rust/src/map.rs index 76a0b1e..41a809b 100644 --- a/rust/src/map.rs +++ b/rust/src/map.rs @@ -196,8 +196,6 @@ impl Map { } pub fn register_pickup(&mut self, pickup: DynGd) -> u8 { - godot_print!("Registered {:?}", pickup); - let id = self.pickup_counter; self.pickup_counter += 1; self.pickups.insert(id, pickup); diff --git a/rust/src/pickup.rs b/rust/src/pickup.rs index 147d62a..7498707 100644 --- a/rust/src/pickup.rs +++ b/rust/src/pickup.rs @@ -14,6 +14,14 @@ pub enum PickupKind { Health, } +#[derive(Debug, Default)] +pub enum ReplayVisibility { + #[default] + NoReplay, + Hidden, + Visible, +} + #[derive(GodotClass)] #[class(base=Node3D, init, tool)] pub struct HealthPickup { @@ -23,6 +31,7 @@ pub struct HealthPickup { time_elapsed: f64, pickup_id: Option, respawn: f64, + replay_visibility: ReplayVisibility, base: Base, } @@ -52,8 +61,14 @@ impl INode3D for HealthPickup { self.time_elapsed += delta; self.respawn -= delta; self.update_common(self.time_elapsed); - if let Some(area) = &mut self.pickup_area { - area.set_visible(self.respawn <= 0.); + if let Some(mut area) = self.pickup_area.clone() { + match self.replay_visibility { + ReplayVisibility::NoReplay => { + area.set_visible(self.is_active()); + } + ReplayVisibility::Hidden => area.set_visible(false), + ReplayVisibility::Visible => area.set_visible(true), + } } } } @@ -84,7 +99,15 @@ impl Pickup for HealthPickup { } fn on_pickup(&mut self) { - self.respawn = 10.; + self.respawn = 30.; + } + + fn is_active(&self) -> bool { + self.respawn <= 0. + } + + fn set_replay(&mut self, visible: ReplayVisibility) { + self.replay_visibility = visible; } } @@ -93,6 +116,8 @@ pub trait Pickup { fn kind(&self) -> PickupKind; fn id(&self) -> Option; fn on_pickup(&mut self); + fn is_active(&self) -> bool; + fn set_replay(&mut self, visibility: ReplayVisibility); } pub trait PickupCommon { diff --git a/rust/src/player/local_player.rs b/rust/src/player/local_player.rs index 212ec41..2e52f3a 100644 --- a/rust/src/player/local_player.rs +++ b/rust/src/player/local_player.rs @@ -309,7 +309,6 @@ impl IPlayer for LocalPlayer { } fn on_pickup(&mut self, kind: PickupKind) { - godot_print!("picked up"); match kind { PickupKind::Health => self.heal(100), } diff --git a/rust/src/replay.rs b/rust/src/replay.rs index ad05c27..171a786 100644 --- a/rust/src/replay.rs +++ b/rust/src/replay.rs @@ -15,6 +15,7 @@ use crate::{ game_manager::{Game, GameManager, Player}, map::Map, net::{network_manager::BallSync, util::NetVector3}, + pickup::ReplayVisibility, player::{ DamageSource, IPlayer, NetTransform, ball::Ball, remote_player::RemotePlayer, weapon::WeaponType, @@ -196,6 +197,17 @@ impl INode for ReplayPlayback { self.player_data = frame.player_data.clone(); self.running_goals = frame.goals.clone(); + if let Some(map) = &mut self.current_map { + for (id, visible) in frame.pickups_visible { + if let Some(pickup) = map.bind_mut().pickups.get_mut(&id) { + pickup.dyn_bind_mut().set_replay(match visible { + true => ReplayVisibility::Visible, + false => ReplayVisibility::Hidden, + }); + } + } + } + if let ReplayBall::World(ball_state) = &frame.ball_data { if let Some(ball) = &mut self.ball { ball.bind_mut().apply_sync(BallSync { @@ -325,6 +337,11 @@ impl INode for ReplayPlayback { } fn exit_tree(&mut self) { + if let Some(map) = &mut self.current_map { + for (_, pickup) in &mut map.bind_mut().pickups { + pickup.dyn_bind_mut().set_replay(ReplayVisibility::NoReplay); + } + } for (_, character) in &mut self.player_characters { character.queue_free(); } @@ -424,6 +441,8 @@ impl ReplayRecorder { let mut goals = HashMap::new(); + let mut pickups_visible = HashMap::new(); + if let Some(game) = Game::singleton() { for player in &game.bind().players { if let Some(state) = player.get_state(player.clone()) { @@ -443,6 +462,12 @@ impl ReplayRecorder { ReplayBall::Held }; + if let Some(map) = &game.bind().current_map { + for (id, pickup) in &map.bind().pickups { + pickups_visible.insert(*id, pickup.dyn_bind().is_active()); + } + } + goals = game.bind().goals.clone(); } @@ -451,6 +476,7 @@ impl ReplayRecorder { ReplayFrame { time: self.time_elapsed, goals, + pickups_visible, player_data, ball_data, events: Vec::new(), @@ -530,6 +556,7 @@ pub struct ReplayFrame { time: f64, player_data: HashMap, ball_data: ReplayBall, + pickups_visible: HashMap, events: Vec, goals: HashMap, } diff --git a/rust/src/ui/player_listing.rs b/rust/src/ui/player_listing.rs index 36b9752..3ec2ab3 100644 --- a/rust/src/ui/player_listing.rs +++ b/rust/src/ui/player_listing.rs @@ -63,7 +63,6 @@ impl IHBoxContainer for PlayerListing { impl PlayerListing { pub fn update(&mut self) { - godot_print!("update"); if let Some(player_id) = self.player_id { if let Some(game) = Game::singleton() { if let Some(player) = game.bind().find_player(player_id) {