mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Implement migration for EntityConfig
This commit is contained in:
parent
15431e7f7a
commit
a4908cf5ae
@ -5,7 +5,14 @@ use std::{
|
||||
io::Write,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use veloren_common::comp::inventory::slot::{ArmorSlot, EquipSlot};
|
||||
use veloren_common::{
|
||||
comp::{
|
||||
agent::Alignment,
|
||||
inventory::slot::{ArmorSlot, EquipSlot},
|
||||
Body,
|
||||
},
|
||||
lottery::LootSpec,
|
||||
};
|
||||
|
||||
/// Old version.
|
||||
mod loadout_v1 {
|
||||
@ -40,7 +47,7 @@ mod loadout_v2 {
|
||||
type Weight = u8;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
enum Base {
|
||||
pub enum Base {
|
||||
Asset(String),
|
||||
/// NOTE: If you have the same item in multiple configs,
|
||||
/// first one will have the priority
|
||||
@ -68,49 +75,49 @@ mod loadout_v2 {
|
||||
pub struct LoadoutSpecNew {
|
||||
// Meta fields
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
inherit: Option<Base>,
|
||||
pub inherit: Option<Base>,
|
||||
// Armor
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
head: Option<ItemSpecNew>,
|
||||
pub head: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
neck: Option<ItemSpecNew>,
|
||||
pub neck: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
shoulders: Option<ItemSpecNew>,
|
||||
pub shoulders: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
chest: Option<ItemSpecNew>,
|
||||
pub chest: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
gloves: Option<ItemSpecNew>,
|
||||
pub gloves: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
ring1: Option<ItemSpecNew>,
|
||||
pub ring1: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
ring2: Option<ItemSpecNew>,
|
||||
pub ring2: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
back: Option<ItemSpecNew>,
|
||||
pub back: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
belt: Option<ItemSpecNew>,
|
||||
pub belt: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
legs: Option<ItemSpecNew>,
|
||||
pub legs: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
feet: Option<ItemSpecNew>,
|
||||
pub feet: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
tabard: Option<ItemSpecNew>,
|
||||
pub tabard: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
bag1: Option<ItemSpecNew>,
|
||||
pub bag1: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
bag2: Option<ItemSpecNew>,
|
||||
pub bag2: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
bag3: Option<ItemSpecNew>,
|
||||
pub bag3: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
bag4: Option<ItemSpecNew>,
|
||||
pub bag4: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
lantern: Option<ItemSpecNew>,
|
||||
pub lantern: Option<ItemSpecNew>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
glider: Option<ItemSpecNew>,
|
||||
pub glider: Option<ItemSpecNew>,
|
||||
// Weapons
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
active_hands: Option<Hands>,
|
||||
pub active_hands: Option<Hands>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
inactive_hands: Option<Hands>,
|
||||
pub inactive_hands: Option<Hands>,
|
||||
}
|
||||
|
||||
impl From<(Option<ItemSpec>, Option<ItemSpec>)> for Hands {
|
||||
@ -188,25 +195,214 @@ mod loadout_v2 {
|
||||
}
|
||||
}
|
||||
|
||||
mod v1 {
|
||||
mod entity_v1 {
|
||||
use super::*;
|
||||
pub type Config = EntityConfig;
|
||||
type Weight = u8;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
|
||||
pub enum NameKind {
|
||||
Name(String),
|
||||
Automatic,
|
||||
Uninit,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
|
||||
pub enum BodyBuilder {
|
||||
RandomWith(String),
|
||||
Exact(Body),
|
||||
Uninit,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub enum AlignmentMark {
|
||||
Alignment(Alignment),
|
||||
Uninit,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub enum Meta {
|
||||
SkillSetAsset(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub enum Hands {
|
||||
TwoHanded(super::loadout_v1::ItemSpec),
|
||||
Paired(super::loadout_v1::ItemSpec),
|
||||
Mix {
|
||||
mainhand: super::loadout_v1::ItemSpec,
|
||||
offhand: super::loadout_v1::ItemSpec,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub enum LoadoutAsset {
|
||||
Loadout(String),
|
||||
Choice(Vec<(Weight, String)>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub enum LoadoutKind {
|
||||
FromBody,
|
||||
Asset(LoadoutAsset),
|
||||
Hands(Hands),
|
||||
Extended {
|
||||
hands: Hands,
|
||||
base_asset: LoadoutAsset,
|
||||
inventory: Vec<(u32, String)>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct EntityConfig;
|
||||
pub struct EntityConfig {
|
||||
pub name: NameKind,
|
||||
pub body: BodyBuilder,
|
||||
pub alignment: AlignmentMark,
|
||||
pub loot: LootSpec<String>,
|
||||
pub loadout: LoadoutKind,
|
||||
#[serde(default)]
|
||||
pub meta: Vec<Meta>,
|
||||
}
|
||||
}
|
||||
|
||||
mod v2 {
|
||||
use super::*;
|
||||
pub type OldConfig = super::v1::Config;
|
||||
mod entity_v2 {
|
||||
use super::{
|
||||
entity_v1::{Hands as OldHands, LoadoutAsset, LoadoutKind},
|
||||
loadout_v1::ItemSpec,
|
||||
loadout_v2::{Base, Hands, ItemSpecNew, LoadoutSpecNew},
|
||||
*,
|
||||
};
|
||||
pub type OldConfig = super::entity_v1::Config;
|
||||
pub type Config = EntityConfig;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
|
||||
pub struct EntityConfig;
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub enum LoadoutKindNew {
|
||||
FromBody,
|
||||
Asset(String),
|
||||
Inline(super::loadout_v2::LoadoutSpecNew),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct InventorySpec {
|
||||
loadout: LoadoutKindNew,
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
items: Vec<(u32, String)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct EntityConfig {
|
||||
pub name: super::entity_v1::NameKind,
|
||||
pub body: super::entity_v1::BodyBuilder,
|
||||
pub alignment: super::entity_v1::AlignmentMark,
|
||||
pub loot: LootSpec<String>,
|
||||
pub inventory: InventorySpec,
|
||||
#[serde(default)]
|
||||
pub meta: Vec<super::entity_v1::Meta>,
|
||||
}
|
||||
|
||||
impl From<LoadoutAsset> for LoadoutKindNew {
|
||||
fn from(old: LoadoutAsset) -> Self {
|
||||
match old {
|
||||
LoadoutAsset::Loadout(s) => LoadoutKindNew::Asset(s),
|
||||
LoadoutAsset::Choice(bases) => LoadoutKindNew::Inline(LoadoutSpecNew {
|
||||
inherit: Some(Base::Choice(
|
||||
bases
|
||||
.iter()
|
||||
.map(|(w, s)| (*w, Base::Asset(s.to_owned())))
|
||||
.collect(),
|
||||
)),
|
||||
..Default::default()
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OldHands> for Hands {
|
||||
fn from(old: OldHands) -> Self {
|
||||
match old {
|
||||
OldHands::TwoHanded(spec) => Hands::InHands((Some(spec.into()), None)),
|
||||
OldHands::Mix { mainhand, offhand } => {
|
||||
Hands::InHands((Some(mainhand.into()), Some(offhand.into())))
|
||||
},
|
||||
OldHands::Paired(spec) => match spec {
|
||||
ItemSpec::Item(name) => Hands::InHands((
|
||||
Some(ItemSpecNew::Item(name.clone())),
|
||||
Some(ItemSpecNew::Item(name)),
|
||||
)),
|
||||
ItemSpec::Choice(choices) => {
|
||||
let smallest = choices
|
||||
.iter()
|
||||
.map(|(w, _)| *w)
|
||||
.min_by(|x, y| x.partial_cmp(y).expect("floats are evil"))
|
||||
.expect("choice shouldn't empty");
|
||||
// Very imprecise algo, but it works
|
||||
let new_choices = choices
|
||||
.into_iter()
|
||||
.map(|(w, i)| {
|
||||
let new_weight = (w / smallest) as u8;
|
||||
let choice =
|
||||
Hands::InHands((i.clone().map(Into::into), i.map(Into::into)));
|
||||
|
||||
(new_weight, choice)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Hands::Choice(new_choices)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InventorySpec {
|
||||
fn with_hands(
|
||||
hands: OldHands,
|
||||
loadout: Option<LoadoutAsset>,
|
||||
items: Vec<(u32, String)>,
|
||||
) -> Self {
|
||||
Self {
|
||||
loadout: LoadoutKindNew::Inline(LoadoutSpecNew {
|
||||
inherit: loadout.map(|asset| match asset {
|
||||
LoadoutAsset::Loadout(s) => Base::Asset(s.to_owned()),
|
||||
LoadoutAsset::Choice(bases) => Base::Choice(
|
||||
bases
|
||||
.iter()
|
||||
.map(|(w, s)| (*w, Base::Asset(s.to_owned())))
|
||||
.collect(),
|
||||
),
|
||||
}),
|
||||
active_hands: Some(hands.into()),
|
||||
..Default::default()
|
||||
}),
|
||||
items,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OldConfig> for Config {
|
||||
fn from(old: OldConfig) -> Self {
|
||||
Self::default()
|
||||
let just_loadout = |loadout| InventorySpec {
|
||||
loadout,
|
||||
items: Vec::new(),
|
||||
};
|
||||
|
||||
Self {
|
||||
name: old.name,
|
||||
body: old.body,
|
||||
alignment: old.alignment,
|
||||
loot: old.loot,
|
||||
inventory: match old.loadout {
|
||||
LoadoutKind::FromBody => just_loadout(LoadoutKindNew::FromBody),
|
||||
LoadoutKind::Asset(asset) => just_loadout(asset.into()),
|
||||
LoadoutKind::Hands(hands) => InventorySpec::with_hands(hands, None, Vec::new()),
|
||||
LoadoutKind::Extended {
|
||||
hands,
|
||||
base_asset,
|
||||
inventory,
|
||||
} => InventorySpec::with_hands(hands, Some(base_asset), inventory),
|
||||
},
|
||||
meta: old.meta,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -279,10 +475,17 @@ where
|
||||
.extensions(ron::extensions::Extensions::IMPLICIT_SOME);
|
||||
let config_string =
|
||||
ron::ser::to_string_pretty(&new, pretty_config).expect("serialize shouldn't fail");
|
||||
let comments_string = comments.join("\n");
|
||||
let comments_string = if comments.is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
let mut comments = comments.join("\n");
|
||||
// insert newline for other config content
|
||||
comments.push_str("\n");
|
||||
comments
|
||||
};
|
||||
|
||||
let mut target = fs::File::create(to.join(&path))?;
|
||||
write!(&mut target, "{comments_string}\n{config_string}")
|
||||
write!(&mut target, "{comments_string}{config_string}")
|
||||
.expect("fail to write to the file");
|
||||
println!("{path:?} done");
|
||||
},
|
||||
@ -296,7 +499,12 @@ fn convert_loop(from: &str, to: &str) {
|
||||
path: Path::new("").to_owned(),
|
||||
content: walk_tree(root, root).unwrap(),
|
||||
};
|
||||
walk_with_migrate::<v1::Config, v2::Config>(files, Path::new(from), Path::new(to)).unwrap();
|
||||
walk_with_migrate::<entity_v1::Config, entity_v2::Config>(
|
||||
files,
|
||||
Path::new(from),
|
||||
Path::new(to),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn input_string(prompt: &str) -> String { input_validated_string(prompt, &|_| true) }
|
||||
|
@ -82,7 +82,7 @@ impl Base {
|
||||
enum Hands {
|
||||
/// Allows to specify one pair
|
||||
// TODO: add link to tests with example
|
||||
InHands((Option<ItemSpecNew>, Option<ItemSpecNew>)),
|
||||
InHands((Option<ItemSpec>, Option<ItemSpec>)),
|
||||
/// Allows specify range of choices
|
||||
// TODO: add link to tests with example
|
||||
Choice(Vec<(Weight, Hands)>),
|
||||
@ -95,7 +95,7 @@ impl Hands {
|
||||
) -> Result<(Option<Item>, Option<Item>), LoadoutBuilderError> {
|
||||
match self {
|
||||
Hands::InHands((mainhand, offhand)) => {
|
||||
let mut from_spec = |i: &ItemSpecNew| i.try_to_item(rng);
|
||||
let mut from_spec = |i: &ItemSpec| i.try_to_item(rng);
|
||||
|
||||
let mainhand = mainhand
|
||||
.as_ref()
|
||||
@ -121,20 +121,20 @@ impl Hands {
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
enum ItemSpecNew {
|
||||
enum ItemSpec {
|
||||
Item(String),
|
||||
Choice(Vec<(Weight, Option<ItemSpecNew>)>),
|
||||
Choice(Vec<(Weight, Option<ItemSpec>)>),
|
||||
}
|
||||
|
||||
impl ItemSpecNew {
|
||||
impl ItemSpec {
|
||||
fn try_to_item(&self, rng: &mut impl Rng) -> Result<Option<Item>, LoadoutBuilderError> {
|
||||
match self {
|
||||
ItemSpecNew::Item(item_asset) => {
|
||||
ItemSpec::Item(item_asset) => {
|
||||
let item = Item::new_from_asset(item_asset)
|
||||
.map_err(LoadoutBuilderError::ItemAssetError)?;
|
||||
Ok(Some(item))
|
||||
},
|
||||
ItemSpecNew::Choice(items) => {
|
||||
ItemSpec::Choice(items) => {
|
||||
let (_, item_spec) = items
|
||||
.choose_weighted(rng, |(weight, _)| *weight)
|
||||
.map_err(LoadoutBuilderError::ItemChoiceError)?;
|
||||
@ -156,24 +156,24 @@ pub struct LoadoutSpec {
|
||||
// Meta fields
|
||||
inherit: Option<Base>,
|
||||
// Armor
|
||||
head: Option<ItemSpecNew>,
|
||||
neck: Option<ItemSpecNew>,
|
||||
shoulders: Option<ItemSpecNew>,
|
||||
chest: Option<ItemSpecNew>,
|
||||
gloves: Option<ItemSpecNew>,
|
||||
ring1: Option<ItemSpecNew>,
|
||||
ring2: Option<ItemSpecNew>,
|
||||
back: Option<ItemSpecNew>,
|
||||
belt: Option<ItemSpecNew>,
|
||||
legs: Option<ItemSpecNew>,
|
||||
feet: Option<ItemSpecNew>,
|
||||
tabard: Option<ItemSpecNew>,
|
||||
bag1: Option<ItemSpecNew>,
|
||||
bag2: Option<ItemSpecNew>,
|
||||
bag3: Option<ItemSpecNew>,
|
||||
bag4: Option<ItemSpecNew>,
|
||||
lantern: Option<ItemSpecNew>,
|
||||
glider: Option<ItemSpecNew>,
|
||||
head: Option<ItemSpec>,
|
||||
neck: Option<ItemSpec>,
|
||||
shoulders: Option<ItemSpec>,
|
||||
chest: Option<ItemSpec>,
|
||||
gloves: Option<ItemSpec>,
|
||||
ring1: Option<ItemSpec>,
|
||||
ring2: Option<ItemSpec>,
|
||||
back: Option<ItemSpec>,
|
||||
belt: Option<ItemSpec>,
|
||||
legs: Option<ItemSpec>,
|
||||
feet: Option<ItemSpec>,
|
||||
tabard: Option<ItemSpec>,
|
||||
bag1: Option<ItemSpec>,
|
||||
bag2: Option<ItemSpec>,
|
||||
bag3: Option<ItemSpec>,
|
||||
bag4: Option<ItemSpec>,
|
||||
lantern: Option<ItemSpec>,
|
||||
glider: Option<ItemSpec>,
|
||||
// Weapons
|
||||
active_hands: Option<Hands>,
|
||||
inactive_hands: Option<Hands>,
|
||||
@ -264,96 +264,6 @@ impl assets::Asset for LoadoutSpec {
|
||||
const EXTENSION: &'static str = "ron";
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub enum ItemSpec {
|
||||
/// One specific item.
|
||||
/// Example:
|
||||
/// Item("common.items.armor.steel.foot")
|
||||
Item(String),
|
||||
/// Choice from items with weights.
|
||||
/// Example:
|
||||
/// Choice([
|
||||
/// (1.0, Some(Item("common.items.lantern.blue_0"))),
|
||||
/// (1.0, None),
|
||||
/// ])
|
||||
Choice(Vec<(f32, Option<ItemSpec>)>),
|
||||
}
|
||||
|
||||
impl ItemSpec {
|
||||
pub fn try_to_item(&self, asset_specifier: &str, rng: &mut impl Rng) -> Option<Item> {
|
||||
match self {
|
||||
ItemSpec::Item(specifier) => Some(Item::new_from_asset_expect(specifier)),
|
||||
|
||||
ItemSpec::Choice(items) => {
|
||||
choose(items, asset_specifier, rng)
|
||||
.as_ref()
|
||||
.and_then(|e| match e {
|
||||
entry @ ItemSpec::Item { .. } => entry.try_to_item(asset_specifier, rng),
|
||||
choice @ ItemSpec::Choice { .. } => {
|
||||
choice.try_to_item(asset_specifier, rng)
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
/// # Usage
|
||||
/// Read everything and checks if it's loading
|
||||
///
|
||||
/// # Panics
|
||||
/// 1) If weights are invalid
|
||||
/// 2) If item doesn't correspond to `EquipSlot`
|
||||
pub fn validate(&self, equip_slot: EquipSlot) {
|
||||
match self {
|
||||
ItemSpec::Item(specifier) => {
|
||||
let item = Item::new_from_asset_expect(specifier);
|
||||
assert!(
|
||||
equip_slot.can_hold(&item.kind),
|
||||
"Tried to place {} into {:?}",
|
||||
specifier,
|
||||
equip_slot
|
||||
);
|
||||
std::mem::drop(item);
|
||||
},
|
||||
ItemSpec::Choice(items) => {
|
||||
for (p, entry) in items {
|
||||
if p <= &0.0 {
|
||||
let err = format!(
|
||||
"Weight is less or equal to 0.0.\n ({:?}: {:?})",
|
||||
equip_slot, self
|
||||
);
|
||||
panic!("\n\n{}\n\n", err);
|
||||
} else {
|
||||
entry.as_ref().map(|e| e.validate(equip_slot));
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn choose<'a>(
|
||||
items: &'a [(f32, Option<ItemSpec>)],
|
||||
asset_specifier: &str,
|
||||
rng: &mut impl Rng,
|
||||
) -> &'a Option<ItemSpec> {
|
||||
items.choose_weighted(rng, |item| item.0).map_or_else(
|
||||
|err| match err {
|
||||
WeightedError::NoItem | WeightedError::AllWeightsZero => &None,
|
||||
WeightedError::InvalidWeight => {
|
||||
let err = format!("Negative values of probability in {}.", asset_specifier);
|
||||
common_base::dev_panic!(err, or return &None)
|
||||
},
|
||||
WeightedError::TooMany => {
|
||||
let err = format!("More than u32::MAX values in {}.", asset_specifier);
|
||||
common_base::dev_panic!(err, or return &None)
|
||||
},
|
||||
},
|
||||
|(_p, itemspec)| itemspec,
|
||||
)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn make_potion_bag(quantity: u32) -> Item {
|
||||
let mut bag = Item::new_from_asset_expect("common.items.armor.misc.bag.tiny_leather_pouch");
|
||||
@ -779,7 +689,7 @@ impl LoadoutBuilder {
|
||||
let spec = spec.eval(rng)?;
|
||||
|
||||
// Utility function to unwrap our itemspec
|
||||
let mut to_item = |maybe_item: Option<ItemSpecNew>| {
|
||||
let mut to_item = |maybe_item: Option<ItemSpec>| {
|
||||
if let Some(item) = maybe_item {
|
||||
item.try_to_item(rng)
|
||||
} else {
|
||||
|
@ -2,7 +2,7 @@ use crate::{
|
||||
assets::{self, AssetExt, Error},
|
||||
comp::{
|
||||
self, agent, humanoid,
|
||||
inventory::loadout_builder::{ItemSpec, LoadoutBuilder, LoadoutSpec},
|
||||
inventory::loadout_builder::{LoadoutBuilder, LoadoutSpec},
|
||||
Alignment, Body, Item,
|
||||
},
|
||||
lottery::LootSpec,
|
||||
@ -38,7 +38,7 @@ impl Default for AlignmentMark {
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub enum LoadoutKindNew {
|
||||
pub enum LoadoutKind {
|
||||
FromBody,
|
||||
Asset(String),
|
||||
Inline(LoadoutSpec),
|
||||
@ -46,43 +46,11 @@ pub enum LoadoutKindNew {
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct InventorySpec {
|
||||
loadout: LoadoutKindNew,
|
||||
loadout: LoadoutKind,
|
||||
#[serde(default)]
|
||||
items: Vec<(u32, String)>,
|
||||
}
|
||||
|
||||
/// - TwoHanded(ItemSpec) for one 2h or 1h weapon,
|
||||
/// - Paired(ItemSpec) for two 1h weapons aka berserker mode,
|
||||
/// - Mix { mainhand: ItemSpec, offhand: ItemSpec, }
|
||||
/// for two different 1h weapons.
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub enum Hands {
|
||||
TwoHanded(ItemSpec),
|
||||
Paired(ItemSpec),
|
||||
Mix {
|
||||
mainhand: ItemSpec,
|
||||
offhand: ItemSpec,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub enum LoadoutAsset {
|
||||
Loadout(String),
|
||||
Choice(Vec<(u32, String)>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub enum LoadoutKind {
|
||||
FromBody,
|
||||
Asset(LoadoutAsset),
|
||||
Hands(Hands),
|
||||
Extended {
|
||||
hands: Hands,
|
||||
base_asset: LoadoutAsset,
|
||||
inventory: Vec<(u32, String)>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub enum Meta {
|
||||
SkillSetAsset(String),
|
||||
@ -335,16 +303,16 @@ impl EntityInfo {
|
||||
.collect();
|
||||
|
||||
match loadout {
|
||||
LoadoutKindNew::FromBody => {
|
||||
LoadoutKind::FromBody => {
|
||||
self = self.with_default_equip();
|
||||
},
|
||||
LoadoutKindNew::Asset(loadout) => {
|
||||
LoadoutKind::Asset(loadout) => {
|
||||
let loadout = LoadoutBuilder::from_asset(&loadout, rng).unwrap_or_else(|e| {
|
||||
panic!("failed to load loadout for {config_asset}: {e:?}");
|
||||
});
|
||||
self.loadout = loadout;
|
||||
},
|
||||
LoadoutKindNew::Inline(loadout_spec) => {
|
||||
LoadoutKind::Inline(loadout_spec) => {
|
||||
let loadout =
|
||||
LoadoutBuilder::from_loadout_spec(loadout_spec, rng).unwrap_or_else(|e| {
|
||||
panic!("failed to load loadout for {config_asset}: {e:?}");
|
||||
|
Loading…
Reference in New Issue
Block a user