diff --git a/rust/src/chat.rs b/rust/src/chat.rs index b677b7a..b74b004 100644 --- a/rust/src/chat.rs +++ b/rust/src/chat.rs @@ -57,9 +57,9 @@ impl ChatMessage { add_player(&mut label, &player); } } - DamageSource::Killbox => { + DamageSource::Killbox(kind) => { add_player(&mut label, &player); - label.append_text(" fell into the void"); + label.append_text(&kind.as_kill_text()); } } } diff --git a/rust/src/game_manager.rs b/rust/src/game_manager.rs index 8605403..b68372c 100644 --- a/rust/src/game_manager.rs +++ b/rust/src/game_manager.rs @@ -739,30 +739,38 @@ impl Game { if let Ok(mut local_player) = character.clone().try_cast::() { local_player.bind_mut().signals().on_die().connect_other( self, - move |s, signal, spid| { - s.on_death(DamageSource::from_signal(signal, spid), id) + move |s, signal, spid, kind| { + s.on_death(DamageSource::from_signal(signal, spid, kind), id) }, ); local_player .bind_mut() .signals() .on_take_damage() - .connect_other(self, move |s, signal, spid, damage| { - s.on_take_damage(DamageSource::from_signal(signal, spid), id, damage) + .connect_other(self, move |s, signal, spid, kind, damage| { + s.on_take_damage( + DamageSource::from_signal(signal, spid, kind), + id, + damage, + ) }); } else if let Ok(mut remote_player) = character.clone().try_cast::() { remote_player.bind_mut().signals().on_die().connect_other( self, - move |s, signal, spid| { - s.on_death(DamageSource::from_signal(signal, spid), id) + move |s, signal, spid, kind| { + s.on_death(DamageSource::from_signal(signal, spid, kind), id) }, ); remote_player .bind_mut() .signals() .on_take_damage() - .connect_other(self, move |s, signal, spid, damage| { - s.on_take_damage(DamageSource::from_signal(signal, spid), id, damage) + .connect_other(self, move |s, signal, spid, kind, damage| { + s.on_take_damage( + DamageSource::from_signal(signal, spid, kind), + id, + damage, + ) }); } } diff --git a/rust/src/killbox.rs b/rust/src/killbox.rs index 29acc49..fd80d86 100644 --- a/rust/src/killbox.rs +++ b/rust/src/killbox.rs @@ -2,6 +2,7 @@ use godot::{ classes::{Area3D, IArea3D}, prelude::*, }; +use serde::{Deserialize, Serialize}; use crate::{ game_manager::Game, @@ -9,9 +10,48 @@ use crate::{ player::{DamageSource, IPlayer, ball::Ball}, }; +#[derive(Debug, Clone, Copy, GodotConvert, Default, Var, Serialize, Deserialize)] +#[godot(via = GString)] +pub enum KillboxKind { + #[default] + Void, + Spikes, + Lava, + SeaOfBlood, + OuterSpace, + Quicksand, + LargeBoulder, + ElectricFence, + RadioactiveGoo, +} + +impl KillboxKind { + pub fn as_kill_text(&self) -> String { + match self { + KillboxKind::Void => " fell into the void", + KillboxKind::Spikes => " got impailed by spikes", + KillboxKind::Lava => " burned in lava", + KillboxKind::SeaOfBlood => " went looking for the Iron Lung", + KillboxKind::OuterSpace => " suffocated in outer space", + KillboxKind::Quicksand => " drowned in a pit of sand", + KillboxKind::LargeBoulder => { + " was squished by a large boulder the size of a small boulder" + } + KillboxKind::ElectricFence => " got electrocuted by a fence", + KillboxKind::RadioactiveGoo => { + " turned into a mutant..! no, died of radiation poisoning." + } + } + .to_string() + } +} + #[derive(GodotClass)] #[class(base=Area3D, init)] pub struct Killbox { + #[var] + pub kind: KillboxKind, + base: Base, } @@ -31,7 +71,7 @@ impl Killbox { if NetworkManager::singleton().bind().is_host() { player .dyn_bind_mut() - .take_damage(DamageSource::Killbox, 1000, true); + .take_damage(DamageSource::Killbox(self.kind), 1000, true); } } else if let Ok(_) = node.try_cast::() { if let Some(game) = &mut Game::singleton() { diff --git a/rust/src/player/local_player.rs b/rust/src/player/local_player.rs index faab345..c23bbab 100644 --- a/rust/src/player/local_player.rs +++ b/rust/src/player/local_player.rs @@ -12,6 +12,7 @@ use godot::{ use crate::{ game_manager::{Game, GameManager}, game_settings::{GameSettings, GameSettingsManager}, + killbox::KillboxKind, net::{ network_manager::{ NetworkManager, @@ -184,8 +185,12 @@ impl IPlayer for LocalPlayer { fn take_damage(&mut self, source: DamageSource, damage: i32, kill: bool) { self.run_deferred(move |s| { if s.can_take_damage(&source) { - let (signal, player) = source.into_signal(); - s.run_deferred(move |s| s.signals().on_take_damage().emit(signal, player, damage)); + let (signal, player, kind) = source.into_signal(); + s.run_deferred(move |s| { + s.signals() + .on_take_damage() + .emit(signal, player, kind, damage) + }); s.health -= damage; if kill && s.health <= 0 { s.kill(source); @@ -208,8 +213,8 @@ impl IPlayer for LocalPlayer { fn kill(&mut self, source: DamageSource) { self.drop_ball(false); - let (signal, player) = source.into_signal(); - self.run_deferred(move |s| s.signals().on_die().emit(signal, player)); + let (signal, player, kind) = source.into_signal(); + self.run_deferred(move |s| s.signals().on_die().emit(signal, player, kind)); if let Some(mut mesh) = self.soldier_mesh.take() { mesh.queue_free(); } @@ -567,9 +572,14 @@ impl ICharacterBody3D for LocalPlayer { #[godot_api] impl LocalPlayer { #[signal] - pub fn on_die(source: DamageSourceSignal, player: u16); + pub fn on_die(source: DamageSourceSignal, player: u16, killbox_kind: KillboxKind); #[signal] - pub fn on_take_damage(source: DamageSourceSignal, source_player: u16, damage: i32); + pub fn on_take_damage( + source: DamageSourceSignal, + source_player: u16, + killbox_kind: KillboxKind, + damage: i32, + ); fn update_lock(&mut self) { self.run_deferred(|s| { diff --git a/rust/src/player/mod.rs b/rust/src/player/mod.rs index b6faee3..a0720bc 100644 --- a/rust/src/player/mod.rs +++ b/rust/src/player/mod.rs @@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize}; use crate::{ game_manager::{Game, GameOption}, + killbox::KillboxKind, net::{network_manager::NetworkManager, util::NetVector3}, player::weapon::{BallWeapon, Weapon, WeaponType}, }; @@ -162,21 +163,21 @@ impl PlayerCommon for T { #[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub enum DamageSource { Player(u16), - Killbox, + Killbox(KillboxKind), } impl DamageSource { - pub fn into_signal(&self) -> (DamageSourceSignal, u16) { + pub fn into_signal(&self) -> (DamageSourceSignal, u16, KillboxKind) { match self { - DamageSource::Player(id) => (DamageSourceSignal::Player, *id), - DamageSource::Killbox => (DamageSourceSignal::Killbox, 0), + DamageSource::Player(id) => (DamageSourceSignal::Player, *id, KillboxKind::default()), + DamageSource::Killbox(kind) => (DamageSourceSignal::Killbox, 0, *kind), } } - pub fn from_signal(signal: DamageSourceSignal, player: u16) -> DamageSource { + pub fn from_signal(signal: DamageSourceSignal, player: u16, kind: KillboxKind) -> DamageSource { match signal { DamageSourceSignal::Player => DamageSource::Player(player), - DamageSourceSignal::Killbox => DamageSource::Killbox, + DamageSourceSignal::Killbox => DamageSource::Killbox(kind), } } } diff --git a/rust/src/player/remote_player.rs b/rust/src/player/remote_player.rs index 3a31049..620fbce 100644 --- a/rust/src/player/remote_player.rs +++ b/rust/src/player/remote_player.rs @@ -9,6 +9,7 @@ use godot::{ use crate::{ game_manager::Game, + killbox::KillboxKind, player::{ DamageSource, DamageSourceSignal, IPlayer, NetTransform, PlayerCommon, effects::PlayerEffects, @@ -144,8 +145,12 @@ impl IPlayer for RemotePlayer { fn take_damage(&mut self, source: DamageSource, damage: i32, kill: bool) { self.run_deferred(move |s| { if s.can_take_damage(&source) { - let (signal, player) = source.into_signal(); - s.run_deferred(move |s| s.signals().on_take_damage().emit(signal, player, damage)); + let (signal, player, kind) = source.into_signal(); + s.run_deferred(move |s| { + s.signals() + .on_take_damage() + .emit(signal, player, kind, damage) + }); s.health -= damage; if kill && s.health <= 0 { s.kill(source); @@ -169,8 +174,8 @@ impl IPlayer for RemotePlayer { fn kill(&mut self, source: DamageSource) { self.drop_ball(false); - let (signal, player) = source.into_signal(); - self.run_deferred(move |s| s.signals().on_die().emit(signal, player)); + let (signal, player, kind) = source.into_signal(); + self.run_deferred(move |s| s.signals().on_die().emit(signal, player, kind)); if let Some(mut mesh) = self.soldier_mesh.take() { mesh.queue_free(); } @@ -272,9 +277,14 @@ impl ICharacterBody3D for RemotePlayer { #[godot_api] impl RemotePlayer { #[signal] - pub fn on_die(source: DamageSourceSignal, player: u16); + pub fn on_die(source: DamageSourceSignal, player: u16, killbox_kind: KillboxKind); #[signal] - pub fn on_take_damage(source: DamageSourceSignal, source_player: u16, damage: i32); + pub fn on_take_damage( + source: DamageSourceSignal, + source_player: u16, + killbox_kind: KillboxKind, + damage: i32, + ); } #[godot_dyn]