/* Hurry Curry! - a game about cooking Copyright 2025 metamuffin This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License only. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ use super::{Entity, EntityContext}; use anyhow::Result; use hurrycurry_protocol::{glam::Vec2, Character, PacketS, PlayerClass, PlayerID}; use rand::random; pub struct Tram { pub length: usize, pub character: Character, pub ids: Vec, pub points: Vec, pub progress: f32, pub spacing: f32, pub smoothing: f32, } impl Entity for Tram { fn finished(&self) -> bool { false } fn tick(&mut self, c: EntityContext<'_>) -> Result<()> { if self.ids.is_empty() { for i in 0..self.length { let id = PlayerID(random()); c.packet_in.push_back(PacketS::Join { name: format!("Tram {i}"), character: self.character, class: PlayerClass::Tram, id: Some(id), position: self.points.first().copied(), }); self.ids.push(id); } } for (i, id) in self.ids.iter().enumerate() { if let Some(player) = c.game.players.get(id) { let t = self.progress + self.spacing * i as f32; let i = t.trunc() as usize; let p_a = self.points[i % self.points.len()]; let p_b = self.points[(i + 1) % self.points.len()]; let p = p_a.lerp(p_b, t.fract()); if p.distance(player.movement.position) < self.smoothing { self.progress += 0.1; self.progress %= self.points.len() as f32; }; let dir = if player.movement.position.distance(p) > self.smoothing * 0.8 { p - player.movement.position } else { Vec2::ZERO }; c.packet_in.push_back(PacketS::Movement { player: *id, dir, boost: false, pos: None, }); } } Ok(()) } fn destructor(&mut self, c: EntityContext<'_>) { for id in self.ids.drain(..) { c.packet_in.push_back(PacketS::Leave { player: id }) } } }