//! Example demonstrating combined Items, NPCs, Quests, and Harvestables database usage //! //! Run with: cargo run --example game_data_demo use cursebreaker_parser::{ItemDatabase, NpcDatabase, QuestDatabase, HarvestableDatabase, LootDatabase}; use std::env; fn main() -> Result<(), Box> { println!("šŸŽ® Cursebreaker Game Data Demo\n"); // Load all game data println!("šŸ“š Loading game data..."); let cb_assets_path = env::var("CB_ASSETS_PATH").unwrap_or_else(|_| "/home/connor/repos/CBAssets".to_string()); let item_db = ItemDatabase::load_from_xml(&format!("{}/Data/XMLs/Items/Items.xml", cb_assets_path))?; let npc_db = NpcDatabase::load_from_xml(&format!("{}/Data/XMLs/Npcs/NPCInfo.xml", cb_assets_path))?; let quest_db = QuestDatabase::load_from_xml(&format!("{}/Data/XMLs/Quests/Quests.xml", cb_assets_path))?; let harvestable_db = HarvestableDatabase::load_from_xml(&format!("{}/Data/XMLs/Harvestables/HarvestableInfo.xml", cb_assets_path))?; let loot_db = LootDatabase::load_from_xml(&format!("{}/Data/XMLs/Loot/Loot.xml", cb_assets_path))?; println!("āœ… Loaded {} items", item_db.len()); println!("āœ… Loaded {} NPCs", npc_db.len()); println!("āœ… Loaded {} quests", quest_db.len()); println!("āœ… Loaded {} harvestables", harvestable_db.len()); println!("āœ… Loaded {} loot tables\n", loot_db.len()); // ======================================================================= // Items // ======================================================================= println!("=== Items ==="); let weapons = item_db.get_by_slot("weapon"); let armor = item_db.get_by_slot("armor"); let consumables = item_db.get_by_slot("consumable"); println!("By slot:"); println!(" • Weapons: {}", weapons.len()); println!(" • Armor: {}", armor.len()); println!(" • Consumables: {}", consumables.len()); // Find specific item if let Some(sword) = item_db.get_by_id(150) { println!("\nSample item (ID 150):"); println!(" Name: {}", sword.name); if let Some(desc) = &sword.description { println!(" Description: {}", desc); } if let Some(skill) = &sword.skill { println!(" Skill: {}", skill); } } println!(); // ======================================================================= // NPCs // ======================================================================= println!("=== NPCs ==="); let hostile = npc_db.get_hostile(); let interactable = npc_db.get_interactable(); let shopkeepers = npc_db.get_shopkeepers(); println!("By type:"); println!(" • Hostile NPCs: {}", hostile.len()); println!(" • Interactable NPCs: {}", interactable.len()); println!(" • Shopkeepers: {}", shopkeepers.len()); // Find NPCs by tag let undead = npc_db.get_by_tag("Undead"); let predators = npc_db.get_by_tag("Predator"); println!("\nBy tag:"); println!(" • Undead: {}", undead.len()); println!(" • Predators: {}", predators.len()); // Sample hostile NPC if let Some(wolf) = npc_db.get_by_id(1) { println!("\nSample hostile NPC (ID 1):"); println!(" Name: {}", wolf.name); if let Some(level) = wolf.level { println!(" Level: {}", level); } if let Some(aggro) = wolf.aggrodistance { println!(" Aggro Distance: {}", aggro); } if let Some(speed) = wolf.movementspeed { println!(" Movement Speed: {}", speed); } println!(" Stats: {} stat entries", wolf.stats.len()); } // Sample interactable NPC println!("\nSample shopkeepers:"); for shopkeeper in shopkeepers.iter().take(3) { println!(" • {} (Shop ID: {:?})", shopkeeper.name, shopkeeper.shop); } println!(); // ======================================================================= // Quests // ======================================================================= println!("=== Quests ==="); let main_quests = quest_db.get_main_quests(); let side_quests = quest_db.get_side_quests(); let hidden_quests = quest_db.get_hidden_quests(); println!("By type:"); println!(" • Main quests: {}", main_quests.len()); println!(" • Side quests: {}", side_quests.len()); println!(" • Hidden quests: {}", hidden_quests.len()); // Main quest details println!("\nMain quests:"); for quest in main_quests.iter().take(5) { println!(" • {} (ID: {}, {} phases)", quest.name, quest.id, quest.phase_count()); } // Sample quest details if let Some(quest) = quest_db.get_by_id(1) { println!("\nSample quest (ID 1):"); println!(" Name: {}", quest.name); println!(" Phases: {}", quest.phases.len()); println!(" Rewards: {}", quest.rewards.len()); if let Some(phase) = quest.get_phase(1) { if let Some(desc) = &phase.trackerdescription { println!(" Phase 1: {}", desc); } } if !quest.rewards.is_empty() { println!(" Quest rewards:"); for reward in &quest.rewards { if let Some(item_id) = reward.item { if let Some(item) = item_db.get_by_id(item_id) { println!(" - {} x{}", item.name, reward.amount.unwrap_or(1)); } } else if let Some(skill) = &reward.skill { println!(" - {} XP: {}", skill, reward.xp.unwrap_or(0)); } } } } println!(); // ======================================================================= // Harvestables // ======================================================================= println!("=== Harvestables ==="); let trees = harvestable_db.get_trees(); let woodcutting = harvestable_db.get_by_skill("Woodcutting"); let mining = harvestable_db.get_by_skill("mining"); let fishing = harvestable_db.get_by_skill("Fishing"); let alchemy = harvestable_db.get_by_skill("Alchemy"); println!("By skill:"); println!(" • Trees: {}", trees.len()); println!(" • Woodcutting: {}", woodcutting.len()); println!(" • Mining: {}", mining.len()); println!(" • Fishing: {}", fishing.len()); println!(" • Alchemy: {}", alchemy.len()); // Sample harvestable if let Some(spruce) = harvestable_db.get_by_typeid(1) { println!("\nSample harvestable (TypeID 1):"); println!(" Name: {}", spruce.name); println!(" Action: {}", spruce.actionname.as_deref().unwrap_or("N/A")); if let Some(level) = spruce.level { println!(" Level: {}", level); } if let Some(skill) = &spruce.skill { println!(" Skill: {}", skill); } if let Some(tool) = &spruce.tool { println!(" Tool: {}", tool); } println!(" Drops: {} different items", spruce.drops.len()); // Show drops println!(" Item drops:"); for drop in &spruce.drops { if let Some(item) = item_db.get_by_id(drop.id) { println!(" - {} ({}x{}, rate: {})", item.name, drop.minamount.unwrap_or(1), drop.maxamount.unwrap_or(1), drop.droprate.unwrap_or(0)); } } } println!("\nHarvestables by level:"); let low_level = harvestable_db.get_by_level_range(1, 10); let mid_level = harvestable_db.get_by_level_range(11, 50); let high_level = harvestable_db.get_by_level_range(51, 100); println!(" • Level 1-10: {}", low_level.len()); println!(" • Level 11-50: {}", mid_level.len()); println!(" • Level 51-100: {}", high_level.len()); println!(); // ======================================================================= // Loot Tables // ======================================================================= println!("=== Loot Tables ==="); let all_tables = loot_db.all_tables(); let conditional_tables = loot_db.get_conditional_tables(); let guaranteed_tables = loot_db.get_tables_with_guaranteed_drops(); println!("Statistics:"); println!(" • Total loot tables: {}", loot_db.len()); println!(" • NPCs with loot: {}", loot_db.get_all_npcs_with_loot().len()); println!(" • Droppable items: {}", loot_db.get_all_droppable_items().len()); println!(" • Tables with conditional drops: {}", conditional_tables.len()); println!(" • Tables with guaranteed drops: {}", guaranteed_tables.len()); // Sample loot table if let Some(table) = all_tables.first() { println!("\nSample loot table:"); if let Some(name) = &table.name { println!(" Name: {}", name); } println!(" NPCs: {:?}", table.npc_ids); println!(" Drops: {} items", table.drops.len()); // Show first few drops println!(" Sample drops:"); for drop in table.drops.iter().take(3) { if let Some(item) = item_db.get_by_id(drop.item) { let rate_str = drop.rate.map(|r| r.to_string()).unwrap_or_else(|| "N/A".to_string()); let amount_str = if let (Some(min), Some(max)) = (drop.minamount, drop.maxamount) { format!("{}x{}", min, max) } else { "1x1".to_string() }; println!(" - {} ({}, rate: {})", item.name, amount_str, rate_str); } } } // Cross-reference: Find what an NPC drops println!("\nSample NPC drops:"); if let Some(npc) = npc_db.get_hostile().first() { println!(" NPC: {} (ID: {})", npc.name, npc.id); let drops = loot_db.get_drops_for_npc(npc.id); if !drops.is_empty() { println!(" Drops {} different items:", drops.len()); for drop in drops.iter().take(5) { if let Some(item) = item_db.get_by_id(drop.item) { println!(" - {}", item.name); } } } else { println!(" No drops configured"); } } // Cross-reference: Find what NPCs drop an item if let Some(item) = item_db.get_by_id(180) { println!("\nItem '{}' drops from:", item.name); let npcs = loot_db.get_npcs_dropping_item(180); for npc_id in npcs.iter().take(5) { if let Some(npc) = npc_db.get_by_id(*npc_id) { println!(" • {}", npc.name); } } } println!(); // ======================================================================= // Cross-referencing data // ======================================================================= println!("=== Cross-referencing Data ==="); // Find NPCs that give quests let mut quest_givers = 0; for npc in npc_db.all_npcs() { if !npc.questmarkers.is_empty() { quest_givers += 1; } } println!("NPCs with quest markers: {}", quest_givers); // Find items that are quest rewards let mut quest_reward_items = std::collections::HashSet::new(); for quest in quest_db.all_quests() { for reward in &quest.rewards { if let Some(item_id) = reward.item { quest_reward_items.insert(item_id); } } } println!("Unique items used as quest rewards: {}", quest_reward_items.len()); // Find items that are harvestable drops let mut harvestable_items = std::collections::HashSet::new(); for harvestable in harvestable_db.all_harvestables() { for drop in &harvestable.drops { harvestable_items.insert(drop.id); } } println!("Unique items from harvestables: {}", harvestable_items.len()); println!("\n✨ Demo complete!"); Ok(()) }