Compare commits

..

No commits in common. "e015978b9f1b23b7656ed247c0fce1789df407b6" and "c5d386b7550fc07115cf57eed78ac4c9049acd8b" have entirely different histories.

11 changed files with 2 additions and 358 deletions

View File

@ -1,27 +0,0 @@
extends Triggerable
@export var mesh: MeshInstance3D
func update_appearance(time: float) -> void:
var progress = clamp(time, 0.0, 1.0);
var new_color = Color.RED * (1.0 - progress) + Color.WHITE * progress
if mesh != null:
mesh.get_active_material(0).set("albedo_color", new_color)
func _activate_visual(player_id: int, time_since_activation: float) -> void:
update_appearance(time_since_activation)
func _deactivate_visual() -> void:
update_appearance(1.0)
func _on_activate() -> bool:
return false
func _process(delta: float) -> void:
if is_server_active():
if server_active_for() > 1.0:
deactivate()
if is_active():
update_appearance(active_for())
else:
update_appearance(1.0)

View File

@ -1 +0,0 @@
uid://cijpblptlwvs

View File

@ -1,16 +1,8 @@
[gd_scene format=3 uid="uid://c5p0ft870i1sk"] [gd_scene format=3 uid="uid://c5p0ft870i1sk"]
[ext_resource type="PackedScene" uid="uid://dpqqe7hjktit8" path="res://maps/two_towers/two_towers_static.scn" id="2_l5vmt"] [ext_resource type="PackedScene" uid="uid://dpqqe7hjktit8" path="res://maps/two_towers/two_towers_static.scn" id="2_l5vmt"]
[ext_resource type="Script" uid="uid://cijpblptlwvs" path="res://maps/scripts/test.gd" id="3_vwb5y"]
[ext_resource type="Script" uid="uid://diepa0rcedh5f" path="res://maps/meta/map_rebuilder.gd" id="4_y3aqj"] [ext_resource type="Script" uid="uid://diepa0rcedh5f" path="res://maps/meta/map_rebuilder.gd" id="4_y3aqj"]
[sub_resource type="BoxShape3D" id="BoxShape3D_1cgct"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_vwb5y"]
[sub_resource type="BoxMesh" id="BoxMesh_1cgct"]
material = SubResource("StandardMaterial3D_vwb5y")
[node name="two_towers" type="Map" unique_id=590524284 node_paths=PackedStringArray("spawners", "ball_spawner")] [node name="two_towers" type="Map" unique_id=590524284 node_paths=PackedStringArray("spawners", "ball_spawner")]
spawners = [NodePath("two_towers_static/func_godot_map/entity_11_info_spawn_point"), NodePath("two_towers_static/func_godot_map/entity_5_info_spawn_point")] spawners = [NodePath("two_towers_static/func_godot_map/entity_11_info_spawn_point"), NodePath("two_towers_static/func_godot_map/entity_5_info_spawn_point")]
ball_spawner = NodePath("two_towers_static/func_godot_map/entity_1_info_spawn_point") ball_spawner = NodePath("two_towers_static/func_godot_map/entity_1_info_spawn_point")
@ -19,19 +11,3 @@ ball_spawner = NodePath("two_towers_static/func_godot_map/entity_1_info_spawn_po
script = ExtResource("4_y3aqj") script = ExtResource("4_y3aqj")
[node name="two_towers_static" parent="." unique_id=86902040 instance=ExtResource("2_l5vmt")] [node name="two_towers_static" parent="." unique_id=86902040 instance=ExtResource("2_l5vmt")]
[node name="triggerable" type="Triggerable" parent="." unique_id=1206596848 node_paths=PackedStringArray("mesh")]
script = ExtResource("3_vwb5y")
mesh = NodePath("mesh_instance_3d")
[node name="shootable_trigger" type="ShootableTrigger" parent="triggerable" unique_id=306909670]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 42.184772, 10.981467, 7.8725615)
[node name="collision_shape_3d" type="CollisionShape3D" parent="triggerable/shootable_trigger" unique_id=298869370]
shape = SubResource("BoxShape3D_1cgct")
[node name="mesh_instance_3d" type="MeshInstance3D" parent="triggerable" unique_id=174590790]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 42.184772, 10.981467, 7.8725615)
mesh = SubResource("BoxMesh_1cgct")
[connection signal="on_shot" from="triggerable/shootable_trigger" to="triggerable" method="activate" unbinds=2]

