99 lines
2.3 KiB
Rust
99 lines
2.3 KiB
Rust
|
use anyhow::Result;
|
||
|
use serde::Deserialize;
|
||
|
use std::collections::HashMap;
|
||
|
|
||
|
use crate::{handle::FactionHandle, Content};
|
||
|
|
||
|
pub(crate) mod syntax {
|
||
|
use std::collections::HashMap;
|
||
|
|
||
|
use serde::Deserialize;
|
||
|
// Raw serde syntax structs.
|
||
|
// These are never seen by code outside this crate.
|
||
|
|
||
|
#[derive(Debug, Deserialize)]
|
||
|
pub struct Faction {
|
||
|
pub display_name: String,
|
||
|
pub relationship: HashMap<String, super::Relationship>,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, Deserialize, Clone, Copy)]
|
||
|
pub enum Relationship {
|
||
|
#[serde(rename = "hostile")]
|
||
|
Hostile,
|
||
|
|
||
|
#[serde(rename = "neutral")]
|
||
|
Neutral,
|
||
|
|
||
|
#[serde(rename = "enemy")]
|
||
|
Enemy,
|
||
|
}
|
||
|
|
||
|
/// Represents a game faction
|
||
|
#[derive(Debug, Clone)]
|
||
|
pub struct Faction {
|
||
|
/// The name of this faction
|
||
|
pub name: String,
|
||
|
|
||
|
/// This faction's handle
|
||
|
pub handle: FactionHandle,
|
||
|
|
||
|
pub relationships: HashMap<FactionHandle, Relationship>,
|
||
|
}
|
||
|
|
||
|
impl crate::Build for Faction {
|
||
|
type InputSyntax = HashMap<String, syntax::Faction>;
|
||
|
|
||
|
fn build(factions: Self::InputSyntax, ct: &mut Content) -> Result<()> {
|
||
|
// Keeps track of position in faction array.
|
||
|
// This lets us build FactionHandles before finishing all factions.
|
||
|
let faction_names: Vec<String> = factions.keys().map(|x| x.to_owned()).collect();
|
||
|
|
||
|
for f_idx in 0..faction_names.len() {
|
||
|
let faction_name = &faction_names[f_idx];
|
||
|
let faction = &factions[faction_name];
|
||
|
|
||
|
// Handle for this faction
|
||
|
let h = FactionHandle { index: f_idx };
|
||
|
|
||
|
// Compute relationships
|
||
|
let mut relationships = HashMap::new();
|
||
|
for i in 0..faction_names.len() {
|
||
|
let f_other = &faction_names[i];
|
||
|
let h_other = FactionHandle { index: i };
|
||
|
if let Some(r) = faction.relationship.get(f_other) {
|
||
|
relationships.insert(h_other, *r);
|
||
|
} else {
|
||
|
// Default relationship, if not specified
|
||
|
|
||
|
// Look at reverse direction...
|
||
|
let other = factions[f_other].relationship.get(faction_name);
|
||
|
relationships.insert(
|
||
|
h_other,
|
||
|
// ... and pick a relationship based on that.
|
||
|
match other {
|
||
|
Some(Relationship::Hostile) => Relationship::Hostile {},
|
||
|
_ => Relationship::Neutral {},
|
||
|
},
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let relationships = faction
|
||
|
.relationship
|
||
|
.iter()
|
||
|
.map(|x| (h, x.1.clone()))
|
||
|
.collect();
|
||
|
|
||
|
ct.factions.push(Self {
|
||
|
name: faction_name.to_owned(),
|
||
|
handle: h,
|
||
|
relationships,
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return Ok(());
|
||
|
}
|
||
|
}
|