skullball/rust/src/goal.rs

63 lines
1.8 KiB
Rust

use godot::{
classes::{Area3D, IArea3D, MeshInstance3D, ShaderMaterial},
prelude::*,
};
use crate::{game::Game, net::network_manager::NetworkManager, player::ball::Ball};
#[derive(GodotClass)]
#[class(base=Area3D, init)]
pub struct Goal {
#[export]
pub team: u8,
#[export]
pub mesh: Option<Gd<MeshInstance3D>>,
base: Base<Area3D>,
}
#[godot_api]
impl IArea3D for Goal {
fn ready(&mut self) {
if let Some(game) = Game::singleton() {
if let Some(team) = game.bind().get_team(self.team)
&& let Some(mesh) = &mut self.mesh
&& let Some(mat) = mesh.get_active_material(0)
&& let Ok(mut mat) = mat.try_cast::<ShaderMaterial>()
{
mat.set_shader_parameter("goal_color", &team.bind().color.to_variant());
}
}
self.base()
.signals()
.body_entered()
.connect_other(self, |s, other| s.on_enter(other));
}
}
impl Goal {
fn on_enter(&self, node: Gd<Node3D>) {
if let Ok(mut ball) = node.try_cast::<Ball>()
&& !ball.bind().entered_goal
{
ball.bind_mut().entered_goal = true;
if let Some(mut game) = Game::singleton() {
let teams = game
.bind()
.get_teams()
.iter_shared()
.enumerate()
.map(|(id, _)| id as u8)
.filter(|id| *id != self.team)
.collect();
if NetworkManager::singleton().bind().is_host() {
game.bind_mut().respawn_ball();
game.bind_mut()
.handle_goal(ball.bind().dropper.unwrap_or(0), teams);
}
}
}
}
}