feat: Add shop buy logic (#34)

This commit is contained in:
demenik
2025-12-01 15:48:08 +01:00
parent 9d69d8f253
commit 08c5312a85
3 changed files with 107 additions and 2 deletions

View File

@@ -1,4 +1,5 @@
use crate::{features::config::components::BerrySeedConfig, prelude::*}; use crate::features::config::components::BerrySeedConfig;
use crate::prelude::*;
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ItemType { pub enum ItemType {
@@ -112,6 +113,76 @@ pub struct Inventory {
pub items: Vec<Entity>, pub items: Vec<Entity>,
} }
impl Inventory {
pub fn update_item_stack(
&mut self,
commands: &mut Commands,
items_query: &mut Query<&mut ItemStack>,
item_type_to_update: ItemType,
amount_delta: i32,
) -> bool {
let mut target_entity_index: Option<usize> = None;
let mut current_stack_amount: u32 = 0;
let mut entity_id_to_update: Option<Entity> = None;
// Try to find an existing stack of the item
for (i, &entity) in self.items.iter().enumerate() {
if let Ok(stack) = items_query.get(entity) {
if stack.item_type == item_type_to_update {
target_entity_index = Some(i);
current_stack_amount = stack.amount;
entity_id_to_update = Some(entity);
break;
}
}
}
match amount_delta {
val if val > 0 => {
// Add items
let add_amount = amount_delta as u32;
if let Some(entity) = entity_id_to_update {
if let Ok(mut stack) = items_query.get_mut(entity) {
stack.amount += add_amount;
}
} else {
// Item not found, create a new stack
let new_item_stack = ItemStack {
item_type: item_type_to_update,
amount: add_amount,
};
let id = commands.spawn(new_item_stack).id();
self.items.push(id);
}
true
}
val if val < 0 => {
// Remove items
let remove_amount = amount_delta.abs() as u32;
let Some(entity) = entity_id_to_update else {
return false; // Item not found for removal
};
if current_stack_amount < remove_amount {
return false; // Not enough items
};
if let Ok(mut stack) = items_query.get_mut(entity) {
stack.amount -= remove_amount;
if stack.amount == 0 {
commands.entity(entity).despawn();
if let Some(index) = target_entity_index {
self.items.remove(index);
}
}
}
true
}
_ => true,
}
}
}
#[derive(Component)] #[derive(Component)]
pub enum RootMarker { pub enum RootMarker {
Inventory, Inventory,

View File

@@ -50,4 +50,25 @@ impl ShopOffer {
offers offers
} }
pub fn buy(
&self,
inventory: &mut Inventory,
commands: &mut Commands,
items: &mut Query<&mut ItemStack>,
) -> bool {
// Try to remove cost (berries)
if inventory.update_item_stack(commands, items, ItemType::Berry, -(self.cost as i32)) {
inventory.update_item_stack(
commands,
items,
self.item.item_type.clone(),
self.item.amount as i32,
);
true
} else {
false // Not enough berries
} }
}
}

View File

@@ -19,6 +19,8 @@ fn buttons(
root_query: Query<(Entity, &RootMarker)>, root_query: Query<(Entity, &RootMarker)>,
game_config: Res<GameConfig>, game_config: Res<GameConfig>,
asset_server: Res<AssetServer>, asset_server: Res<AssetServer>,
mut inventory: ResMut<Inventory>,
mut items: Query<&mut ItemStack>,
) { ) {
for (interaction, button_type) in &mut interaction_query { for (interaction, button_type) in &mut interaction_query {
match *interaction { match *interaction {
@@ -33,7 +35,18 @@ fn buttons(
} }
} }
} }
_ => {} ButtonType::ShopBuyItem(offer) => {
if offer.buy(&mut inventory, &mut commands, &mut items) {
// Item bought, exit the menu
for (entity, root) in root_query.iter() {
match *root {
RootMarker::Shop => commands.entity(entity).despawn(),
}
}
} else {
// Error (e.g. not enough berries)
}
}
}, },
_ => {} _ => {}
} }