View File

@ -384,19 +384,6 @@ impl Game {
character.set_visible(true); character.set_visible(true);
} }
} }
if let Some(map) = &mut self.current_map {
for (_, triggerable) in &mut map.bind_mut().triggerables {
let player_id = triggerable.bind().get_active().clone();
if let Some(player_id) = player_id {
let active_for = triggerable.bind().server_active_for();
triggerable
.bind_mut()
.activate_visual(player_id, active_for);
} else {
triggerable.bind_mut().deactivate_visual();
}
}
}
if let Some(ball) = &mut self.world_ball { if let Some(ball) = &mut self.world_ball {
ball.set_visible(true); ball.set_visible(true);
} }
@ -1363,52 +1350,6 @@ impl Game {
}); });
} }
pub fn on_trigger_activate(&mut self, id: u8, player_id: u16) {
self.run_deferred(move |s| {
if s.current_replay_playback.is_none()
&& let Some(map) = &mut s.current_map
&& let Some(triggerable) = map.bind_mut().triggerables.get_mut(&id)
{
triggerable.bind_mut().activate_visual(player_id, 0.);
}
if let Some(recorder) = &mut s.replay_recorder {
recorder
.bind_mut()
.record_event(ReplayEvent::TriggerActivate(id, player_id));
}
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer
&& let PeerKind::Server(peer, _) = peer
{
peer.broadcast_reliable(Package::TriggerActivate(id, player_id));
}
});
}
pub fn on_trigger_deactivate(&mut self, id: u8) {
self.run_deferred(move |s| {
if s.current_replay_playback.is_none()
&& let Some(map) = &mut s.current_map
&& let Some(triggerable) = map.bind_mut().triggerables.get_mut(&id)
{
triggerable.bind_mut().deactivate_visual();
}
if let Some(recorder) = &mut s.replay_recorder {
recorder
.bind_mut()
.record_event(ReplayEvent::TriggerDeactivate(id));
}
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer
&& let PeerKind::Server(peer, _) = peer
{
peer.broadcast_reliable(Package::TriggerDeactivate(id));
}
});
}
pub fn spawn_telegrenade( pub fn spawn_telegrenade(
&mut self, &mut self,
player_id: u16, player_id: u16,

View File

@ -4,7 +4,7 @@ use godot::{classes::CharacterBody3D, prelude::*};
use crate::{ use crate::{
game::{Game, GameManager}, game::{Game, GameManager},
map::{pickup::Pickup, triggers::Triggerable}, map::pickup::Pickup,
net::util::NetVector3, net::util::NetVector3,
player::{ player::{
IPlayer, NetTransform, ball::Ball, local_player::LocalPlayer, remote_player::RemotePlayer, IPlayer, NetTransform, ball::Ball, local_player::LocalPlayer, remote_player::RemotePlayer,
@ -18,7 +18,6 @@ pub mod killbox;
pub mod map_resource; pub mod map_resource;
pub mod map_static; pub mod map_static;
pub mod pickup; pub mod pickup;
pub mod triggers;
#[derive(GodotClass)] #[derive(GodotClass)]
#[class(base=Node3D, init)] #[class(base=Node3D, init)]
@ -31,9 +30,6 @@ pub struct Map {
pickup_counter: u8, pickup_counter: u8,
pub pickups: HashMap<u8, DynGd<Node3D, dyn Pickup>>, pub pickups: HashMap<u8, DynGd<Node3D, dyn Pickup>>,
triggerable_counter: u8,
pub triggerables: HashMap<u8, Gd<Triggerable>>,
base: Base<Node3D>, base: Base<Node3D>,
} }
@ -213,13 +209,6 @@ impl Map {
id id
} }
pub fn register_triggerable(&mut self, triggerable: Gd<Triggerable>) -> u8 {
let id = self.triggerable_counter;
self.triggerable_counter += 1;
self.triggerables.insert(id, triggerable);
id
}
pub fn spawn_telegrenade( pub fn spawn_telegrenade(
&mut self, &mut self,
location: NetVector3, location: NetVector3,

View File

@ -1,169 +0,0 @@
use godot::{classes::Area3D, prelude::*};
use crate::{
game::Game,
map::Map,
net::network_manager::NetworkManager,
player::{DamageSource, shootable::Shootable},
replay::StandaloneReplayManager,
};
#[derive(GodotClass)]
#[class(base=Node3D, init)]
pub struct Triggerable {
triggerable_id: Option<u8>,
/// Contains the activator player's ID if active.
active: Option<u16>,
active_for: f64,
visual_active: Option<u16>,
visual_active_for: f64,
base: Base<Node3D>,
}
#[godot_api]
impl INode3D for Triggerable {
fn ready(&mut self) {
if let Some(game) = &Game::singleton() {
game.signals()
.on_map_loaded()
.connect_other(self, Self::register_triggerable);
} else {
StandaloneReplayManager::singleton()
.signals()
.on_map_loaded()
.connect_other(self, Self::register_triggerable);
}
}
fn physics_process(&mut self, delta: f64) {
if self.active.is_some() {
self.active_for += delta;
} else {
self.active_for = 0.;
}
if self.visual_active.is_some() {
self.visual_active_for += delta;
} else {
self.visual_active_for = 0.;
}
}
}
#[godot_api]
impl Triggerable {
/// Called whenever this triggerable's visuals should be immediately
/// activated.
#[func(virtual)]
pub fn on_activate_visual(&mut self, _player_id: u16, _time_since_activation: f64) {}
/// Called whenever this triggerable's visuals should be immediately
/// deactivated.
#[func(virtual)]
pub fn on_deactivate_visual(&mut self) {}
/// Called whenever this triggerable is activated on the server-side.
/// Returns a bool indicating if this triggerable should be immediately
/// deactivated. Defaults to true.
#[func(virtual)]
pub fn on_activate(&mut self) -> bool {
true
}
/// Called whenever this triggerable is deactivated on the server-side.
#[func(virtual)]
pub fn on_deactivate(&mut self) {}
pub fn activate_visual(&mut self, player_id: u16, time_since_activation: f64) {
self.visual_active = Some(player_id);
self.visual_active_for = time_since_activation;
self.on_activate_visual(player_id, time_since_activation);
}
pub fn deactivate_visual(&mut self) {
self.visual_active = None;
self.visual_active_for = 0.;
self.on_deactivate_visual();
}
/// Activates this trigger. Active triggerables can not be re-activated
/// without being deactivated first. Only executes on the server-side.
#[func]
pub fn activate(&mut self, player_id: u16) {
if NetworkManager::singleton().bind().is_host() && !self.active.is_some() {
self.active = Some(player_id);
if let Some(game) = &mut Game::singleton() {
game.bind_mut()
.on_trigger_activate(self.triggerable_id.unwrap_or(0), player_id);
}
if self.on_activate() {
self.deactivate();
}
}
}
/// Deactivates this trigger. Only executes on the server-side.
#[func]
pub fn deactivate(&mut self) {
if NetworkManager::singleton().bind().is_host() {
self.active = None;
if let Some(game) = &mut Game::singleton() {
game.bind_mut()
.on_trigger_deactivate(self.triggerable_id.unwrap_or(0));
}
self.on_deactivate();
}
}
#[func]
pub fn is_server_active(&self) -> bool {
self.active.is_some()
}
#[func]
pub fn server_active_for(&self) -> f64 {
self.active_for
}
#[func]
pub fn is_active(&self) -> bool {
self.visual_active.is_some()
}
#[func]
pub fn active_for(&self) -> f64 {
self.visual_active_for
}
pub fn get_active(&self) -> Option<u16> {
self.active
}
fn register_triggerable(&mut self, mut map: Gd<Map>) {
self.run_deferred(move |s| {
let id = map.bind_mut().register_triggerable(s.to_gd());
s.triggerable_id = Some(id);
});
}
}
#[derive(GodotClass)]
#[class(base=Area3D, init)]
pub struct ShootableTrigger {
base: Base<Area3D>,
}
#[godot_api]
impl ShootableTrigger {
#[signal]
pub fn on_shot(player: u16, damage: i32, dir: Vector3);
}
#[godot_dyn]
impl Shootable for ShootableTrigger {
fn on_shoot(&mut self, source: DamageSource, damage: i32, dir: Vector3) {
if let DamageSource::Player(id) = source {
self.signals().on_shot().emit(id, damage, dir);
}
}
}

View File

@ -362,8 +362,6 @@ pub enum Package {
Goal(u16, Vec<u8>), Goal(u16, Vec<u8>),
Announcement(u16, Announcement), Announcement(u16, Announcement),
Pickup(u8, u16), Pickup(u8, u16),
TriggerActivate(u8, u16),
TriggerDeactivate(u8),
ThrowTelegrenade(u16, NetVector3), ThrowTelegrenade(u16, NetVector3),
TelegrenadeTeleport(u16, NetVector3), TelegrenadeTeleport(u16, NetVector3),
TelegrenadeActivate, TelegrenadeActivate,

View File

@ -252,16 +252,6 @@ impl NetworkManager {
game.bind_mut().opts = opts; game.bind_mut().opts = opts;
} }
} }
Package::TriggerActivate(id, player_id) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().on_trigger_activate(id, player_id);
}
}
Package::TriggerDeactivate(id) => {
if let Some(game) = &mut Game::singleton() {
game.bind_mut().on_trigger_deactivate(id);
}
}
_ => {} _ => {}
}, },
}, },

