304 lines
12 KiB
Rust
304 lines
12 KiB
Rust
//! 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<dyn std::error::Error>> {
|
|
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(())
|
|
}
|