summaryrefslogtreecommitdiff
path: root/dungeon/src/entity.rs
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-11-20 10:39:36 -0500
committerFreya Murphy <freya@freyacat.org>2025-11-20 10:39:36 -0500
commit825d0657b4a312bfa33567846a9abfb782f767e4 (patch)
tree70a6b7ce15ea66a586a082e45059b24d3ff15606 /dungeon/src/entity.rs
parentdungeon: entity death (diff)
downloadDungeonCrawl-825d0657b4a312bfa33567846a9abfb782f767e4.tar.gz
DungeonCrawl-825d0657b4a312bfa33567846a9abfb782f767e4.tar.bz2
DungeonCrawl-825d0657b4a312bfa33567846a9abfb782f767e4.zip
dungeon: pickup items
Diffstat (limited to 'dungeon/src/entity.rs')
-rw-r--r--dungeon/src/entity.rs155
1 files changed, 143 insertions, 12 deletions
diff --git a/dungeon/src/entity.rs b/dungeon/src/entity.rs
index da807c2..d6ca7e5 100644
--- a/dungeon/src/entity.rs
+++ b/dungeon/src/entity.rs
@@ -8,7 +8,7 @@ use std::{
use rand::Rng;
use crate::{
- Dungeon, astar, const_pos,
+ Dungeon, PlayerAction, astar, const_pos,
map::Floor,
player_input::PlayerInput,
pos::{Direction, FPos, Pos},
@@ -46,24 +46,23 @@ pub enum Item {
LargeBomb,
}
impl Item {
- pub fn consume(self, dungeon: &mut Dungeon) {
+ pub fn consume(self, player: &mut Player, floor: &mut Floor) {
match self {
Self::HeartFragment => {
- dungeon.player.entity.heal(1);
+ player.entity.heal(1);
}
Self::HealthPotion => {
- dungeon.player.entity.heal(3);
+ player.entity.heal(3);
}
Self::SpeedPotion => {
- dungeon.player.potion_timer =
- Instant::now().checked_add(Duration::from_secs(5));
- dungeon.player.entity.speed = dungeon.player.entity.speed.inc();
+ player.potion_timer = Instant::now().checked_add(Duration::from_secs(5));
+ player.entity.speed = player.entity.speed.inc();
}
Self::Bomb => {
- dungeon.floor.explode(dungeon.player.entity.pos, 1);
+ floor.explode(player.entity.pos, 1);
}
Self::LargeBomb => {
- dungeon.floor.explode(dungeon.player.entity.pos, 2);
+ floor.explode(player.entity.pos, 2);
}
}
}
@@ -330,6 +329,14 @@ impl Entity {
pub const fn is_alive(&self) -> bool {
!self.is_dead()
}
+
+ /// Returns the item in the entity (if this entity is an item)
+ pub const fn get_item(&self) -> Option<Item> {
+ match &self.kind {
+ EntityKind::Item(item) => Some(*item),
+ _ => None,
+ }
+ }
}
/// The current "weapon" level we have
@@ -360,6 +367,7 @@ pub struct Player {
// How long until we reset potion effects?
pub potion_timer: Option<Instant>,
pub active_inv_slot: usize,
+ pub last_drop_time: Instant,
}
impl Player {
/// Instantiates the game player at a given `Pos`
@@ -372,18 +380,20 @@ impl Player {
/// let pos = Pos::new(1, 2).unwrap();
/// let player = Player::new(pos);
/// ```
- pub const fn new(pos: Pos) -> Self {
+ pub fn new(pos: Pos) -> Self {
let entity = Entity::player(pos);
let inventory = vec![];
let weapon = Weapon::RustyKnife;
let potion_timer = None;
let active_inv_slot = 0;
+ let last_drop_time = Instant::now();
Self {
entity,
inventory,
weapon,
potion_timer,
active_inv_slot,
+ last_drop_time,
}
}
}
@@ -395,7 +405,7 @@ impl Default for Player {
}
struct Updater<'a> {
- floor: &'a Floor,
+ floor: &'a mut Floor,
rng: &'a mut DungeonRng,
player_pos: Pos,
input: PlayerInput,
@@ -530,11 +540,104 @@ impl Updater<'_> {
entity.dir = dir;
}
}
+
+ /// Update player potion timer
+ fn update_player_potion_effects(player: &mut Player) {
+ if let Some(timer) = player.potion_timer
+ && Instant::now() > timer
+ {
+ player.potion_timer = None;
+ player.entity.speed = player.entity.kind.initial_speed();
+ }
+ }
+
+ /// Handle player "Use Item"
+ fn handle_player_use_item(&mut self, player: &mut Player, action: &mut PlayerAction) {
+ if self.input.use_item && player.active_inv_slot < player.inventory.len() {
+ let item = player.inventory.remove(player.active_inv_slot);
+ action.potion = item.is_potion();
+ action.bomb = item.is_bomb();
+ item.consume(player, self.floor);
+ }
+ }
+
+ /// Handle player "Drop Item"
+ fn handle_player_drop_item(
+ &self,
+ player: &mut Player,
+ action: &mut PlayerAction,
+ entities: &mut Vec<Entity>,
+ ) {
+ if self.input.drop && player.active_inv_slot < player.inventory.len() {
+ let item = player.inventory.remove(player.active_inv_slot);
+ entities.push(Entity::new(
+ player.entity.pos,
+ Direction::East,
+ EntityKind::Item(item),
+ ));
+ player.active_inv_slot = player
+ .active_inv_slot
+ .max(player.inventory.len().saturating_sub(1));
+ action.drop_item = true;
+ player.last_drop_time = Instant::now();
+ }
+ }
+
+ /// Handle player "Attack"
+ const fn handle_player_attack(&self, _player: &mut Player, action: &mut PlayerAction) {
+ if self.input.attack {
+ // TODO: attack
+ action.attack = true;
+ }
+ }
+
+ /// Handle player "Pickup Items"
+ fn handle_player_pickup_items(
+ player: &mut Player,
+ action: &mut PlayerAction,
+ entities: &mut Vec<Entity>,
+ ) {
+ if player.last_drop_time.elapsed() < Duration::from_secs(3) {
+ // delay picking up dropped items
+ return;
+ }
+
+ let mut idx = 0;
+ loop {
+ if idx >= entities.len() {
+ break;
+ }
+ if entities[idx].fpos.abs_diff(player.entity.fpos).magnitude() >= 0.25 {
+ idx += 1;
+ continue;
+ }
+ let Some(item) = entities[idx].get_item() else {
+ idx += 1;
+ continue;
+ };
+ if player.inventory.len() < PLAYER_INVENTORY_SIZE_USIZE {
+ entities.remove(idx);
+ player.inventory.push(item);
+ action.pickup_item = true;
+ } else {
+ idx += 1;
+ }
+ }
+ }
+
+ /// Handle player "Change INV Slot"
+ const fn handle_player_inv_slot(&self, player: &mut Player) {
+ if let Some(slot) = self.input.inv_slot
+ && slot < PLAYER_INVENTORY_SIZE_USIZE
+ {
+ player.active_inv_slot = slot;
+ }
+ }
}
impl Dungeon {
pub(crate) fn update_entities(&mut self, input: PlayerInput, delta_time: f32) {
let mut updater = Updater {
- floor: &self.floor,
+ floor: &mut self.floor,
rng: &mut self.game_rng,
player_pos: self.player.entity.pos,
input,
@@ -551,4 +654,32 @@ impl Dungeon {
}
self.entities.retain(Entity::is_alive);
}
+
+ pub(crate) fn update_player(
+ &mut self,
+ input: PlayerInput,
+ delta_time: f32,
+ ) -> PlayerAction {
+ let mut updater = Updater {
+ floor: &mut self.floor,
+ rng: &mut self.game_rng,
+ player_pos: self.player.entity.pos,
+ input,
+ delta_time,
+ };
+
+ let mut action = PlayerAction::default();
+ Updater::update_player_potion_effects(&mut self.player);
+ updater.handle_player_use_item(&mut self.player, &mut action);
+ updater.handle_player_drop_item(&mut self.player, &mut action, &mut self.entities);
+ Updater::handle_player_pickup_items(
+ &mut self.player,
+ &mut action,
+ &mut self.entities,
+ );
+ updater.handle_player_attack(&mut self.player, &mut action);
+ updater.handle_player_inv_slot(&mut self.player);
+
+ action
+ }
}