View File

@ -39,7 +39,6 @@ pub fn cast_ray(
ray.set_hit_back_faces(false); ray.set_hit_back_faces(false);
ray.set_hit_from_inside(false); ray.set_hit_from_inside(false);
ray.set_collide_with_bodies(true); ray.set_collide_with_bodies(true);
ray.set_collide_with_areas(true);
ray.set_exclude(&exclude); ray.set_exclude(&exclude);
if let Some(world) = world if let Some(world) = world
&& let Some(mut space) = world.get_direct_space_state() && let Some(mut space) = world.get_direct_space_state()

View File

@ -368,7 +368,7 @@ impl DamageSource {
} }
#[derive(Debug, GodotConvert, Clone)] #[derive(Debug, GodotConvert, Clone)]
#[godot(via = GString)] #[godot(via = u8)]
pub enum DamageSourceSignal { pub enum DamageSourceSignal {
Player, Player,
Killbox, Killbox,

View File

@ -265,8 +265,6 @@ pub struct ReplayPlayback {
pub spectated_player_id: u16, pub spectated_player_id: u16,
pub fast_forwarding: bool, pub fast_forwarding: bool,
/// True for one frame after fast-forwarding is done
pub was_fast_forwarding: bool,
pub finished: bool, pub finished: bool,
@ -355,20 +353,6 @@ impl INode for ReplayPlayback {
} }
} }
} }
if self.was_fast_forwarding {
for (id, triggerable) in &mut map.bind_mut().triggerables {
if let Some(state) = frame.triggerables.get(id) {
if let Some(player_id) = state.active {
triggerable
.bind_mut()
.activate_visual(player_id, state.active_for);
} else {
triggerable.bind_mut().deactivate_visual();
}
}
}
}
} }
for event in &frame.events { for event in &frame.events {
@ -427,20 +411,6 @@ impl INode for ReplayPlayback {
pickup.dyn_bind_mut().on_pickup(); pickup.dyn_bind_mut().on_pickup();
} }
} }
ReplayEvent::TriggerActivate(id, player_id) => {
if let Some(map) = &mut self.current_map
&& let Some(triggerable) = map.bind_mut().triggerables.get_mut(id)
{
triggerable.bind_mut().activate_visual(*player_id, 0.);
}
}
ReplayEvent::TriggerDeactivate(id) => {
if let Some(map) = &mut self.current_map
&& let Some(triggerable) = map.bind_mut().triggerables.get_mut(id)
{
triggerable.bind_mut().deactivate_visual();
}
}
ReplayEvent::TelegrenadeSpawn(player_id, location, velocity) => { ReplayEvent::TelegrenadeSpawn(player_id, location, velocity) => {
if let Some(prev_grenade) = self.telegrenades.get_mut(player_id) { if let Some(prev_grenade) = self.telegrenades.get_mut(player_id) {
prev_grenade.queue_free(); prev_grenade.queue_free();
@ -493,7 +463,6 @@ impl INode for ReplayPlayback {
self.signals().on_data_changed().emit(); self.signals().on_data_changed().emit();
} }
self.was_fast_forwarding = self.fast_forwarding;
self.fast_forwarding = false; self.fast_forwarding = false;
if !self.finished && self.current_frame_idx >= self.replay.frames.len() { if !self.finished && self.current_frame_idx >= self.replay.frames.len() {
@ -691,8 +660,6 @@ impl ReplayRecorder {
let mut pickups_visible = HashMap::new(); let mut pickups_visible = HashMap::new();
let mut triggerables = HashMap::new();
if let Some(game) = Game::singleton() { if let Some(game) = Game::singleton() {
for player in &game.bind().players { for player in &game.bind().players {
if let Some(state) = player.get_state(player.clone()) { if let Some(state) = player.get_state(player.clone()) {
@ -715,15 +682,6 @@ impl ReplayRecorder {
for (id, pickup) in &map.bind().pickups { for (id, pickup) in &map.bind().pickups {
pickups_visible.insert(*id, pickup.dyn_bind().is_active()); pickups_visible.insert(*id, pickup.dyn_bind().is_active());
} }
for (id, triggerable) in &map.bind().triggerables {
triggerables.insert(
*id,
ReplayTriggerableState {
active: triggerable.bind().get_active(),
active_for: triggerable.bind().server_active_for(),
},
);
}
} }
goals = game.bind().goals.clone(); goals = game.bind().goals.clone();
@ -735,7 +693,6 @@ impl ReplayRecorder {
time: self.time_elapsed, time: self.time_elapsed,
goals, goals,
pickups_visible, pickups_visible,
triggerables,
player_data, player_data,
ball_data, ball_data,
events: Vec::new(), events: Vec::new(),
@ -850,7 +807,6 @@ pub struct ReplayFrame {
player_data: HashMap<u16, ReplayPlayerState>, player_data: HashMap<u16, ReplayPlayerState>,
ball_data: ReplayBall, ball_data: ReplayBall,
pickups_visible: HashMap<u8, bool>, pickups_visible: HashMap<u8, bool>,
triggerables: HashMap<u8, ReplayTriggerableState>,
events: Vec<ReplayEvent>, events: Vec<ReplayEvent>,
goals: HashMap<u8, u16>, goals: HashMap<u8, u16>,
} }
@ -864,8 +820,6 @@ pub enum ReplayEvent {
Punch(u16, NetVector3), Punch(u16, NetVector3),
TakeDamage(u16, DamageSource, i32), TakeDamage(u16, DamageSource, i32),
Pickup(PickupKind, u8, u16), Pickup(PickupKind, u8, u16),
TriggerActivate(u8, u16),
TriggerDeactivate(u8),
TelegrenadeSpawn(u16, NetVector3, NetVector3), TelegrenadeSpawn(u16, NetVector3, NetVector3),
TelegrenadeDespawn(u16), TelegrenadeDespawn(u16),
} }
@ -919,9 +873,3 @@ pub struct ReplayBallData {
transform: NetTransform, transform: NetTransform,
velocity: NetVector3, velocity: NetVector3,
} }
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct ReplayTriggerableState {
active: Option<u16>,
active_for: f64,
}