diff --git a/godot/scenes/player/local_player.tscn b/godot/scenes/player/local_player.tscn index a9f12f9..a3e9579 100644 --- a/godot/scenes/player/local_player.tscn +++ b/godot/scenes/player/local_player.tscn @@ -1,5 +1,6 @@ [gd_scene format=3 uid="uid://ct70bpbca8one"] +[ext_resource type="PackedScene" uid="uid://d3yjdufcbjtxc" path="res://scenes/player/telefrag_area.tscn" id="1_0yoer"] [ext_resource type="PackedScene" uid="uid://bod6b3befmyt5" path="res://scenes/player/soldier_m.tscn" id="1_jd651"] [ext_resource type="PackedScene" uid="uid://cl66unms2gim0" path="res://scenes/player/effects.tscn" id="2_ywmwa"] [ext_resource type="Shader" uid="uid://datt1r440base" path="res://shaders/vignette.tres" id="3_7awel"] @@ -41,6 +42,7 @@ throw_ball_sfx = NodePath("ball_throw_sfx") health = 100 punch_cooldown = 1.0 telegrenade_cooldown = NodePath("cooldown_icon") +telefrag_area_prefab = ExtResource("1_0yoer") telegrenade_cd = 10.0 collision_mask = 4 slide_on_ceiling = false diff --git a/godot/scenes/player/remote_player.tscn b/godot/scenes/player/remote_player.tscn index bcb081d..ae9dbd5 100644 --- a/godot/scenes/player/remote_player.tscn +++ b/godot/scenes/player/remote_player.tscn @@ -1,5 +1,6 @@ [gd_scene format=3 uid="uid://kfxc0migw80o"] +[ext_resource type="PackedScene" uid="uid://d3yjdufcbjtxc" path="res://scenes/player/telefrag_area.tscn" id="1_8dfyr"] [ext_resource type="PackedScene" uid="uid://bod6b3befmyt5" path="res://scenes/player/soldier_m.tscn" id="1_e2ekk"] [ext_resource type="PackedScene" uid="uid://cl66unms2gim0" path="res://scenes/player/effects.tscn" id="2_orxjf"] [ext_resource type="AudioStream" uid="uid://cl416orgv11vj" path="res://raw_assets/sfx/ball/little_robot_sound_factory_fantasy_Inventory_Open_00.mp3" id="3_840kl"] @@ -55,6 +56,7 @@ double_health_bar_sprite = NodePath("double_health_bar_sprite") ball_pickup_sfx = NodePath("ball_pickup_sfx") ball_throw_sfx = NodePath("ball_throw_sfx") arrow = NodePath("arrow") +telefrag_area_prefab = ExtResource("1_8dfyr") telegrenade_cd = 10.0 collision_layer = 2 collision_mask = 4 diff --git a/godot/scenes/player/telefrag_area.tscn b/godot/scenes/player/telefrag_area.tscn new file mode 100644 index 0000000..d390815 --- /dev/null +++ b/godot/scenes/player/telefrag_area.tscn @@ -0,0 +1,13 @@ +[gd_scene format=3 uid="uid://d3yjdufcbjtxc"] + +[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_3g557"] +radius = 0.53027344 +height = 2.192627 + +[node name="telefrag_area" type="Area3D" unique_id=928216980] +collision_layer = 0 +collision_mask = 3 + +[node name="telefrag_collider" type="CollisionShape3D" parent="." unique_id=1902330860] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.0906982, 0) +shape = SubResource("CapsuleShape3D_3g557") diff --git a/rust/src/player/local_player.rs b/rust/src/player/local_player.rs index 597eb56..a174584 100644 --- a/rust/src/player/local_player.rs +++ b/rust/src/player/local_player.rs @@ -2,7 +2,7 @@ use std::{f32::consts::PI, ops::Neg}; use godot::{ classes::{ - AudioStreamPlayer, Camera3D, CharacterBody3D, CollisionShape3D, ColorRect, + Area3D, AudioStreamPlayer, Camera3D, CharacterBody3D, CollisionShape3D, ColorRect, ICharacterBody3D, Input, InputEvent, InputEventMouseMotion, Label, input::MouseMode, }, obj::WithBaseField, @@ -81,6 +81,8 @@ pub struct LocalPlayer { punch_cooldown: f64, #[export] telegrenade_cooldown: Option>, + #[export] + telefrag_area_prefab: Option>, pub player_id: Option, @@ -107,6 +109,9 @@ pub struct LocalPlayer { telegrenade_cd_remaining: f64, telegrenades_allowed: bool, + telefrag_area: Option>, + telefrag_frames: u8, + buffs: Buffs, base: Base, @@ -409,6 +414,23 @@ impl IPlayer for LocalPlayer { self.buffs = buffs.clone(); buffs.update_effects(self); } + + fn set_telefrag_frame(&mut self) { + if let Some(prefab) = &self.telefrag_area_prefab { + let area = prefab.instantiate_as::(); + + area.signals() + .body_entered() + .connect_other(self, |s, other| s.body_entered(other)); + + self.base_mut().add_child(&area); + + godot_print!("added area"); + self.telefrag_frames = 1; + + self.telefrag_area = Some(area); + } + } } #[godot_api] @@ -764,6 +786,15 @@ impl ICharacterBody3D for LocalPlayer { self.base_mut().set_global_rotation(new_rot); self.player_update(delta); + + if self.telefrag_frames == 0 { + if let Some(area) = &mut self.telefrag_area.take() { + godot_print!("removed area"); + area.queue_free(); + } + } else { + self.telefrag_frames -= 1; + } } fn exit_tree(&mut self) { @@ -874,6 +905,22 @@ impl LocalPlayer { mat.set("shader_parameter/Color", &color.to_variant()); } } + + fn body_entered(&mut self, collider: Gd) { + if !NetworkManager::singleton().bind().is_host() { + return; + } + if collider.instance_id() == self.base().instance_id() { + return; + } + if let Ok(mut player) = collider.try_dynify::() { + player.dyn_bind_mut().take_damage( + DamageSource::Player(self.get_player_id().unwrap_or(0)), + 1000, + true, + ); + } + } } #[godot_dyn] diff --git a/rust/src/player/mod.rs b/rust/src/player/mod.rs index b9fbb69..17e89cc 100644 --- a/rust/src/player/mod.rs +++ b/rust/src/player/mod.rs @@ -80,6 +80,7 @@ pub trait IPlayer { fn get_buffs_mut(&mut self) -> &mut Buffs; fn new_buff(&mut self, buff: Buff); fn set_buffs(&mut self, buffs: Buffs); + fn set_telefrag_frame(&mut self); } pub trait PlayerCommon { @@ -320,6 +321,7 @@ impl PlayerCommon for T { } self.set_telegrenade(None); self.base_mut().set_global_position(to); + self.set_telefrag_frame(); true } } diff --git a/rust/src/player/remote_player.rs b/rust/src/player/remote_player.rs index 13a7a40..9b9e20b 100644 --- a/rust/src/player/remote_player.rs +++ b/rust/src/player/remote_player.rs @@ -1,6 +1,6 @@ use godot::{ classes::{ - AudioStreamPlayer3D, Camera3D, CharacterBody3D, CollisionShape3D, ICharacterBody3D, + Area3D, AudioStreamPlayer3D, Camera3D, CharacterBody3D, CollisionShape3D, ICharacterBody3D, Label3D, Sprite3D, TextureProgressBar, }, obj::WithBaseField, @@ -10,6 +10,7 @@ use godot::{ use crate::{ game::{Game, opts::GameOption}, killbox::KillboxKind, + net::network_manager::NetworkManager, pickup::PickupKind, player::{ DamageSource, DamageSourceSignal, IPlayer, NetTransform, PlayerCommon, @@ -57,6 +58,8 @@ pub struct RemotePlayer { ball_throw_sfx: Option>, #[export] arrow: Option>, + #[export] + telefrag_area_prefab: Option>, pub player_id: Option, pub player_name: String, @@ -78,6 +81,9 @@ pub struct RemotePlayer { telegrenade_cd_remaining: f64, telegrenades_allowed: bool, + telefrag_area: Option>, + telefrag_frames: u8, + buffs: Buffs, base: Base, @@ -359,6 +365,24 @@ impl IPlayer for RemotePlayer { self.buffs = buffs.clone(); buffs.update_effects(self); } + + fn set_telefrag_frame(&mut self) { + if let Some(prefab) = &self.telefrag_area_prefab { + let area = prefab.instantiate_as::(); + + area.signals() + .body_entered() + .connect_other(self, |s, other| s.body_entered(other)); + + self.base_mut().add_child(&area); + + godot_print!("added area"); + + self.telefrag_frames = 1; + + self.telefrag_area = Some(area); + } + } } #[godot_api] @@ -430,6 +454,15 @@ impl ICharacterBody3D for RemotePlayer { fn physics_process(&mut self, delta: f64) { self.player_update(delta); + + if self.telefrag_frames == 0 { + if let Some(area) = &mut self.telefrag_area.take() { + godot_print!("removed area"); + area.queue_free(); + } + } else { + self.telefrag_frames -= 1; + } } } @@ -462,6 +495,22 @@ impl RemotePlayer { self.health = health; self.update_health_bar(); } + + fn body_entered(&mut self, collider: Gd) { + if !NetworkManager::singleton().bind().is_host() { + return; + } + if collider.instance_id() == self.base().instance_id() { + return; + } + if let Ok(mut player) = collider.try_dynify::() { + player.dyn_bind_mut().take_damage( + DamageSource::Player(self.get_player_id().unwrap_or(0)), + 1000, + true, + ); + } + } } #[godot_dyn]