Add initial support for telegrenades
This commit is contained in:
parent
d32b3cade0
commit
81402f2cf4
@ -130,6 +130,11 @@ punch={
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
throw_telegrenade={
|
||||
"deadzone": 0.2,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":113,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
|
||||
[physics]
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
[ext_resource type="PackedScene" uid="uid://hmh2lrrlo2wy" path="res://scenes/player/replay_player.tscn" id="6_5fjlq"]
|
||||
[ext_resource type="PackedScene" uid="uid://dfnbc8sbufa4j" path="res://scenes/misc/ball.tscn" id="7_cv0ql"]
|
||||
[ext_resource type="PackedScene" uid="uid://dc17w5n6y1an" path="res://scenes/misc/replay_ball.tscn" id="8_m1inn"]
|
||||
[ext_resource type="PackedScene" uid="uid://cuh8bvyx7yy8e" path="res://scenes/misc/teleport_grenade.tscn" id="9_nxoss"]
|
||||
|
||||
[node name="game_manager" type="GameManager" unique_id=1442044769]
|
||||
respawn_timer = 10.0
|
||||
@ -22,4 +23,5 @@ remote_player = ExtResource("5_nxoss")
|
||||
replay_player = ExtResource("6_5fjlq")
|
||||
ball = ExtResource("7_cv0ql")
|
||||
replay_ball = ExtResource("8_m1inn")
|
||||
telegrenade = ExtResource("9_nxoss")
|
||||
maps = Array[MapResource]([ExtResource("1_glms7"), ExtResource("2_glms7"), ExtResource("5_rotn8")])
|
||||
|
||||
23
godot/scenes/misc/teleport_grenade.tscn
Normal file
23
godot/scenes/misc/teleport_grenade.tscn
Normal file
@ -0,0 +1,23 @@
|
||||
[gd_scene format=3 uid="uid://cuh8bvyx7yy8e"]
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_1cgct"]
|
||||
radius = 0.5088567
|
||||
|
||||
[sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_bbjda"]
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_otqol"]
|
||||
albedo_texture = SubResource("PlaceholderTexture2D_bbjda")
|
||||
|
||||
[sub_resource type="BoxMesh" id="BoxMesh_3g557"]
|
||||
material = SubResource("StandardMaterial3D_otqol")
|
||||
size = Vector3(0.1, 0.1, 0.1)
|
||||
|
||||
[node name="teleport_grenade" type="Telegrenade" unique_id=1670808846]
|
||||
collision_layer = 0
|
||||
collision_mask = 4
|
||||
|
||||
[node name="collision_shape_3d" type="CollisionShape3D" parent="." unique_id=1124839205]
|
||||
shape = SubResource("SphereShape3D_1cgct")
|
||||
|
||||
[node name="mesh_instance_3d" type="MeshInstance3D" parent="." unique_id=1327678222]
|
||||
mesh = SubResource("BoxMesh_3g557")
|
||||
@ -22,7 +22,7 @@ use crate::{
|
||||
pickup::PickupKind,
|
||||
player::{
|
||||
DamageSource, IPlayer, NetTransform, ball::Ball, local_player::LocalPlayer,
|
||||
remote_player::RemotePlayer, weapon::WeaponType,
|
||||
remote_player::RemotePlayer, telegrenade::Telegrenade, weapon::WeaponType,
|
||||
},
|
||||
replay::{ReplayEvent, ReplayPlayback, ReplayRecorder},
|
||||
team_resource::TeamResource,
|
||||
@ -58,6 +58,9 @@ pub struct GameManager {
|
||||
#[export]
|
||||
#[export_group(name = "Prefabs")]
|
||||
pub replay_ball: Option<Gd<PackedScene>>,
|
||||
#[export]
|
||||
#[export_group(name = "Prefabs")]
|
||||
pub telegrenade: Option<Gd<PackedScene>>,
|
||||
|
||||
pub game: Option<Gd<Game>>,
|
||||
base: Base<Node>,
|
||||
@ -1251,6 +1254,26 @@ impl Game {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn spawn_telegrenade(
|
||||
&mut self,
|
||||
location: NetVector3,
|
||||
velocity: NetVector3,
|
||||
) -> Option<Gd<Telegrenade>> {
|
||||
if let Some(map) = &mut self.current_map {
|
||||
map.bind_mut().spawn_telegrenade(location, velocity)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on_throw_telegrenade(&mut self, player_id: u16, to: NetVector3) {
|
||||
if let Some(player) = self.find_player_mut(player_id)
|
||||
&& let Some(character) = &mut player.character
|
||||
{
|
||||
character.dyn_bind_mut().try_throw_telegrenade(to.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
||||
@ -8,6 +8,7 @@ use crate::{
|
||||
pickup::Pickup,
|
||||
player::{
|
||||
IPlayer, NetTransform, ball::Ball, local_player::LocalPlayer, remote_player::RemotePlayer,
|
||||
telegrenade::Telegrenade,
|
||||
},
|
||||
replay::{ReplayPlayer, ReplayPlayerState, StandaloneReplayManager},
|
||||
};
|
||||
@ -201,4 +202,22 @@ impl Map {
|
||||
self.pickups.insert(id, pickup);
|
||||
id
|
||||
}
|
||||
|
||||
pub fn spawn_telegrenade(
|
||||
&mut self,
|
||||
location: NetVector3,
|
||||
velocity: NetVector3,
|
||||
) -> Option<Gd<Telegrenade>> {
|
||||
if let Some(prefab) = &GameManager::singleton().bind().telegrenade {
|
||||
let mut telegrenade = prefab.instantiate_as::<Telegrenade>();
|
||||
self.base_mut().add_child(&telegrenade);
|
||||
|
||||
telegrenade.set_global_position(location.into());
|
||||
telegrenade.set_linear_velocity(velocity.into());
|
||||
|
||||
Some(telegrenade)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,6 +315,7 @@ pub enum Package {
|
||||
Goal(Vec<u8>),
|
||||
Announcement(u16, Announcement),
|
||||
Pickup(u8, u16),
|
||||
ThrowTelegrenade(u16, NetVector3),
|
||||
|
||||
// End-of-Game packages
|
||||
FinishGame,
|
||||
|
||||
@ -231,6 +231,13 @@ impl NetworkManager {
|
||||
game.bind_mut().on_pickup(pickup_id, player_id);
|
||||
}
|
||||
}
|
||||
Package::ThrowTelegrenade(player_id, to) => {
|
||||
if let Some(game) = &mut Game::singleton() {
|
||||
if player_id != game.bind().self_id.unwrap_or(0) {
|
||||
game.bind_mut().on_throw_telegrenade(player_id, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
},
|
||||
@ -443,6 +450,15 @@ impl NetworkManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
Package::ThrowTelegrenade(_, to) => {
|
||||
if let Some(game) = &mut Game::singleton() {
|
||||
let player =
|
||||
game.bind().find_player_by_addr(&conn.address).cloned();
|
||||
if let Some(player) = player {
|
||||
game.bind_mut().on_throw_telegrenade(player.id(), to);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
},
|
||||
|
||||
@ -16,7 +16,7 @@ use crate::{
|
||||
net::{
|
||||
network_manager::{
|
||||
NetworkManager,
|
||||
Package::{self, Jump, Punch, Shoot},
|
||||
Package::{self, Jump, Punch, Shoot, ThrowTelegrenade},
|
||||
PeerKind,
|
||||
},
|
||||
util::cast_ray,
|
||||
@ -28,6 +28,7 @@ use crate::{
|
||||
remote_player::RemotePlayer,
|
||||
shootable::Shootable,
|
||||
soldier_mesh::SoldierMesh,
|
||||
telegrenade::Telegrenade,
|
||||
weapon::{BallWeapon, Raygun, Shotgun, Weapon, WeaponType},
|
||||
},
|
||||
replay::ReplayEvent,
|
||||
@ -87,6 +88,8 @@ pub struct LocalPlayer {
|
||||
|
||||
punch_cd_remaining: f64,
|
||||
|
||||
telegrenade: Option<Gd<Telegrenade>>,
|
||||
|
||||
base: Base<CharacterBody3D>,
|
||||
}
|
||||
|
||||
@ -163,6 +166,10 @@ impl IPlayer for LocalPlayer {
|
||||
|
||||
fn apply_look_up(&mut self, _look: f32) {}
|
||||
|
||||
fn try_throw_telegrenade(&mut self, to: Vector3) -> bool {
|
||||
self.throw_telegrenade_common(to)
|
||||
}
|
||||
|
||||
fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool {
|
||||
if self.try_shoot_common(to, deal_damage) {
|
||||
if let Some(game) = &mut Game::singleton()
|
||||
@ -313,6 +320,14 @@ impl IPlayer for LocalPlayer {
|
||||
PickupKind::Health => self.heal(100),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_telegrenade(&mut self, grenade: Option<Gd<Telegrenade>>) {
|
||||
self.telegrenade = grenade;
|
||||
}
|
||||
|
||||
fn as_gd(&self) -> DynGd<CharacterBody3D, dyn IPlayer> {
|
||||
self.to_gd().into_dyn().upcast()
|
||||
}
|
||||
}
|
||||
|
||||
#[godot_api]
|
||||
@ -463,6 +478,28 @@ impl ICharacterBody3D for LocalPlayer {
|
||||
|
||||
fn input(&mut self, event: Gd<InputEvent>) {
|
||||
if self.locked {
|
||||
if event.is_action_pressed("throw_telegrenade") {
|
||||
if let Some(pos) = self.raycast_from_camera() {
|
||||
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer {
|
||||
match peer {
|
||||
PeerKind::Client(peer, addr) => {
|
||||
if self.try_throw_telegrenade(pos) {
|
||||
peer.send_reliable(addr, ThrowTelegrenade(0, pos.into()));
|
||||
}
|
||||
}
|
||||
PeerKind::Server(peer, _) => {
|
||||
if self.try_throw_telegrenade(pos) {
|
||||
peer.broadcast_reliable(ThrowTelegrenade(
|
||||
self.player_id.unwrap_or(0),
|
||||
pos.into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if event.is_action_pressed("shoot") {
|
||||
if let Some(pos) = self.raycast_from_camera() {
|
||||
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer {
|
||||
|
||||
@ -1,6 +1,10 @@
|
||||
use std::{collections::HashSet, f32::consts::PI, ops::Neg};
|
||||
|
||||
use godot::{classes::ICharacterBody3D, obj::WithBaseField, prelude::*};
|
||||
use godot::{
|
||||
classes::{CharacterBody3D, ICharacterBody3D},
|
||||
obj::WithBaseField,
|
||||
prelude::*,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
@ -13,6 +17,7 @@ use crate::{
|
||||
pickup::PickupKind,
|
||||
player::{
|
||||
shootable::Shootable,
|
||||
telegrenade::Telegrenade,
|
||||
weapon::{BallWeapon, Weapon, WeaponType},
|
||||
},
|
||||
};
|
||||
@ -24,6 +29,7 @@ pub mod player_hand_remover;
|
||||
pub mod remote_player;
|
||||
pub mod shootable;
|
||||
pub mod soldier_mesh;
|
||||
pub mod telegrenade;
|
||||
pub mod weapon;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
@ -61,6 +67,9 @@ pub trait IPlayer {
|
||||
fn get_health(&self) -> i32;
|
||||
fn heal(&mut self, amount: i32);
|
||||
fn on_pickup(&mut self, kind: PickupKind);
|
||||
fn try_throw_telegrenade(&mut self, to: Vector3) -> bool;
|
||||
fn set_telegrenade(&mut self, telegrenade: Option<Gd<Telegrenade>>);
|
||||
fn as_gd(&self) -> DynGd<CharacterBody3D, dyn IPlayer>;
|
||||
}
|
||||
|
||||
pub trait PlayerCommon {
|
||||
@ -71,6 +80,7 @@ pub trait PlayerCommon {
|
||||
fn can_take_damage(&self, source: &DamageSource) -> bool;
|
||||
fn try_shoot_common(&mut self, to: Vector3, deal_damage: bool) -> bool;
|
||||
fn try_punch_common(&mut self, to: Vector3, deal_damage: bool) -> bool;
|
||||
fn throw_telegrenade_common(&mut self, to: Vector3) -> bool;
|
||||
}
|
||||
|
||||
impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerCommon for T {
|
||||
@ -256,6 +266,29 @@ impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerCommon for T {
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn throw_telegrenade_common(&mut self, to: Vector3) -> bool {
|
||||
if self.is_dead() {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.run_deferred(move |s| {
|
||||
if let Some(game) = &mut Game::singleton()
|
||||
&& let Some(origin) = s.get_camera_origin()
|
||||
{
|
||||
let mut telegrenade = game.bind_mut().spawn_telegrenade(
|
||||
origin.get_global_position().into(),
|
||||
(to.normalized() * 10.).into(),
|
||||
);
|
||||
if let Some(telegrenade) = &mut telegrenade {
|
||||
telegrenade.bind_mut().player = Some(s.as_gd());
|
||||
s.set_telegrenade(Some(telegrenade.clone()));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
|
||||
@ -15,6 +15,7 @@ use crate::{
|
||||
effects::PlayerEffects,
|
||||
shootable::Shootable,
|
||||
soldier_mesh::SoldierMesh,
|
||||
telegrenade::Telegrenade,
|
||||
weapon::{Weapon, WeaponType},
|
||||
},
|
||||
};
|
||||
@ -63,6 +64,8 @@ pub struct RemotePlayer {
|
||||
|
||||
punch_cd_remaining: f64,
|
||||
|
||||
pub telegrenade: Option<Gd<Telegrenade>>,
|
||||
|
||||
base: Base<CharacterBody3D>,
|
||||
}
|
||||
|
||||
@ -134,6 +137,10 @@ impl IPlayer for RemotePlayer {
|
||||
self.try_shoot_common(to, deal_damage)
|
||||
}
|
||||
|
||||
fn try_throw_telegrenade(&mut self, to: Vector3) -> bool {
|
||||
self.throw_telegrenade_common(to)
|
||||
}
|
||||
|
||||
fn try_punch(&mut self, to: Vector3, deal_damage: bool) -> bool {
|
||||
if self.punch_cd_remaining <= 0. {
|
||||
self.punch_cd_remaining = self.punch_cooldown;
|
||||
@ -253,6 +260,14 @@ impl IPlayer for RemotePlayer {
|
||||
PickupKind::Health => self.heal(100),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_telegrenade(&mut self, grenade: Option<Gd<Telegrenade>>) {
|
||||
self.telegrenade = grenade;
|
||||
}
|
||||
|
||||
fn as_gd(&self) -> DynGd<CharacterBody3D, dyn IPlayer> {
|
||||
self.to_gd().into_dyn().upcast()
|
||||
}
|
||||
}
|
||||
|
||||
#[godot_api]
|
||||
|
||||
37
rust/src/player/telegrenade.rs
Normal file
37
rust/src/player/telegrenade.rs
Normal file
@ -0,0 +1,37 @@
|
||||
use godot::{
|
||||
classes::{CharacterBody3D, IRigidBody3D, RigidBody3D},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
net::util::NetVector3,
|
||||
player::{IPlayer, NetTransform},
|
||||
};
|
||||
|
||||
#[derive(GodotClass)]
|
||||
#[class(base=RigidBody3D, init)]
|
||||
pub struct Telegrenade {
|
||||
pub player: Option<DynGd<CharacterBody3D, dyn IPlayer>>,
|
||||
|
||||
base: Base<RigidBody3D>,
|
||||
}
|
||||
|
||||
#[godot_api]
|
||||
impl IRigidBody3D for Telegrenade {
|
||||
fn ready(&mut self) {}
|
||||
}
|
||||
|
||||
impl Telegrenade {
|
||||
pub fn teleport(&mut self) {}
|
||||
|
||||
pub fn get_transform(&self) -> NetTransform {
|
||||
NetTransform {
|
||||
location: self.base().get_global_position().into(),
|
||||
rotation: self.base().get_global_rotation().into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_velocity(&self) -> NetVector3 {
|
||||
self.base().get_linear_velocity().into()
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user