Add play_fx for weapons

This commit is contained in:
Sofia 2026-08-06 18:36:07 +03:00
parent c866db3581
commit a34884fb27
7 changed files with 68 additions and 38 deletions

View File

@ -1103,8 +1103,9 @@ impl Game {
.bind_mut()
.record_event(ReplayEvent::Shoot(player_id, to.into()));
}
let play_fx = self.current_replay_playback.is_none();
if let Some(player) = self.find_player_mut(player_id) {
player.try_shoot(to, transform, look_up, deal_damage)
player.try_shoot(to, transform, look_up, deal_damage, play_fx)
} else {
false
}
@ -1596,13 +1597,14 @@ impl Player {
transform: NetTransform,
look_up: f32,
deal_damage: bool,
play_fx: bool,
) -> bool {
if let Some(character) = &mut self.character {
character
.dyn_bind_mut()
.apply_rotation(transform.rotation.into());
character.dyn_bind_mut().apply_look_up(look_up);
character.dyn_bind_mut().try_shoot(to, deal_damage)
character.dyn_bind_mut().try_shoot(to, deal_damage, play_fx)
} else {
false
}

View File

@ -1,4 +1,7 @@
use godot::{classes::Area3D, prelude::*};
use godot::{
classes::{Area3D, StaticBody3D},
prelude::*,
};
use crate::{
game::Game,
@ -156,9 +159,9 @@ impl Triggerable {
}
#[derive(GodotClass)]
#[class(base=Area3D, init)]
#[class(base=StaticBody3D, init)]
pub struct ShootableTrigger {
base: Base<Area3D>,
base: Base<StaticBody3D>,
}
#[godot_api]

View File

@ -206,8 +206,8 @@ impl IPlayer for LocalPlayer {
}
}
fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool {
if self.buffs.can_shoot() && self.try_shoot_common(to, deal_damage) {
fn try_shoot(&mut self, to: Vector3, deal_damage: bool, play_fx: bool) -> bool {
if self.buffs.can_shoot() && self.try_shoot_common(to, deal_damage, play_fx) {
if let Some(weapon) = &mut self.weapon {
weapon.set_position(-Vector3::FORWARD);
weapon.set_rotation(Vector3::RIGHT * 0.5);
@ -667,7 +667,7 @@ impl ICharacterBody3D for LocalPlayer {
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer {
match peer {
PeerKind::Client(peer, addr) => {
if self.try_shoot(pos, false) {
if self.try_shoot(pos, false, true) {
peer.send_reliable(
addr,
Shoot(0, pos.into(), self.get_transform(), self.look_up),
@ -675,7 +675,7 @@ impl ICharacterBody3D for LocalPlayer {
}
}
PeerKind::Server(peer, _) => {
if self.try_shoot(pos, true) {
if self.try_shoot(pos, true, true) {
peer.broadcast_reliable(Shoot(
self.player_id.unwrap_or(0),
pos.into(),

View File

@ -54,7 +54,7 @@ pub trait IPlayer {
fn get_look_up(&self) -> f32;
fn get_transform(&self) -> NetTransform;
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, play_fx: bool) -> bool;
fn try_punch(&mut self, to: Vector3, deal_damage: bool) -> bool;
fn take_damage(&mut self, source_player: DamageSource, damage: i32, kill: bool);
fn is_dead(&self) -> bool;
@ -88,7 +88,7 @@ pub trait PlayerCommon {
fn drop_ball_common(&mut self, with_velocity: bool) -> bool;
fn get_look_dir(&self) -> Vector3;
fn can_take_damage(&self, source: &DamageSource) -> bool;
fn try_shoot_common(&mut self, to: Vector3, deal_damage: bool) -> bool;
fn try_shoot_common(&mut self, to: Vector3, deal_damage: bool, play_fx: bool) -> bool;
fn try_punch_common(&mut self, to: Vector3, deal_damage: bool) -> bool;
fn throw_telegrenade_common(&mut self, to: Vector3) -> bool;
fn telegrenade_teleport_common(&mut self, to: Vector3) -> bool;
@ -207,7 +207,7 @@ impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerCommon for T {
true
}
fn try_shoot_common(&mut self, to: Vector3, deal_damage: bool) -> bool {
fn try_shoot_common(&mut self, to: Vector3, deal_damage: bool, play_fx: bool) -> bool {
if self.is_dead() {
return false;
}
@ -227,6 +227,7 @@ impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerCommon for T {
to,
camera_origin.get_basis().col_b(),
deal_damage,
play_fx,
)
} else {
false

View File

@ -151,9 +151,9 @@ impl IPlayer for RemotePlayer {
self.look_up = look;
}
fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool {
fn try_shoot(&mut self, to: Vector3, deal_damage: bool, play_fx: bool) -> bool {
if self.buffs.can_shoot() {
self.try_shoot_common(to, deal_damage)
self.try_shoot_common(to, deal_damage, play_fx)
} else {
false
}

View File

@ -22,6 +22,7 @@ pub trait Weapon {
to: Vector3,
up: Vector3,
deal_damage: bool,
play_fx: bool,
) -> bool;
fn get_type(&self) -> WeaponType;
fn get_max_cd(&self) -> f64;
@ -73,12 +74,15 @@ impl Weapon for Raygun {
to: Vector3,
_: Vector3,
deal_damage: bool,
play_fx: bool,
) -> bool {
if self.cooldown_remaining > 0. {
return false;
}
if let Some(emitter) = &mut self.sound_emitter {
if let Some(emitter) = &mut self.sound_emitter
&& play_fx
{
emitter.play();
}
@ -90,12 +94,14 @@ impl Weapon for Raygun {
&Array::from_iter(vec![player]),
);
let target_clone = target.clone();
self.run_deferred(|s| {
if let Some(target) = target_clone {
add_decal(&target, s.decal.clone());
}
});
if play_fx {
let target_clone = target.clone();
self.run_deferred(|s| {
if let Some(target) = target_clone {
add_decal(&target, s.decal.clone());
}
});
}
let dir = (to - source.get_global_position()).normalized();
let beam_end = target
@ -103,7 +109,9 @@ impl Weapon for Raygun {
.map(|r| r.position)
.unwrap_or(source.get_global_position() + dir * 100.);
if let Some(prefab) = &self.bullet_prefab {
if let Some(prefab) = &self.bullet_prefab
&& play_fx
{
let mut bullet = prefab.instantiate_as::<Beam>();
bullet.bind_mut().source = Some(source.get_global_position());
@ -196,15 +204,20 @@ impl Weapon for Shotgun {
to: Vector3,
up: Vector3,
deal_damage: bool,
play_fx: bool,
) -> bool {
if self.cooldown_remaining > 0. {
return false;
}
if let Some(audio) = &mut self.sound_emitter {
if let Some(audio) = &mut self.sound_emitter
&& play_fx
{
audio.play();
}
if let Some(vfx) = &mut self.vfx {
if let Some(vfx) = &mut self.vfx
&& play_fx
{
vfx.set_emitting(true);
}
@ -219,20 +232,22 @@ impl Weapon for Shotgun {
PI / 2.,
10.,
);
let mut bullet_decal_results = Vec::new();
for _ in 0..10 {
if let Some(result) = results
.get(self.rng.randi_range(0, results.len() as i32 - 1) as usize)
.cloned()
{
bullet_decal_results.push(result);
if play_fx {
let mut bullet_decal_results = Vec::new();
for _ in 0..10 {
if let Some(result) = results
.get(self.rng.randi_range(0, results.len() as i32 - 1) as usize)
.cloned()
{
bullet_decal_results.push(result);
}
}
}
for result in bullet_decal_results {
self.run_deferred(move |s| {
add_decal(&result, s.decal.clone());
});
for result in bullet_decal_results {
self.run_deferred(move |s| {
add_decal(&result, s.decal.clone());
});
}
}
for result in &results {
@ -334,7 +349,16 @@ pub struct BallWeapon {
#[godot_dyn]
impl Weapon for BallWeapon {
fn shoot(&mut self, _: Rid, _: u16, _: Vector3, _: Vector3, _: Vector3, _: bool) -> bool {
fn shoot(
&mut self,
_: Rid,
_: u16,
_: Vector3,
_: Vector3,
_: Vector3,
_: bool,
_: bool,
) -> bool {
true
}

View File

@ -380,7 +380,7 @@ impl INode for ReplayPlayback {
}
ReplayEvent::Shoot(player_id, to) => {
if let Some(character) = self.player_characters.get_mut(player_id) {
character.bind_mut().try_shoot((*to).into(), false);
character.bind_mut().try_shoot((*to).into(), false, true);
}
}
ReplayEvent::Respawn(player_id, data) => {