aboutsummaryrefslogtreecommitdiff
path: root/server/src/entity
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2026-03-20 19:07:05 +0100
committermetamuffin <metamuffin@disroot.org>2026-03-20 19:07:05 +0100
commit67e3d5e2d501c57a1e731df698725f1695b2868f (patch)
tree297edda4307dfbe58788f0a33d9c8e3374e83335 /server/src/entity
parent65bfbd5cbfc63ad5a812e1090e70cc6d87a1b3e9 (diff)
downloadhurrycurry-67e3d5e2d501c57a1e731df698725f1695b2868f.tar
hurrycurry-67e3d5e2d501c57a1e731df698725f1695b2868f.tar.bz2
hurrycurry-67e3d5e2d501c57a1e731df698725f1695b2868f.tar.zst
tutorials for buttons
Diffstat (limited to 'server/src/entity')
-rw-r--r--server/src/entity/pedestrians.rs3
-rw-r--r--server/src/entity/tutorial.rs120
2 files changed, 103 insertions, 20 deletions
diff --git a/server/src/entity/pedestrians.rs b/server/src/entity/pedestrians.rs
index 4fe91464..40ec721d 100644
--- a/server/src/entity/pedestrians.rs
+++ b/server/src/entity/pedestrians.rs
@@ -1,5 +1,3 @@
-use crate::random_gauss;
-
/*
Hurry Curry! - a game about cooking
Copyright (C) 2025 Hurry Curry! Contributors
@@ -18,6 +16,7 @@ use crate::random_gauss;
*/
use super::{Entity, EntityContext};
+use crate::random_gauss;
use anyhow::Result;
use hurrycurry_locale::TrError;
use hurrycurry_protocol::{Character, PacketS, PlayerClass, PlayerID, glam::Vec2};
diff --git a/server/src/entity/tutorial.rs b/server/src/entity/tutorial.rs
index 87896a09..47ec2aff 100644
--- a/server/src/entity/tutorial.rs
+++ b/server/src/entity/tutorial.rs
@@ -19,34 +19,60 @@ use super::{Entity, EntityContext};
use anyhow::Result;
use hurrycurry_locale::{TrError, trm};
use hurrycurry_protocol::{
- ItemIndex, Message, PacketC, PlayerID, Recipe, RecipeIndex, TileIndex, glam::IVec2,
+ ItemIndex, ItemLocation, Message, PacketC, PlayerID, Recipe, RecipeIndex, TileIndex,
+ glam::IVec2,
};
use log::{debug, warn};
pub struct Tutorial {
pub player: PlayerID,
- target: ItemIndex,
-
+ state: TutorialState,
next_update_due: f32,
- had_aquired_target: bool,
-
current_hint: Option<(Option<IVec2>, Message)>,
delete_timer: f32,
pub ended: bool,
}
+pub enum TutorialState {
+ Item {
+ item: ItemIndex,
+ had_aquired_target: bool,
+ },
+ Button {
+ tile: TileIndex,
+ pressed: bool,
+ },
+}
+
impl Tutorial {
- pub fn new(player: PlayerID, item: ItemIndex) -> Self {
+ fn new(player: PlayerID, target: TutorialState) -> Self {
Self {
ended: false,
player,
next_update_due: 0.,
- target: item,
+ state: target,
current_hint: None,
delete_timer: 1.5,
- had_aquired_target: false,
}
}
+ pub fn new_item(player: PlayerID, item: ItemIndex) -> Self {
+ Self::new(
+ player,
+ TutorialState::Item {
+ item,
+ had_aquired_target: false,
+ },
+ )
+ }
+ pub fn new_button(player: PlayerID, tile: TileIndex) -> Self {
+ Self::new(
+ player,
+ TutorialState::Button {
+ tile,
+ pressed: false,
+ },
+ )
+ }
}
impl Entity for Tutorial {
@@ -63,10 +89,34 @@ impl Entity for Tutorial {
}
c.packet_out.push_back(PacketC::TutorialEnded {
player: self.player,
- item: self.target,
+ item: match &self.state {
+ TutorialState::Item { item, .. } => *item,
+ _ => ItemIndex(0), // TODO
+ },
success: false,
});
}
+ fn interact(
+ &mut self,
+ c: EntityContext<'_>,
+ target: Option<ItemLocation>,
+ player: PlayerID,
+ ) -> Result<bool, TrError> {
+ if player == self.player {
+ match (&mut self.state, target) {
+ (TutorialState::Button { tile, pressed }, Some(ItemLocation::Tile(pos))) => {
+ if let Some(t) = c.game.tiles.get(&pos) {
+ if t.parts.contains(tile) {
+ *pressed = true;
+ }
+ }
+ }
+ _ => (),
+ };
+ }
+ Ok(false)
+ }
+
fn tick(&mut self, c: EntityContext<'_>) -> Result<(), TrError> {
if self.ended {
return Ok(());
@@ -78,21 +128,30 @@ impl Entity for Tutorial {
}
self.next_update_due += TARGET_DT;
- let mut hint = StepContext {
- ent: &c,
- had_aquired_target: &mut self.had_aquired_target,
- player: self.player,
- recursion_abort: 0,
- }
- .fulfil_demand(self.target)
- .err();
+ let mut hint = match &mut self.state {
+ TutorialState::Item {
+ item,
+ had_aquired_target,
+ } => StepContext {
+ ent: &c,
+ had_aquired_target,
+ player: self.player,
+ recursion_abort: 0,
+ }
+ .fulfil_demand(*item)
+ .err(),
+ TutorialState::Button { tile, pressed } => find_button(&c, *tile, *pressed),
+ };
if hint.is_none() {
self.delete_timer -= TARGET_DT;
if self.delete_timer <= 0. {
self.ended = true;
hint = None;
c.packet_out.push_back(PacketC::TutorialEnded {
- item: self.target,
+ item: match &self.state {
+ TutorialState::Item { item, .. } => *item,
+ _ => ItemIndex(0),
+ },
player: self.player,
success: true,
});
@@ -123,6 +182,31 @@ impl Entity for Tutorial {
}
}
+fn find_button(
+ ent: &EntityContext,
+ tile: TileIndex,
+ pressed: bool,
+) -> Option<(Option<IVec2>, Message)> {
+ if pressed {
+ return None;
+ }
+ ent.game
+ .tile_index
+ .get(&tile)
+ .map(|pos| pos.iter().next())
+ .flatten()
+ .map(|p| {
+ (
+ Some(*p),
+ match ent.game.data.tile_name(tile) {
+ "book" => trm!("s.tutorial.button.book"),
+ "map-selector" => trm!("s.tutorial.button.map_selector"),
+ _ => trm!("s.tutorial.interact"),
+ },
+ )
+ })
+}
+
struct StepContext<'a> {
ent: &'a EntityContext<'a>,
had_aquired_target: &'a mut bool,