Implement friendly fire gamerule
This commit is contained in:
parent
f732472f7c
commit
4f9e24f5ab
@ -11,7 +11,7 @@ use godot::{
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
game_manager::Game,
|
game_manager::{Game, GameOption},
|
||||||
net::{
|
net::{
|
||||||
network_manager::{
|
network_manager::{
|
||||||
NetworkManager,
|
NetworkManager,
|
||||||
@ -56,14 +56,15 @@ pub trait IPlayer {
|
|||||||
fn get_ball_origin(&self) -> Option<Gd<Node3D>>;
|
fn get_ball_origin(&self) -> Option<Gd<Node3D>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PlayerMovement {
|
pub trait PlayerCommon {
|
||||||
fn player_update(&mut self, delta: f64);
|
fn player_update(&mut self, delta: f64);
|
||||||
fn try_jump(&mut self) -> bool;
|
fn try_jump(&mut self) -> bool;
|
||||||
fn drop_ball_common(&mut self, with_velocity: bool) -> bool;
|
fn drop_ball_common(&mut self, with_velocity: bool) -> bool;
|
||||||
fn get_look_dir(&self) -> Vector3;
|
fn get_look_dir(&self) -> Vector3;
|
||||||
|
fn can_take_damage(&self, source: &DamageSource) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerMovement for T {
|
impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerCommon for T {
|
||||||
fn player_update(&mut self, delta: f64) {
|
fn player_update(&mut self, delta: f64) {
|
||||||
self.set_y_speed(self.get_y_speed() - 9.8 * delta as f32);
|
self.set_y_speed(self.get_y_speed() - 9.8 * delta as f32);
|
||||||
if self.base().is_on_floor() && self.get_y_speed() < 0. {
|
if self.base().is_on_floor() && self.get_y_speed() < 0. {
|
||||||
@ -141,6 +142,30 @@ impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerMovement for T {
|
|||||||
Vector3::ZERO
|
Vector3::ZERO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn can_take_damage(&self, source: &DamageSource) -> bool {
|
||||||
|
match source {
|
||||||
|
DamageSource::Player(source_player_id) => {
|
||||||
|
if let Some(game) = Game::singleton() {
|
||||||
|
let (self_team, source_team) = if let Some(self_player) =
|
||||||
|
game.bind().find_player(self.get_player_id().unwrap_or(0))
|
||||||
|
&& let Some(source_player) = game.bind().find_player(*source_player_id)
|
||||||
|
{
|
||||||
|
(self_player.data.team, source_player.data.team)
|
||||||
|
} else {
|
||||||
|
(0, 0)
|
||||||
|
};
|
||||||
|
if self_team == source_team
|
||||||
|
&& !game.bind().opts.is_true(GameOption::FriendlyFire)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(GodotClass)]
|
#[derive(GodotClass)]
|
||||||
@ -271,12 +296,16 @@ impl IPlayer for LocalPlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn take_damage(&mut self, source: DamageSource, damage: i32, kill: bool) {
|
fn take_damage(&mut self, source: DamageSource, damage: i32, kill: bool) {
|
||||||
let (signal, player) = source.into_signal();
|
self.run_deferred(move |s| {
|
||||||
self.run_deferred(move |s| s.signals().on_take_damage().emit(signal, player, damage));
|
if s.can_take_damage(&source) {
|
||||||
self.health -= damage;
|
let (signal, player) = source.into_signal();
|
||||||
if kill && self.health <= 0 {
|
s.run_deferred(move |s| s.signals().on_take_damage().emit(signal, player, damage));
|
||||||
self.kill(source);
|
s.health -= damage;
|
||||||
}
|
if kill && s.health <= 0 {
|
||||||
|
s.kill(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_dead(&self) -> bool {
|
fn is_dead(&self) -> bool {
|
||||||
@ -645,12 +674,16 @@ impl IPlayer for RemotePlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn take_damage(&mut self, source: DamageSource, damage: i32, kill: bool) {
|
fn take_damage(&mut self, source: DamageSource, damage: i32, kill: bool) {
|
||||||
let (signal, player) = source.into_signal();
|
self.run_deferred(move |s| {
|
||||||
self.run_deferred(move |s| s.signals().on_take_damage().emit(signal, player, damage));
|
if s.can_take_damage(&source) {
|
||||||
self.health -= damage;
|
let (signal, player) = source.into_signal();
|
||||||
if kill && self.health <= 0 {
|
s.run_deferred(move |s| s.signals().on_take_damage().emit(signal, player, damage));
|
||||||
self.kill(source);
|
s.health -= damage;
|
||||||
}
|
if kill && s.health <= 0 {
|
||||||
|
s.kill(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_dead(&self) -> bool {
|
fn is_dead(&self) -> bool {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user