/* 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, PacketS, PlayerClass, PlayerID}; use rand::random; pub struct Tram { length: usize, character: i32, ids: Vec, points: Vec, index: usize, } impl Tram { pub fn new(character: i32, length: usize, points: Vec) -> Self { Self { character, ids: Vec::new(), length, points, index: 0, } } } 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::Bot, id: Some(id), }); self.ids.push(id); } } let mut ppos = None; for id in &self.ids { if let Some(p) = c.game.players.get(id) { let target = if let Some(pos) = ppos { pos } else { let tar = self.points[self.index]; if p.movement.position.distance(tar) < 2. { self.index += 1; self.index %= self.points.len(); } tar }; ppos = Some(p.movement.position); let dir = if p.movement.position.distance(target) > 2. { target - p.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 }) } } }