/* Hurry Curry! - a game about cooking Copyright (C) 2025 Hurry Curry! Contributors 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_locale::TrError; use hurrycurry_protocol::{ TileIndex, glam::{IVec2, Vec2, vec2}, }; #[derive(Debug, Clone)] pub struct PlayerPortalPair { a_i: IVec2, b_i: IVec2, a_f: Vec2, b_f: Vec2, in_tile: TileIndex, neutral_tile: TileIndex, out_tile: TileIndex, state: i8, delay: f32, } impl PlayerPortalPair { pub fn new( a: IVec2, b: IVec2, in_tile: TileIndex, neutral_tile: TileIndex, out_tile: TileIndex, ) -> Self { Self { a_i: a, b_i: b, a_f: a.as_vec2() + vec2(0.5, 0.5), b_f: b.as_vec2() + vec2(0.5, 0.5), in_tile, neutral_tile, out_tile, state: 1, delay: 0., } } } impl Entity for PlayerPortalPair { fn tick(&mut self, c: EntityContext) -> Result<(), TrError> { let qn = |p, r| { let mut o = None; c.game .players_spatial_index .query(p, r, |pid, _| o = Some(pid)); o }; self.delay -= c.dt; let near_a = qn(self.a_f, 1.5); let near_b = qn(self.b_f, 1.5); let in_a = qn(self.a_f, 0.7); let in_b = qn(self.b_f, 0.7); if (self.state == 1 && near_b.is_none() && in_a.is_none()) || (self.state == -1 && near_a.is_none() && in_b.is_none()) { c.game.remove_tile_part(self.a_i, self.in_tile); c.game.remove_tile_part(self.a_i, self.out_tile); c.game.add_tile_part(self.a_i, self.neutral_tile); c.game.remove_tile_part(self.b_i, self.in_tile); c.game.remove_tile_part(self.b_i, self.out_tile); c.game.add_tile_part(self.b_i, self.neutral_tile); self.state = 0; return Ok(()); } if self.state == 0 && in_a.is_some() { c.game.remove_tile_part(self.a_i, self.neutral_tile); c.game.remove_tile_part(self.b_i, self.neutral_tile); c.game.add_tile_part(self.a_i, self.in_tile); c.game.add_tile_part(self.b_i, self.out_tile); self.state = 1; self.delay = 0.2; return Ok(()); } if self.state == 0 && in_b.is_some() { c.game.remove_tile_part(self.b_i, self.neutral_tile); c.game.remove_tile_part(self.a_i, self.neutral_tile); c.game.add_tile_part(self.b_i, self.in_tile); c.game.add_tile_part(self.a_i, self.out_tile); self.state = -1; self.delay = 0.2; return Ok(()); } if self.state == 1 && self.delay < 0. && let Some(player) = in_a && let Some(p) = c.game.players.get_mut(&player) { p.movement.position = self.b_f; p.movement_must_sync = true; } if self.state == -1 && self.delay < 0. && let Some(player) = in_b && let Some(p) = c.game.players.get_mut(&player) { p.movement.position = self.a_f; p.movement_must_sync = true; } Ok(()) } }