aex/src/entities/mock.rs

164 lines
33 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use crate::prelude::*;
use super::*;
impl Dashboard {
pub fn mock () -> Self {
Dashboard {
campaign: "В Поисках Дмитрия Шардалина".to_owned(),
campaign_image: "https://assetsio.gnwcdn.com/dnd-5e-journeys-through-the-radiant-citadel-salted-legacy-artwork.jpg?width=690&quality=80&format=jpg&auto=webp".to_owned(),
session: 12,
date: NaiveDate::from_ymd_opt(1488, 3, 19).unwrap(),
player: PlayerData {
name: Name {
first: "Абоба".to_string(),
last: "Амогус".to_string(),
alias: "Такелажник".to_string(),
},
class: "Чувствительный молодой человек".to_string(),
image: "https://i.pinimg.com/736x/25/58/32/2558329d333fda61615da6ce50dcddda.jpg".to_owned(),
level: 8,
xp: 3231,
temp_hp: 12,
hp: 1,
max_hp: 61,
balance: Balance { platinum: 12, gold: 200, electrum: 1, silver: 101, copper: 129021021 },
spell_slots: SpellSlots(core::array::from_fn(|i| SpellSlotLevel { used: 1, total: 9 - i as u8 })),
attunements: Attunements([const { None }; 3]),
hit_dice: HitDice { used: 1, total: 7 },
death_save_throws: DeathSaveThrows { failed: 1, succeeded: 3 },
prepared: PreparedSpells(vec![Spell { name: "Fire Bolt".to_owned() }]),
inventory: generate_mock_inventory(),
},
common: CommonData {
balance: Balance { platinum: 1312, gold: 3211200, electrum: 231, silver: 1, copper: 21021 },
inventory: generate_mock_inventory(),
},
quest_book: generate_mock_questbook(),
notes: generate_mock_notebook(),
people: generate_mock_contact_book(),
}
}
}
fn generate_mock_inventory() -> Inventory {
let items = vec![
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Vorpal Sword".to_string(), weight: Some(4.0), description: Some("A blade that severs heads with a single swing.".to_string()), tags: HashMap::from([ ("type".to_string(), "weapon".to_string()), ("rarity".to_string(), "legendary".to_string()), ]), }), },
InventoryEntry { quantity: 3, item: InventoryItem::Custom(CustomInventoryItem { name: "Potion of Healing".to_string(), weight: Some(0.5), description: Some("A vial of red liquid that restores vitality.".to_string()), tags: HashMap::from([ ("type".to_string(), "potion".to_string()), ("rarity".to_string(), "common".to_string()), ]), }), },
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Cloak of Elvenkind".to_string(), weight: Some(1.0), description: Some("A cloak that blends into shadows.".to_string()), tags: HashMap::from([ ("type".to_string(), "wondrous".to_string()), ("rarity".to_string(), "uncommon".to_string()), ]), }), },
InventoryEntry { quantity: 2, item: InventoryItem::Custom(CustomInventoryItem { name: "Bag of Holding".to_string(), weight: Some(15.0), description: Some("A small bag with vast internal space.".to_string()), tags: HashMap::from([ ("type".to_string(), "wondrous".to_string()), ("rarity".to_string(), "uncommon".to_string()), ]), }), },
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Mithril Chainmail".to_string(), weight: Some(20.0), description: Some("Lightweight armor that gleams like silver.".to_string()), tags: HashMap::from([ ("type".to_string(), "armor".to_string()), ("rarity".to_string(), "rare".to_string()), ]), }), },
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Wand of Fireballs".to_string(), weight: Some(0.2), description: Some("A wand that unleashes fiery explosions.".to_string()), tags: HashMap::from([ ("type".to_string(), "wand".to_string()), ("rarity".to_string(), "rare".to_string()), ]), }), },
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Ring of Invisibility".to_string(), weight: Some(0.1), description: Some("Grants the wearer invisibility.".to_string()), tags: HashMap::from([ ("type".to_string(), "ring".to_string()), ("rarity".to_string(), "legendary".to_string()), ]), }), },
InventoryEntry { quantity: 2, item: InventoryItem::Custom(CustomInventoryItem { name: "Boots of Speed".to_string(), weight: Some(1.5), description: Some("Boots that enhance the wearer's speed.".to_string()), tags: HashMap::from([ ("type".to_string(), "wondrous".to_string()), ("rarity".to_string(), "rare".to_string()), ]), }), },
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Dagger of Venom".to_string(), weight: Some(1.0), description: Some("A dagger coated with deadly poison.".to_string()), tags: HashMap::from([ ("type".to_string(), "weapon".to_string()), ("rarity".to_string(), "rare".to_string()), ]), }), },
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Staff of Power".to_string(), weight: Some(5.0), description: Some("A staff pulsing with arcane might.".to_string()), tags: HashMap::from([ ("type".to_string(), "staff".to_string()), ("rarity".to_string(), "very rare".to_string()), ]), }), },
InventoryEntry { quantity: 4, item: InventoryItem::Custom(CustomInventoryItem { name: "Torch".to_string(), weight: Some(1.0), description: Some("A simple torch for illumination.".to_string()), tags: HashMap::from([ ("type".to_string(), "tool".to_string()), ("rarity".to_string(), "common".to_string()), ]), }), },
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Amulet of Health".to_string(), weight: Some(0.3), description: Some("Boosts the wearer's vitality.".to_string()), tags: HashMap::from([ ("type".to_string(), "wondrous".to_string()), ("rarity".to_string(), "rare".to_string()), ]), }), },
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Flame Tongue".to_string(), weight: Some(3.0), description: Some("A sword that ignites on command.".to_string()), tags: HashMap::from([ ("type".to_string(), "weapon".to_string()), ("rarity".to_string(), "rare".to_string()), ]), }), },
InventoryEntry { quantity: 5, item: InventoryItem::Custom(CustomInventoryItem { name: "Arrow of Slaying".to_string(), weight: Some(0.1), description: Some("An arrow designed to kill a specific foe.".to_string()), tags: HashMap::from([ ("type".to_string(), "ammunition".to_string()), ("rarity".to_string(), "very rare".to_string()), ]), }), },
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Cloak of Displacement".to_string(), weight: Some(1.0), description: Some("Makes the wearer hard to hit.".to_string()), tags: HashMap::from([ ("type".to_string(), "wondrous".to_string()), ("rarity".to_string(), "rare".to_string()), ]), }), },
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Helm of Teleportation".to_string(), weight: Some(3.0), description: Some("Allows teleportation to known locations.".to_string()), tags: HashMap::from([ ("type".to_string(), "wondrous".to_string()), ("rarity".to_string(), "rare".to_string()), ]), }), },
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Crystal Ball".to_string(), weight: Some(7.0), description: Some("A magical orb for scrying.".to_string()), tags: HashMap::from([ ("type".to_string(), "wondrous".to_string()), ("rarity".to_string(), "very rare".to_string()), ]), }), },
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Gauntlets of Ogre Power".to_string(), weight: Some(2.0), description: Some("Grants the strength of an ogre.".to_string()), tags: HashMap::from([ ("type".to_string(), "wondrous".to_string()), ("rarity".to_string(), "uncommon".to_string()), ]), }), },
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Robe of the Archmagi".to_string(), weight: Some(1.0), description: Some("Enhances a wizard's spellcasting.".to_string()), tags: HashMap::from([ ("type".to_string(), "wondrous".to_string()), ("rarity".to_string(), "legendary".to_string()), ]), }), },
InventoryEntry { quantity: 1, item: InventoryItem::Custom(CustomInventoryItem { name: "Horn of Blasting".to_string(), weight: Some(2.0), description: Some("Emits a destructive sonic blast.".to_string()), tags: HashMap::from([ ("type".to_string(), "wondrous".to_string()), ("rarity".to_string(), "rare".to_string()), ]), }), },
];
Inventory(items)
}
fn generate_mock_notebook () -> NoteBook {
NoteBook(vec![
Note { session: 1, content: "Met Elminster in Waterdeep; hinted at Netherese ruin.".to_string(), date_ingame: NaiveDate::from_ymd_opt(1481, 4, 15).unwrap(), date_real: NaiveDateTime::parse_from_str("2025-09-01 14:30:00", "%Y-%m-%d %H:%M:%S").unwrap(), tags: HashSet::from_iter(vec!["Elminster".to_string(), "Waterdeep".to_string()]) },
Note { session: 2, content: "Zhentarim agents watching Baldur's Gate tavern.".to_string(), date_ingame: NaiveDate::from_ymd_opt(1481, 4, 16).unwrap(), date_real: NaiveDateTime::parse_from_str("2025-09-02 09:15:00", "%Y-%m-%d %H:%M:%S").unwrap(), tags: HashSet::from_iter(vec!["Zhentarim".to_string()]) },
Note { session: 3, content: "Phandalin: Redbrands extorting locals, hideout in manor.".to_string(), date_ingame: NaiveDate::from_ymd_opt(1481, 4, 20).unwrap(), date_real: NaiveDateTime::parse_from_str("2025-09-03 18:45:00", "%Y-%m-%d %H:%M:%S").unwrap(), tags: HashSet::from_iter(vec!["Phandalin".to_string(), "Redbrands".to_string()]) },
Note { session: 4, content: "Neverember offers 100gp for bandit leader's head.".to_string(), date_ingame: NaiveDate::from_ymd_opt(1481, 4, 22).unwrap(), date_real: NaiveDateTime::parse_from_str("2025-09-04 11:20:00", "%Y-%m-%d %H:%M:%S").unwrap(), tags: HashSet::from_iter(vec!["Neverwinter".to_string()]) },
Note { session: 5, content: "Strange rune in Underdark; ask Candlekeep scholars.".to_string(), date_ingame: NaiveDate::from_ymd_opt(1481, 5, 1).unwrap(), date_real: NaiveDateTime::parse_from_str("2025-09-05 20:10:00", "%Y-%m-%d %H:%M:%S").unwrap(), tags: HashSet::from_iter(vec!["Underdark".to_string(), "Candlekeep".to_string()]) },
Note { session: 6, content: "Luskan pirates smuggling at docks; check crates.".to_string(), date_ingame: NaiveDate::from_ymd_opt(1481, 5, 3).unwrap(), date_real: NaiveDateTime::parse_from_str("2025-09-06 15:30:00", "%Y-%m-%d %H:%M:%S").unwrap(), tags: HashSet::from_iter(vec!["Luskan".to_string()]) },
Note { session: 7, content: "Silverymoon wards flicker at midnight; sabotage?".to_string(), date_ingame: NaiveDate::from_ymd_opt(1481, 5, 5).unwrap(), date_real: NaiveDateTime::parse_from_str("2025-09-07 22:00:00", "%Y-%m-%d %H:%M:%S").unwrap(), tags: HashSet::from_iter(vec!["Silverymoon".to_string(), "Arcane".to_string()]) },
Note { session: 8, content: "Daggerford militia needs help with Cragmaw goblins.".to_string(), date_ingame: NaiveDate::from_ymd_opt(1481, 5, 7).unwrap(), date_real: NaiveDateTime::parse_from_str("2025-09-08 12:45:00", "%Y-%m-%d %H:%M:%S").unwrap(), tags: HashSet::from_iter(vec!["Daggerford".to_string()]) },
Note { session: 9, content: "Suzail's Lathander temple requests festival guards.".to_string(), date_ingame: NaiveDate::from_ymd_opt(1481, 5, 10).unwrap(), date_real: NaiveDateTime::parse_from_str("2025-09-09 10:00:00", "%Y-%m-%d %H:%M:%S").unwrap(), tags: HashSet::from_iter(vec!["Suzail".to_string(), "Lathander".to_string()]) },
Note { session: 10, content: "Rumors of dragon in Evermoors; need fire resistance.".to_string(), date_ingame: NaiveDate::from_ymd_opt(1481, 5, 12).unwrap(), date_real: NaiveDateTime::parse_from_str("2025-09-10 17:25:00", "%Y-%m-%d %H:%M:%S").unwrap(), tags: HashSet::from_iter(vec!["Evermoors".to_string()]) },
Note { session: 11, content: "Harpers want Zhentarim plans from Zhentil Keep.".to_string(), date_ingame: NaiveDate::from_ymd_opt(1481, 5, 15).unwrap(), date_real: NaiveDateTime::parse_from_str("2025-09-11 08:50:00", "%Y-%m-%d %H:%M:%S").unwrap(), tags: HashSet::from_iter(vec!["Harpers".to_string(), "Zhentarim".to_string()]) },
Note { session: 12, content: "Shady Cormyr merchant; possible doppelganger.".to_string(), date_ingame: NaiveDate::from_ymd_opt(1481, 5, 17).unwrap(), date_real: NaiveDateTime::parse_from_str("2025-09-11 14:00:00", "%Y-%m-%d %H:%M:%S").unwrap(), tags: HashSet::new() },
])
}
fn generate_mock_questbook () -> QuestBook {
QuestBook(vec![
Quest { title: "Slay the Bandit Chief".to_string(), location_taken: Some("Waterdeep".to_string()), location_task: Some("Phandalin".to_string()), date_taken: Some(NaiveDate::from_ymd_opt(1481, 4, 15).unwrap()), date_by: Some(NaiveDate::from_ymd_opt(1481, 5, 15).unwrap()), description: Some("Kill the bandit leader.".to_string()), from: Some(Name { first: "Dagult".to_string(), last: "Neverember".to_string(), alias: "".to_string(), ..Default::default() }), reward: Some(Balance { platinum: 0, gold: 100, electrum: 0, silver: 0, copper: 0 }) },
Quest { title: "Find the Lost Artifact".to_string(), location_taken: Some("Baldur's Gate".to_string()), location_task: None, date_taken: Some(NaiveDate::from_ymd_opt(1481, 6, 1).unwrap()), date_by: None, description: Some("Seek a relic in ruins.".to_string()), from: Some(Name { first: "Elminster".to_string(), last: "".to_string(), alias: "The Sage of Shadowdale".to_string() }), reward: Some(Balance { platinum: 10, gold: 50, electrum: 0, silver: 0, copper: 0 }) },
Quest { title: "Escort the Caravan".to_string(), location_taken: Some("Neverwinter".to_string()), location_task: Some("Luskan".to_string()), date_taken: None, date_by: Some(NaiveDate::from_ymd_opt(1481, 7, 30).unwrap()), description: Some("Protect traders.".to_string()), from: None, reward: Some(Balance { platinum: 0, gold: 20, electrum: 0, silver: 50, copper: 0 }) },
Quest { title: "Clear the Goblin Den".to_string(), location_taken: Some("Daggerford".to_string()), location_task: Some("Cragmaw Hideout".to_string()), date_taken: Some(NaiveDate::from_ymd_opt(1481, 3, 10).unwrap()), date_by: Some(NaiveDate::from_ymd_opt(1481, 4, 10).unwrap()), description: None, from: Some(Name { first: "".to_string(), last: "".to_string(), alias: "Local Militia".to_string(), ..Default::default() }), reward: Some(Balance { platinum: 0, gold: 30, electrum: 0, silver: 0, copper: 100 }) },
Quest { title: "Rescue the Noble".to_string(), location_taken: None, location_task: Some("Underdark".to_string()), date_taken: Some(NaiveDate::from_ymd_opt(1481, 5, 20).unwrap()), date_by: None, description: Some("Save a kidnapped noble.".to_string()), from: Some(Name { first: "".to_string(), last: "Silverhand".to_string(), alias: "".to_string(), ..Default::default() }), reward: Some(Balance { platinum: 5, gold: 200, electrum: 0, silver: 0, copper: 0 }) },
Quest { title: "Steal the Zhentarim Plans".to_string(), location_taken: Some("Zhentil Keep".to_string()), location_task: Some("Zhentil Keep".to_string()), date_taken: None, date_by: Some(NaiveDate::from_ymd_opt(1481, 8, 15).unwrap()), description: None, from: Some(Name { first: "".to_string(), last: "".to_string(), alias: "Harpers".to_string(), ..Default::default() }), reward: Some(Balance { platinum: 0, gold: 75, electrum: 0, silver: 0, copper: 0 }) },
Quest { title: "Hunt the Dire Wolf".to_string(), location_taken: Some("Silverymoon".to_string()), location_task: Some("Evermoors".to_string()), date_taken: Some(NaiveDate::from_ymd_opt(1481, 2, 5).unwrap()), date_by: None, description: Some("Track and kill a beast.".to_string()), from: None, reward: Some(Balance { platinum: 0, gold: 15, electrum: 0, silver: 20, copper: 50 }) },
Quest { title: "Recover the Spellbook".to_string(), location_taken: Some("Candlekeep".to_string()), location_task: None, date_taken: Some(NaiveDate::from_ymd_opt(1481, 1, 10).unwrap()), date_by: Some(NaiveDate::from_ymd_opt(1481, 2, 10).unwrap()), description: Some("Find a stolen tome.".to_string()), from: Some(Name { first: "".to_string(), last: "".to_string(), alias: "Candlekeep Scholars".to_string(), ..Default::default() }), reward: None },
Quest { title: "Guard the Temple".to_string(), location_taken: Some("Suzail".to_string()), location_task: Some("Temple of Lathander".to_string()), date_taken: None, date_by: None, description: Some("Protect the shrine.".to_string()), from: Some(Name { first: "".to_string(), last: "".to_string(), alias: "Clerics of Lathander".to_string(), ..Default::default() }), reward: Some(Balance { platinum: 0, gold: 50, electrum: 0, silver: 0, copper: 0 }) },
Quest { title: "Explore the Ruins".to_string(), location_taken: Some("Cormyr".to_string()), location_task: Some("Netherese Ruins".to_string()), date_taken: Some(NaiveDate::from_ymd_opt(1481, 9, 1).unwrap()), date_by: Some(NaiveDate::from_ymd_opt(1481, 10, 1).unwrap()), description: None, from: None, reward: None },
])
}
fn generate_mock_contact_book () -> ContactBook {
let mut contacts = HashMap::new();
// 40 Characters Met by Party (80%)
contacts.insert("Elminster".to_string(), Contact { name: Name { first: "Elminster".to_string(), last: "".to_string(), alias: "The Sage of Shadowdale".to_string() }, image: None, status: Some(ContactStatus::Alive), location: Some("Shadowdale".to_string()), notes: Some("Wise but cryptic wizard.".to_string()) });
contacts.insert("Drizzt Do'Urden".to_string(), Contact { name: Name { first: "Drizzt".to_string(), last: "Do'Urden".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Icewind Dale".to_string()), notes: Some("Renegade drow ranger.".to_string()) });
contacts.insert("Lord Neverember".to_string(), Contact { name: Name { first: "Dagult".to_string(), last: "Neverember".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Neverwinter".to_string()), notes: Some("Ruler seeking bandit leader.".to_string()) });
contacts.insert("Minsc".to_string(), Contact { name: Name { first: "Minsc".to_string(), last: "".to_string(), alias: "Rascal of Rashemen".to_string() }, image: None, status: Some(ContactStatus::Alive), location: Some("Baldur's Gate".to_string()), notes: Some("Loud warrior with hamster.".to_string()) });
contacts.insert("Jarlaxle".to_string(), Contact { name: Name { first: "Jarlaxle".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Luskan".to_string()), notes: Some("Sly drow mercenary leader.".to_string()) });
contacts.insert("Volo".to_string(), Contact { name: Name { first: "Volothamp".to_string(), last: "Geddarm".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Waterdeep".to_string()), notes: Some("Exaggerates his travel tales.".to_string()) });
contacts.insert("Laeral Silverhand".to_string(), Contact { name: Name { first: "Laeral".to_string(), last: "Silverhand".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Waterdeep".to_string()), notes: Some("Open Lord, powerful mage.".to_string()) });
contacts.insert("Hammond Ardeep".to_string(), Contact { name: Name { first: "Hammond".to_string(), last: "Ardeep".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Daggerford".to_string()), notes: Some("Militia leader vs. goblins.".to_string()) });
contacts.insert("Sister Garaele".to_string(), Contact { name: Name { first: "Garaele".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Phandalin".to_string()), notes: Some("Harper agent in temple.".to_string()) });
contacts.insert("Gundren Rockseeker".to_string(), Contact { name: Name { first: "Gundren".to_string(), last: "Rockseeker".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Phandalin".to_string()), notes: Some("Dwarf seeking lost mine.".to_string()) });
contacts.insert("Sildar Hallwinter".to_string(), Contact { name: Name { first: "Sildar".to_string(), last: "Hallwinter".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Phandalin".to_string()), notes: Some("Lord's Alliance knight.".to_string()) });
contacts.insert("Qelline Alderleaf".to_string(), Contact { name: Name { first: "Qelline".to_string(), last: "Alderleaf".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Phandalin".to_string()), notes: Some("Halfling farmer, kind.".to_string()) });
contacts.insert("Toblen Stonehill".to_string(), Contact { name: Name { first: "Toblen".to_string(), last: "Stonehill".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Phandalin".to_string()), notes: Some("Innkeeper, knows rumors.".to_string()) });
contacts.insert("Darathra Shendrel".to_string(), Contact { name: Name { first: "Darathra".to_string(), last: "Shendrel".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Triboar".to_string()), notes: Some("Lord Protector, fair.".to_string()) });
contacts.insert("Ziraj the Hunter".to_string(), Contact { name: Name { first: "Ziraj".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Neverwinter Wood".to_string()), notes: Some("Tracks orcs.".to_string()) });
contacts.insert("Eldrin Thalindra".to_string(), Contact { name: Name { first: "Eldrin".to_string(), last: "Thalindra".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Silverymoon".to_string()), notes: Some("Arcane ward keeper.".to_string()) });
contacts.insert("Randal Morn".to_string(), Contact { name: Name { first: "Randal".to_string(), last: "Morn".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Daggerdale".to_string()), notes: Some("Fights Zhentarim.".to_string()) });
contacts.insert("Khelben Blackstaff".to_string(), Contact { name: Name { first: "Khelben".to_string(), last: "Arunsun".to_string(), alias: "The Blackstaff".to_string() }, image: None, status: Some(ContactStatus::Dead), location: Some("Waterdeep".to_string()), notes: Some("Former archmage, deceased.".to_string()) });
contacts.insert("Mirt the Moneylender".to_string(), Contact { name: Name { first: "Mirt".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Waterdeep".to_string()), notes: Some("Harper ally, wealthy.".to_string()) });
contacts.insert("Durnan".to_string(), Contact { name: Name { first: "Durnan".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Waterdeep".to_string()), notes: Some("Yawning Portal owner.".to_string()) });
contacts.insert("Fzoul Chembryl".to_string(), Contact { name: Name { first: "Fzoul".to_string(), last: "Chembryl".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Dead), location: Some("Zhentil Keep".to_string()), notes: Some("Former Zhentarim leader.".to_string()) });
contacts.insert("Bruenor Battlehammer".to_string(), Contact { name: Name { first: "Bruenor".to_string(), last: "Battlehammer".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Mithral Hall".to_string()), notes: Some("Dwarf king, ally.".to_string()) });
contacts.insert("Catti-brie".to_string(), Contact { name: Name { first: "Catti-brie".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Mithral Hall".to_string()), notes: Some("Skilled archer.".to_string()) });
contacts.insert("Regis".to_string(), Contact { name: Name { first: "Regis".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Icewind Dale".to_string()), notes: Some("Halfling, sneaky.".to_string()) });
contacts.insert("Artemis Entreri".to_string(), Contact { name: Name { first: "Artemis".to_string(), last: "Entreri".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Calimport".to_string()), notes: Some("Dangerous assassin.".to_string()) });
contacts.insert("Storm Silverhand".to_string(), Contact { name: Name { first: "Storm".to_string(), last: "Silverhand".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Shadowdale".to_string()), notes: Some("Bard and Chosen.".to_string()) });
contacts.insert("Halia Thornton".to_string(), Contact { name: Name { first: "Halia".to_string(), last: "Thornton".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Phandalin".to_string()), notes: Some("Zhentarim agent, subtle.".to_string()) });
contacts.insert("Darlia Greystone".to_string(), Contact { name: Name { first: "Darlia".to_string(), last: "Greystone".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Triboar".to_string()), notes: Some("Blacksmith, reliable.".to_string()) });
contacts.insert("Eldric Varn".to_string(), Contact { name: Name { first: "Eldric".to_string(), last: "Varn".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Luskan".to_string()), notes: Some("Ship captain, shady.".to_string()) });
contacts.insert("Tymoras Priest".to_string(), Contact { name: Name { first: "".to_string(), last: "".to_string(), alias: "Tymoras Priest".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Suzail".to_string()), notes: Some("Blesses adventurers.".to_string()) });
contacts.insert("Redbrand Leader".to_string(), Contact { name: Name { first: "".to_string(), last: "".to_string(), alias: "Glasstaff".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Phandalin".to_string()), notes: Some("Runs thug gang.".to_string()) });
contacts.insert("Brynna of Lathander".to_string(), Contact { name: Name { first: "Brynna".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Suzail".to_string()), notes: Some("Temple cleric.".to_string()) });
contacts.insert("Korgul the Tumbler".to_string(), Contact { name: Name { first: "Korgul".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Baldur's Gate".to_string()), notes: Some("Thieves guild contact.".to_string()) });
contacts.insert("Tharivol the Mage".to_string(), Contact { name: Name { first: "Tharivol".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Silverymoon".to_string()), notes: Some("Studies arcane wards.".to_string()) });
contacts.insert("Gorlag the Orc".to_string(), Contact { name: Name { first: "Gorlag".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Dead), location: Some("Neverwinter Wood".to_string()), notes: Some("Slain orc chieftain.".to_string()) });
contacts.insert("Lhara the Merchant".to_string(), Contact { name: Name { first: "Lhara".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Cormyr".to_string()), notes: Some("Sells rare goods.".to_string()) });
contacts.insert("Ebon the Rogue".to_string(), Contact { name: Name { first: "Ebon".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Zhentil Keep".to_string()), notes: Some("Sneaky informant.".to_string()) });
contacts.insert("Father Llymic".to_string(), Contact { name: Name { first: "Llymic".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Dead), location: Some("Icewind Dale".to_string()), notes: Some("Evil priest, defeated.".to_string()) });
contacts.insert("Sylvara the Druid".to_string(), Contact { name: Name { first: "Sylvara".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("High Forest".to_string()), notes: Some("Protects the woods.".to_string()) });
contacts.insert("Raul the Barkeep".to_string(), Contact { name: Name { first: "Raul".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Daggerford".to_string()), notes: Some("Hears local gossip.".to_string()) });
// 5 Contacts (10%)
contacts.insert("Valthor the Fence".to_string(), Contact { name: Name { first: "Valthor".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Baldur's Gate".to_string()), notes: Some("Buys stolen goods.".to_string()) });
contacts.insert("Zyra the Alchemist".to_string(), Contact { name: Name { first: "Zyra".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Waterdeep".to_string()), notes: Some("Sells potions.".to_string()) });
contacts.insert("Kren the Smuggler".to_string(), Contact { name: Name { first: "Kren".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Luskan".to_string()), notes: Some("Moves contraband.".to_string()) });
contacts.insert("Mira the Scribe".to_string(), Contact { name: Name { first: "Mira".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Candlekeep".to_string()), notes: Some("Deciphers texts.".to_string()) });
contacts.insert("Thok the Armorer".to_string(), Contact { name: Name { first: "Thok".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Neverwinter".to_string()), notes: Some("Crafts fine armor.".to_string()) });
// 3 Present-Day Legends (6%)
contacts.insert("Tiamat".to_string(), Contact { name: Name { first: "".to_string(), last: "".to_string(), alias: "The Dragon Queen".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: None, notes: Some("Evil dragon goddess.".to_string()) });
contacts.insert("Vecna".to_string(), Contact { name: Name { first: "".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: None, notes: Some("Lich god of secrets.".to_string()) });
contacts.insert("Claugiyliamatar".to_string(), Contact { name: Name { first: "".to_string(), last: "".to_string(), alias: "Old Gnawbone".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::Alive), location: Some("Kryptgarden Forest".to_string()), notes: Some("Ancient green dragon.".to_string()) });
// 2 Past Legends (4%, DeadBygone)
contacts.insert("Manshoon".to_string(), Contact { name: Name { first: "Manshoon".to_string(), last: "".to_string(), alias: "".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::DeadBygone), location: Some("Zhentil Keep".to_string()), notes: Some("Zhentarim founder, long dead.".to_string()) });
contacts.insert("Netherese Archwizard".to_string(), Contact { name: Name { first: "".to_string(), last: "".to_string(), alias: "Netherese Archwizard".to_string(), ..Default::default() }, image: None, status: Some(ContactStatus::DeadBygone), location: None, notes: Some("Ancient mage of lost empire.".to_string()) });
ContactBook(contacts)
}