Add blood decals for clients as well
This commit is contained in:
parent
3ef771d0b6
commit
5ccfc651a1
@ -31,6 +31,7 @@ use crate::{
|
||||
buffs::{Buff, BuffKind},
|
||||
local_player::LocalPlayer,
|
||||
remote_player::RemotePlayer,
|
||||
shootable::Shootable,
|
||||
telegrenade::Telegrenade,
|
||||
weapon::WeaponType,
|
||||
},
|
||||
@ -1087,6 +1088,25 @@ impl Game {
|
||||
}
|
||||
}
|
||||
|
||||
// Handled whenever a player is shot, run on client-side only
|
||||
pub fn handle_on_shot(
|
||||
&mut self,
|
||||
player_id: u16,
|
||||
source: DamageSource,
|
||||
damage: i32,
|
||||
delta: NetVector3,
|
||||
) {
|
||||
if let Some(player) = self.find_player_mut(player_id)
|
||||
&& let Some(character) = &mut player.character
|
||||
{
|
||||
if let Ok(mut shootable) = character.clone().into_gd().try_dynify::<dyn Shootable>() {
|
||||
shootable
|
||||
.dyn_bind_mut()
|
||||
.on_shoot_visual(source, damage, delta.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle shooting, either from the server of from a client
|
||||
pub fn handle_shoot(
|
||||
&mut self,
|
||||
|
||||
@ -181,6 +181,8 @@ impl Shootable for ShootableTrigger {
|
||||
self.signals().on_shot().emit(id, damage, dir);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_shoot_visual(&mut self, _: DamageSource, _: i32, _: Vector3) {}
|
||||
}
|
||||
|
||||
#[derive(GodotClass)]
|
||||
|
||||
@ -357,6 +357,7 @@ pub enum Package {
|
||||
Jump(u16),
|
||||
Shoot(u16, NetVector3, NetTransform, f32),
|
||||
Punch(u16, NetVector3, NetTransform, f32),
|
||||
OnShot(u16, DamageSource, i32, NetVector3),
|
||||
TakeDamage(DamageSource, u16, i32),
|
||||
Kill(DamageSource, u16),
|
||||
SpawnBall(NetTransform, NetVector3, Option<u16>),
|
||||
|
||||
@ -7,6 +7,7 @@ use crate::{
|
||||
game::{Game, GameManager, opts::GameOption},
|
||||
game_settings::GameSettingsManager,
|
||||
net::network_manager::{NetworkManager, Package, PeerKind},
|
||||
player,
|
||||
popup_queue::{Popup, PopupQueue},
|
||||
ui::cli::{CliColor, CommandLinePanel},
|
||||
};
|
||||
@ -262,6 +263,12 @@ impl NetworkManager {
|
||||
game.bind_mut().on_trigger_deactivate(id);
|
||||
}
|
||||
}
|
||||
Package::OnShot(player_id, source, damage, delta) => {
|
||||
if let Some(game) = &mut Game::singleton() {
|
||||
game.bind_mut()
|
||||
.handle_on_shot(player_id, source, damage, delta);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
},
|
||||
|
||||
@ -100,4 +100,6 @@ impl Shootable for Ball {
|
||||
self.base_mut()
|
||||
.set_linear_velocity(prev_velocity + delta.normalized() * force);
|
||||
}
|
||||
|
||||
fn on_shoot_visual(&mut self, _: DamageSource, _: i32, _: Vector3) {}
|
||||
}
|
||||
|
||||
@ -112,14 +112,15 @@ impl PlayerEffects {
|
||||
s.base().get_basis().col_c(),
|
||||
&s.base().get_world_3d(),
|
||||
&Array::new(),
|
||||
(20. / delta.length()) as u8,
|
||||
10,
|
||||
// Calculate the particular spread of blood
|
||||
(((PI / 4.) * force) / delta.length()).min(PI / 2.),
|
||||
10. + delta.length() / 3.,
|
||||
None,
|
||||
);
|
||||
|
||||
let mut decal_results = Vec::new();
|
||||
for _ in 0..(force * 5.) as usize {
|
||||
for _ in 0..(force * force * 4.) as usize {
|
||||
if let Some(result) = results
|
||||
.get(s.rng.randi_range(0, results.len() as i32 - 1) as usize)
|
||||
.cloned()
|
||||
@ -127,7 +128,6 @@ impl PlayerEffects {
|
||||
decal_results.push(result);
|
||||
}
|
||||
}
|
||||
godot_print!("{:?}", decal_results);
|
||||
|
||||
for result in decal_results {
|
||||
let mut decal = prefab.instantiate_as::<Node3D>();
|
||||
|
||||
@ -940,11 +940,27 @@ impl LocalPlayer {
|
||||
#[godot_dyn]
|
||||
impl Shootable for LocalPlayer {
|
||||
fn on_shoot(&mut self, source: DamageSource, damage: i32, delta: Vector3) {
|
||||
if self.can_take_damage(&source)
|
||||
&& let Some(fx) = &mut self.effects
|
||||
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer
|
||||
&& let PeerKind::Server(peer, _) = peer
|
||||
{
|
||||
fx.bind_mut().shoot_blood(delta, damage as f32 / 100.);
|
||||
peer.broadcast_reliable(Package::OnShot(
|
||||
self.player_id.unwrap_or(0),
|
||||
source,
|
||||
damage,
|
||||
delta.into(),
|
||||
));
|
||||
self.on_shoot_visual(source, damage, delta);
|
||||
}
|
||||
self.take_damage(source, damage, true);
|
||||
}
|
||||
|
||||
fn on_shoot_visual(&mut self, source: DamageSource, damage: i32, delta: Vector3) {
|
||||
self.run_deferred(move |s| {
|
||||
if s.can_take_damage(&source)
|
||||
&& let Some(fx) = &mut s.effects
|
||||
{
|
||||
fx.bind_mut().shoot_blood(delta, damage as f32 / 100.);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ use godot::{
|
||||
use crate::{
|
||||
game::{Game, opts::GameOption},
|
||||
map::{killbox::KillboxKind, pickup::PickupKind},
|
||||
net::network_manager::{NetworkManager, Package, PeerKind},
|
||||
player::{
|
||||
DamageSource, DamageSourceSignal, IPlayer, NetTransform, PlayerCommon,
|
||||
buffs::{Buff, Buffs},
|
||||
@ -502,11 +503,27 @@ impl RemotePlayer {
|
||||
#[godot_dyn]
|
||||
impl Shootable for RemotePlayer {
|
||||
fn on_shoot(&mut self, source: DamageSource, damage: i32, delta: Vector3) {
|
||||
if self.can_take_damage(&source)
|
||||
&& let Some(fx) = &mut self.effects
|
||||
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer
|
||||
&& let PeerKind::Server(peer, _) = peer
|
||||
{
|
||||
fx.bind_mut().shoot_blood(delta, damage as f32 / 100.);
|
||||
peer.broadcast_reliable(Package::OnShot(
|
||||
self.player_id.unwrap_or(0),
|
||||
source,
|
||||
damage,
|
||||
delta.into(),
|
||||
));
|
||||
self.on_shoot_visual(source, damage, delta);
|
||||
}
|
||||
self.take_damage(source, damage, true);
|
||||
}
|
||||
|
||||
fn on_shoot_visual(&mut self, source: DamageSource, damage: i32, delta: Vector3) {
|
||||
self.run_deferred(move |s| {
|
||||
if s.can_take_damage(&source)
|
||||
&& let Some(fx) = &mut s.effects
|
||||
{
|
||||
fx.bind_mut().shoot_blood(delta, damage as f32 / 100.);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,5 +2,6 @@ use crate::player::DamageSource;
|
||||
use godot::prelude::*;
|
||||
|
||||
pub trait Shootable {
|
||||
fn on_shoot(&mut self, source: DamageSource, damage: i32, dir: Vector3);
|
||||
fn on_shoot(&mut self, source: DamageSource, damage: i32, delta: Vector3);
|
||||
fn on_shoot_visual(&mut self, source: DamageSource, damage: i32, delta: Vector3);
|
||||
}
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
use std::{collections::HashSet, f32::consts::PI};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
f32::consts::PI,
|
||||
};
|
||||
|
||||
use godot::{
|
||||
classes::{AudioStreamPlayer3D, GpuParticles3D, RandomNumberGenerator},
|
||||
@ -224,7 +227,7 @@ impl Weapon for Shotgun {
|
||||
vfx.set_emitting(true);
|
||||
}
|
||||
|
||||
let mut colliders = HashSet::new();
|
||||
let mut colliders: HashMap<Gd<Object>, Vec<Vector3>> = HashMap::new();
|
||||
let results = shotgun_ray(
|
||||
from,
|
||||
to,
|
||||
@ -255,17 +258,17 @@ impl Weapon for Shotgun {
|
||||
}
|
||||
|
||||
for result in &results {
|
||||
colliders.insert(result.collider.clone());
|
||||
if let Some(positions) = colliders.get_mut(&result.collider) {
|
||||
positions.push(result.position)
|
||||
} else {
|
||||
colliders.insert(result.collider.clone(), vec![result.position]);
|
||||
}
|
||||
}
|
||||
|
||||
if deal_damage {
|
||||
for collider in colliders {
|
||||
let collider_pos = if let Ok(node) = collider.clone().try_cast::<Node3D>() {
|
||||
node.get_global_position()
|
||||
} else {
|
||||
Vector3::ZERO
|
||||
};
|
||||
let delta = collider_pos - from;
|
||||
for (collider, positions) in colliders {
|
||||
let position = positions.iter().sum::<Vector3>() / positions.len() as f32;
|
||||
let delta = position - from;
|
||||
|
||||
if let Ok(mut shootable) = collider.clone().try_dynify::<dyn Shootable>() {
|
||||
self.run_deferred(move |_| {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user