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