Add telefragging

This commit is contained in:
Sofia 2026-08-03 22:18:52 +03:00
parent 1a2376931b
commit 6056b2cc1b
6 changed files with 117 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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<Gd<CooldownIcon>>,
#[export]
telefrag_area_prefab: Option<Gd<PackedScene>>,
pub player_id: Option<u16>,
@ -107,6 +109,9 @@ pub struct LocalPlayer {
telegrenade_cd_remaining: f64,
telegrenades_allowed: bool,
telefrag_area: Option<Gd<Area3D>>,
telefrag_frames: u8,
buffs: Buffs,
base: Base<CharacterBody3D>,
@ -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::<Area3D>();
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<Node3D>) {
if !NetworkManager::singleton().bind().is_host() {
return;
}
if collider.instance_id() == self.base().instance_id() {
return;
}
if let Ok(mut player) = collider.try_dynify::<dyn IPlayer>() {
player.dyn_bind_mut().take_damage(
DamageSource::Player(self.get_player_id().unwrap_or(0)),
1000,
true,
);
}
}
}
#[godot_dyn]

View File

@ -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<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerCommon for T {
}
self.set_telegrenade(None);
self.base_mut().set_global_position(to);
self.set_telefrag_frame();
true
}
}

View File

@ -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<Gd<AudioStreamPlayer3D>>,
#[export]
arrow: Option<Gd<Node3D>>,
#[export]
telefrag_area_prefab: Option<Gd<PackedScene>>,
pub player_id: Option<u16>,
pub player_name: String,
@ -78,6 +81,9 @@ pub struct RemotePlayer {
telegrenade_cd_remaining: f64,
telegrenades_allowed: bool,
telefrag_area: Option<Gd<Area3D>>,
telefrag_frames: u8,
buffs: Buffs,
base: Base<CharacterBody3D>,
@ -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::<Area3D>();
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<Node3D>) {
if !NetworkManager::singleton().bind().is_host() {
return;
}
if collider.instance_id() == self.base().instance_id() {
return;
}
if let Ok(mut player) = collider.try_dynify::<dyn IPlayer>() {
player.dyn_bind_mut().take_damage(
DamageSource::Player(self.get_player_id().unwrap_or(0)),
1000,
true,
);
}
}
}
#[godot_dyn]