sevenx_engine 0.2.11

Engine de jogos 2D/3D completa com suporte Android, física, áudio, partículas, tilemap, UI, eventos e sistema 3D avançado com PBR.
Documentation
// Sistema de Inventário para RPGs
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Inventory {
    pub slots: Vec<Option<ItemStack>>,
    pub max_slots: usize,
    pub gold: u32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ItemStack {
    pub item: Item,
    pub quantity: u32,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Item {
    pub id: String,
    pub name: String,
    pub description: String,
    pub item_type: ItemType,
    pub rarity: ItemRarity,
    pub value: u32,
    pub max_stack: u32,
    pub icon_path: Option<String>,
    pub stats: HashMap<String, i32>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ItemType {
    Weapon,
    Armor,
    Consumable,
    Quest,
    Material,
    Misc,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ItemRarity {
    Common,
    Uncommon,
    Rare,
    Epic,
    Legendary,
}

impl Inventory {
    pub fn new(max_slots: usize) -> Self {
        Self {
            slots: vec![None; max_slots],
            max_slots,
            gold: 0,
        }
    }

    pub fn add_item(&mut self, item: Item, quantity: u32) -> bool {
        // Tenta empilhar em slot existente
        if item.max_stack > 1 {
            for slot in &mut self.slots {
                if let Some(stack) = slot {
                    if stack.item.id == item.id && stack.quantity < item.max_stack {
                        let space = item.max_stack - stack.quantity;
                        let to_add = quantity.min(space);
                        stack.quantity += to_add;
                        
                        if to_add == quantity {
                            return true;
                        }
                    }
                }
            }
        }

        // Adiciona em slot vazio
        for slot in &mut self.slots {
            if slot.is_none() {
                *slot = Some(ItemStack { item, quantity });
                return true;
            }
        }

        false // Inventário cheio
    }

    pub fn remove_item(&mut self, item_id: &str, quantity: u32) -> bool {
        let mut remaining = quantity;

        for slot in &mut self.slots {
            if let Some(stack) = slot {
                if stack.item.id == item_id {
                    if stack.quantity >= remaining {
                        stack.quantity -= remaining;
                        if stack.quantity == 0 {
                            *slot = None;
                        }
                        return true;
                    } else {
                        remaining -= stack.quantity;
                        *slot = None;
                    }
                }
            }
        }

        remaining == 0
    }

    pub fn has_item(&self, item_id: &str, quantity: u32) -> bool {
        let mut count = 0;
        for slot in &self.slots {
            if let Some(stack) = slot {
                if stack.item.id == item_id {
                    count += stack.quantity;
                }
            }
        }
        count >= quantity
    }

    pub fn get_item_count(&self, item_id: &str) -> u32 {
        let mut count = 0;
        for slot in &self.slots {
            if let Some(stack) = slot {
                if stack.item.id == item_id {
                    count += stack.quantity;
                }
            }
        }
        count
    }

    pub fn swap_slots(&mut self, from: usize, to: usize) -> bool {
        if from >= self.max_slots || to >= self.max_slots {
            return false;
        }
        self.slots.swap(from, to);
        true
    }

    pub fn add_gold(&mut self, amount: u32) {
        self.gold += amount;
    }

    pub fn remove_gold(&mut self, amount: u32) -> bool {
        if self.gold >= amount {
            self.gold -= amount;
            true
        } else {
            false
        }
    }

    pub fn is_full(&self) -> bool {
        self.slots.iter().all(|slot| slot.is_some())
    }

    pub fn empty_slots(&self) -> usize {
        self.slots.iter().filter(|slot| slot.is_none()).count()
    }
}

impl Item {
    pub fn new(id: &str, name: &str) -> Self {
        Self {
            id: id.to_string(),
            name: name.to_string(),
            description: String::new(),
            item_type: ItemType::Misc,
            rarity: ItemRarity::Common,
            value: 0,
            max_stack: 1,
            icon_path: None,
            stats: HashMap::new(),
        }
    }

    pub fn weapon(id: &str, name: &str, damage: i32) -> Self {
        let mut item = Self::new(id, name);
        item.item_type = ItemType::Weapon;
        item.stats.insert("damage".to_string(), damage);
        item
    }

    pub fn armor(id: &str, name: &str, defense: i32) -> Self {
        let mut item = Self::new(id, name);
        item.item_type = ItemType::Armor;
        item.stats.insert("defense".to_string(), defense);
        item
    }

    pub fn consumable(id: &str, name: &str, heal: i32) -> Self {
        let mut item = Self::new(id, name);
        item.item_type = ItemType::Consumable;
        item.max_stack = 99;
        item.stats.insert("heal".to_string(), heal);
        item
    }

    pub fn get_rarity_color(&self) -> [u8; 4] {
        match self.rarity {
            ItemRarity::Common => [200, 200, 200, 255],
            ItemRarity::Uncommon => [100, 255, 100, 255],
            ItemRarity::Rare => [100, 100, 255, 255],
            ItemRarity::Epic => [200, 100, 255, 255],
            ItemRarity::Legendary => [255, 200, 0, 255],
        }
    }
}