Galactica/crates/content/src/part/faction.rs

113 lines
2.9 KiB
Rust
Raw Normal View History

2023-12-30 16:57:03 -08:00
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,
2024-01-02 10:12:10 -08:00
pub color: [f32; 3],
2023-12-30 16:57:03 -08:00
pub relationship: HashMap<String, super::Relationship>,
}
}
2023-12-30 17:39:19 -08:00
/// How two factions should interact with each other.
/// Relationships are directional: the relationship of
/// `a` to `b` may not equal the relationship of `b` to `a`.
///
/// Relationships dictate how a ship of THIS faction
/// will interact with a ship of the OTHER faction.
2023-12-30 16:57:03 -08:00
#[derive(Debug, Deserialize, Clone, Copy)]
pub enum Relationship {
2023-12-30 17:39:19 -08:00
/// Attack this faction
2023-12-30 16:57:03 -08:00
#[serde(rename = "hostile")]
Hostile,
2023-12-30 17:39:19 -08:00
/// Ignore this faction
2023-12-30 16:57:03 -08:00
#[serde(rename = "neutral")]
Neutral,
2023-12-30 17:39:19 -08:00
/// Protect this faction
#[serde(rename = "friend")]
Friend,
2023-12-30 16:57:03 -08:00
}
/// Represents a game faction
#[derive(Debug, Clone)]
pub struct Faction {
/// The name of this faction
pub name: String,
2024-01-02 10:12:10 -08:00
/// This faction's color.
/// Format is RGB, with each color between 0 and 1.
pub color: [f32; 3],
2023-12-30 16:57:03 -08:00
/// This faction's handle
pub handle: FactionHandle,
2023-12-30 17:39:19 -08:00
/// Relationships between this faction and other factions
/// This is guaranteed to contain an entry for ALL factions.
2023-12-30 16:57:03 -08:00
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();
2023-12-30 17:39:19 -08:00
// Indexing will break if this is false.
assert!(ct.factions.len() == 0);
2023-12-30 16:57:03 -08:00
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 {},
},
);
}
}
ct.factions.push(Self {
name: faction_name.to_owned(),
handle: h,
relationships,
2024-01-02 10:12:10 -08:00
color: faction.color,
2023-12-30 16:57:03 -08:00
});
}
return Ok(());
}
}