Compare commits

..

4 Commits

Author SHA1 Message Date
6992bc5eff Fix ball problem in a neater way 2026-07-27 01:41:03 +03:00
463004639c Revert "Possibly fix bugs with ball in replay"
This reverts commit 9a33403761.
2026-07-27 01:36:20 +03:00
327e19fd1a Reapply "Fix bug with respawning"
This reverts commit 5bd1fb9ff6.
2026-07-27 01:36:09 +03:00
5bd1fb9ff6 Revert "Fix bug with respawning"
This reverts commit e259aacc01.
2026-07-27 01:35:12 +03:00
8 changed files with 37 additions and 48 deletions

View File

@ -1162,9 +1162,7 @@ impl Game {
if let Some(player) = self.find_player_mut(player_id) { if let Some(player) = self.find_player_mut(player_id) {
if let Some(character) = &mut player.character { if let Some(character) = &mut player.character {
character character.dyn_bind_mut().take_damage(source, damage, false);
.dyn_bind_mut()
.take_damage(source, damage, false, true);
} }
} }
} }
@ -1173,7 +1171,7 @@ impl Game {
pub fn handle_kill(&mut self, source: DamageSource, player_id: u16) { pub fn handle_kill(&mut self, source: DamageSource, player_id: u16) {
if let Some(player) = self.find_player_mut(player_id) { if let Some(player) = self.find_player_mut(player_id) {
if let Some(character) = &mut player.character { if let Some(character) = &mut player.character {
character.dyn_bind_mut().kill(source.clone(), true); character.dyn_bind_mut().kill(source.clone());
self.on_kill(source, player_id); self.on_kill(source, player_id);
} }
} }

View File

@ -70,12 +70,9 @@ impl Killbox {
pub fn kill(&mut self, node: Gd<Node3D>) { pub fn kill(&mut self, node: Gd<Node3D>) {
if let Ok(mut player) = node.clone().try_dynify::<dyn IPlayer>() { if let Ok(mut player) = node.clone().try_dynify::<dyn IPlayer>() {
if NetworkManager::singleton().bind().is_host() { if NetworkManager::singleton().bind().is_host() {
player.dyn_bind_mut().take_damage( player
DamageSource::Killbox(self.kind), .dyn_bind_mut()
1000, .take_damage(DamageSource::Killbox(self.kind), 1000, true);
true,
true,
);
} }
} else if let Ok(_) = node.try_cast::<Ball>() { } else if let Ok(_) = node.try_cast::<Ball>() {
if let Some(game) = &mut Game::singleton() { if let Some(game) = &mut Game::singleton() {

View File

@ -117,6 +117,7 @@ impl Map {
node.bind_mut().player_id = Some(player_id); node.bind_mut().player_id = Some(player_id);
node.bind_mut().player_name = player.name.clone(); node.bind_mut().player_name = player.name.clone();
node.bind_mut().player_color = player.color.clone().into(); node.bind_mut().player_color = player.color.clone().into();
node.bind_mut().replay_mode = true;
self.base_mut().add_child(&node); self.base_mut().add_child(&node);
node.bind_mut() node.bind_mut()
@ -145,7 +146,6 @@ impl Map {
{ {
let mut ball = ball_prefab.instantiate_as::<Ball>(); let mut ball = ball_prefab.instantiate_as::<Ball>();
ball.bind_mut().dropper = player_id; ball.bind_mut().dropper = player_id;
ball.bind_mut().active = true;
self.base_mut().add_child(&ball); self.base_mut().add_child(&ball);
if let Some(transform) = transform { if let Some(transform) = transform {
ball.set_global_position(transform.location.into()); ball.set_global_position(transform.location.into());
@ -173,7 +173,6 @@ impl Map {
{ {
let mut ball = ball_prefab.instantiate_as::<Ball>(); let mut ball = ball_prefab.instantiate_as::<Ball>();
ball.bind_mut().dropper = player_id; ball.bind_mut().dropper = player_id;
ball.bind_mut().active = false;
self.base_mut().add_child(&ball); self.base_mut().add_child(&ball);
if let Some(transform) = transform { if let Some(transform) = transform {
ball.set_global_position(transform.location.into()); ball.set_global_position(transform.location.into());

View File

@ -12,7 +12,6 @@ use crate::{
#[class(base=RigidBody3D, init)] #[class(base=RigidBody3D, init)]
pub struct Ball { pub struct Ball {
pub dropper: Option<u16>, pub dropper: Option<u16>,
pub active: bool,
alive_for: f64, alive_for: f64,
@ -50,9 +49,6 @@ impl Ball {
} }
fn on_collision(&mut self, node: Gd<Node>) { fn on_collision(&mut self, node: Gd<Node>) {
if !self.active {
return;
}
if let Ok(player) = node.try_dynify::<dyn IPlayer>() if let Ok(player) = node.try_dynify::<dyn IPlayer>()
&& let Some(player_id) = player.dyn_bind().get_player_id() && let Some(player_id) = player.dyn_bind().get_player_id()
{ {

View File

@ -171,7 +171,7 @@ impl IPlayer for LocalPlayer {
fn apply_look_up(&mut self, _look: f32) {} fn apply_look_up(&mut self, _look: f32) {}
fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool { fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool {
if self.try_shoot_common(to, deal_damage, deal_damage) { if self.try_shoot_common(to, deal_damage) {
if let Some(game) = &mut Game::singleton() if let Some(game) = &mut Game::singleton()
&& let Some(recorder) = game.bind_mut().recorder() && let Some(recorder) = game.bind_mut().recorder()
{ {
@ -209,7 +209,7 @@ impl IPlayer for LocalPlayer {
} }
} }
fn take_damage(&mut self, source: DamageSource, damage: i32, kill: bool, drop_ball: bool) { fn take_damage(&mut self, source: DamageSource, damage: i32, kill: bool) {
self.run_deferred(move |s| { self.run_deferred(move |s| {
if s.can_take_damage(&source) { if s.can_take_damage(&source) {
let (signal, player, kind) = source.into_signal(); let (signal, player, kind) = source.into_signal();
@ -220,7 +220,7 @@ impl IPlayer for LocalPlayer {
}); });
s.health -= damage; s.health -= damage;
if kill && s.health <= 0 { if kill && s.health <= 0 {
s.kill(source, drop_ball); s.kill(source);
} }
} }
if let Some(health_label) = &mut s.health_label { if let Some(health_label) = &mut s.health_label {
@ -237,10 +237,8 @@ impl IPlayer for LocalPlayer {
self.dead_for self.dead_for
} }
fn kill(&mut self, source: DamageSource, drop_ball: bool) { fn kill(&mut self, source: DamageSource) {
if drop_ball {
self.drop_ball(false); self.drop_ball(false);
}
let (signal, player, kind) = source.into_signal(); let (signal, player, kind) = source.into_signal();
self.run_deferred(move |s| s.signals().on_die().emit(signal, player, kind)); self.run_deferred(move |s| s.signals().on_die().emit(signal, player, kind));
@ -303,6 +301,10 @@ impl IPlayer for LocalPlayer {
fn get_camera_origin(&self) -> Option<Gd<Node3D>> { fn get_camera_origin(&self) -> Option<Gd<Node3D>> {
self.camera_origin.clone() self.camera_origin.clone()
} }
fn is_replay_mode(&self) -> bool {
false
}
} }
#[godot_api] #[godot_api]
@ -721,6 +723,6 @@ impl LocalPlayer {
#[godot_dyn] #[godot_dyn]
impl Shootable for LocalPlayer { impl Shootable for LocalPlayer {
fn on_shoot(&mut self, source: DamageSource, damage: i32, _: Vector3) { fn on_shoot(&mut self, source: DamageSource, damage: i32, _: Vector3) {
self.take_damage(source, damage, true, true); self.take_damage(source, damage, true);
} }
} }

View File

@ -47,21 +47,16 @@ pub trait IPlayer {
fn jump(&mut self); fn jump(&mut self);
fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool; fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool;
fn try_punch(&mut self, to: Vector3, deal_damage: bool) -> bool; fn try_punch(&mut self, to: Vector3, deal_damage: bool) -> bool;
fn take_damage( fn take_damage(&mut self, source_player: DamageSource, damage: i32, kill: bool);
&mut self,
source_player: DamageSource,
damage: i32,
kill: bool,
drop_ball: bool,
);
fn is_dead(&self) -> bool; fn is_dead(&self) -> bool;
fn kill(&mut self, source_player: DamageSource, drop_ball: bool); fn kill(&mut self, source_player: DamageSource);
fn dead_for(&self) -> f64; fn dead_for(&self) -> f64;
fn swap_weapon(&mut self, weapon: WeaponType, drop_ball: bool); fn swap_weapon(&mut self, weapon: WeaponType, drop_ball: bool);
fn get_weapon(&self) -> Option<DynGd<Node3D, dyn Weapon>>; fn get_weapon(&self) -> Option<DynGd<Node3D, dyn Weapon>>;
fn take_weapon(&mut self) -> Option<DynGd<Node3D, dyn Weapon>>; fn take_weapon(&mut self) -> Option<DynGd<Node3D, dyn Weapon>>;
fn drop_ball(&mut self, with_velocity: bool) -> bool; fn drop_ball(&mut self, with_velocity: bool) -> bool;
fn get_camera_origin(&self) -> Option<Gd<Node3D>>; fn get_camera_origin(&self) -> Option<Gd<Node3D>>;
fn is_replay_mode(&self) -> bool;
} }
pub trait PlayerCommon { pub trait PlayerCommon {
@ -70,7 +65,7 @@ pub trait PlayerCommon {
fn drop_ball_common(&mut self, with_velocity: bool) -> bool; fn drop_ball_common(&mut self, with_velocity: bool) -> bool;
fn get_look_dir(&self) -> Vector3; fn get_look_dir(&self) -> Vector3;
fn can_take_damage(&self, source: &DamageSource) -> bool; fn can_take_damage(&self, source: &DamageSource) -> bool;
fn try_shoot_common(&mut self, to: Vector3, deal_damage: bool, drop_ball: bool) -> bool; fn try_shoot_common(&mut self, to: Vector3, deal_damage: bool) -> bool;
fn try_punch_common(&mut self, to: Vector3, deal_damage: bool) -> bool; fn try_punch_common(&mut self, to: Vector3, deal_damage: bool) -> bool;
} }
@ -182,12 +177,12 @@ impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerCommon for T {
true true
} }
fn try_shoot_common(&mut self, to: Vector3, deal_damage: bool, drop_ball: bool) -> bool { fn try_shoot_common(&mut self, to: Vector3, deal_damage: bool) -> bool {
if self.is_dead() { if self.is_dead() {
return false; return false;
} }
if drop_ball && self.drop_ball(true) { if !self.is_replay_mode() && self.drop_ball(true) {
return true; return true;
} }

View File

@ -48,6 +48,7 @@ pub struct RemotePlayer {
pub player_id: Option<u16>, pub player_id: Option<u16>,
pub player_name: String, pub player_name: String,
pub player_color: Color, pub player_color: Color,
pub replay_mode: bool,
movement_dir: Vector3, movement_dir: Vector3,
y_speed: f32, y_speed: f32,
@ -126,7 +127,7 @@ impl IPlayer for RemotePlayer {
} }
fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool { fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool {
self.try_shoot_common(to, deal_damage, deal_damage) self.try_shoot_common(to, deal_damage)
} }
fn try_punch(&mut self, to: Vector3, deal_damage: bool) -> bool { fn try_punch(&mut self, to: Vector3, deal_damage: bool) -> bool {
@ -138,7 +139,7 @@ impl IPlayer for RemotePlayer {
} }
} }
fn take_damage(&mut self, source: DamageSource, damage: i32, kill: bool, drop_ball: bool) { fn take_damage(&mut self, source: DamageSource, damage: i32, kill: bool) {
self.run_deferred(move |s| { self.run_deferred(move |s| {
if s.can_take_damage(&source) { if s.can_take_damage(&source) {
let (signal, player, kind) = source.into_signal(); let (signal, player, kind) = source.into_signal();
@ -149,7 +150,7 @@ impl IPlayer for RemotePlayer {
}); });
s.health -= damage; s.health -= damage;
if kill && s.health <= 0 { if kill && s.health <= 0 {
s.kill(source, drop_ball); s.kill(source);
} }
} }
if let Some(health_bar) = &mut s.health_bar { if let Some(health_bar) = &mut s.health_bar {
@ -167,8 +168,8 @@ impl IPlayer for RemotePlayer {
self.dead_for self.dead_for
} }
fn kill(&mut self, source: DamageSource, drop_ball: bool) { fn kill(&mut self, source: DamageSource) {
if drop_ball { if !self.replay_mode {
self.drop_ball(false); self.drop_ball(false);
} }
@ -225,6 +226,10 @@ impl IPlayer for RemotePlayer {
fn get_camera_origin(&self) -> Option<Gd<Node3D>> { fn get_camera_origin(&self) -> Option<Gd<Node3D>> {
self.camera_origin.clone() self.camera_origin.clone()
} }
fn is_replay_mode(&self) -> bool {
self.replay_mode
}
} }
#[godot_api] #[godot_api]
@ -288,6 +293,6 @@ impl RemotePlayer {
#[godot_dyn] #[godot_dyn]
impl Shootable for RemotePlayer { impl Shootable for RemotePlayer {
fn on_shoot(&mut self, source: DamageSource, damage: i32, _: Vector3) { fn on_shoot(&mut self, source: DamageSource, damage: i32, _: Vector3) {
self.take_damage(source, damage, true, true); self.take_damage(source, damage, true);
} }
} }

View File

@ -197,7 +197,7 @@ impl INode for ReplayPlayback {
match event { match event {
ReplayEvent::Death(damage_source, player_id) => { ReplayEvent::Death(damage_source, player_id) => {
if let Some(character) = self.player_characters.get_mut(player_id) { if let Some(character) = self.player_characters.get_mut(player_id) {
character.bind_mut().kill(*damage_source, false); character.bind_mut().kill(*damage_source);
} }
} }
ReplayEvent::Shoot(player_id, to) => { ReplayEvent::Shoot(player_id, to) => {
@ -234,12 +234,9 @@ impl INode for ReplayPlayback {
} }
ReplayEvent::TakeDamage(player_id, damage_source, damage) => { ReplayEvent::TakeDamage(player_id, damage_source, damage) => {
if let Some(character) = self.player_characters.get_mut(player_id) { if let Some(character) = self.player_characters.get_mut(player_id) {
character.bind_mut().take_damage( character
*damage_source, .bind_mut()
*damage, .take_damage(*damage_source, *damage, false);
false,
false,
);
} }
} }
} }