Add killbox kinds

This commit is contained in:
Sofia 2026-07-24 23:21:57 +03:00
parent 32c4367aeb
commit a00ced88d0
6 changed files with 98 additions and 29 deletions

View File

@ -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());
}
}
}

View File

@ -739,30 +739,38 @@ impl Game {
if let Ok(mut local_player) = character.clone().try_cast::<LocalPlayer>() {
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::<RemotePlayer>() {
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,
)
});
}
}

View File

@ -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<Area3D>,
}
@ -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::<Ball>() {
if let Some(game) = &mut Game::singleton() {

View File

@ -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| {

View File

@ -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<T: IPlayer + ICharacterBody3D + WithBaseField> 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),
}
}
}

View File

@ -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]