Replace EntityConfig main/second_tool with hands

+ Check equip_slot can hold item in LoadoutBuilder
This commit is contained in:
juliancoffee 2021-07-11 14:28:56 +03:00
parent 1d2ea717ab
commit d04364b1f1
68 changed files with 209 additions and 209 deletions

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.fallback"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,7 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.fallback"),
main_tool: Some(Choice([
hands: TwoHanded(Choice([
(1.0, Some(Item("common.items.weapons.tool.broom"))),
(1.0, Some(Item("common.items.weapons.tool.hoe"))),
(1.0, Some(Item("common.items.weapons.tool.pickaxe"))),
@ -14,7 +14,6 @@ EntityConfig (
(1.0, Some(Item("common.items.weapons.tool.shovel-1"))),
(1.0, Some(Item("common.items.weapons.bow.bone-1"))),
])),
second_tool: None,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.fallback"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-0.boss"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-0.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.gnarling.adlet_bow")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.gnarling.adlet_bow")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-0.gnarling"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-0.miniboss"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-0.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.gnarling.wooden_spear")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.gnarling.wooden_spear")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-0.gnarling"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-0.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.gnarling.gnoll_staff")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.gnarling.gnoll_staff")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-0.gnarling"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-1.boss"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-1.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.adlet.adlet_bow")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.adlet.adlet_bow")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-1.adlet_bow"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.creature.quad_small.generic"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-1.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.adlet.wooden_spear")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.adlet.wooden_spear")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-1.adlet_spear"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-1.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.adlet.gnoll_staff")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.adlet.gnoll_staff")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-1.adlet_spear"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-2.boss"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-2.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.sahagin.adlet_bow")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.sahagin.adlet_bow")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-2.sahagin"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.creature.quad_low.fanged"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-2.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.sahagin.wooden_spear")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.sahagin.wooden_spear")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-2.sahagin"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-2.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.sahagin.gnoll_staff")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.sahagin.gnoll_staff")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-2.sahagin"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.creature.quad_medium.carapace"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-3.boss"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-3.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.haniwa.adlet_bow")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.haniwa.adlet_bow")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-3.haniwa"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Item("common.items.crafting_ing.stones"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-3.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.haniwa.wooden_spear")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.haniwa.wooden_spear")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-3.haniwa"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-3.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.haniwa.gnoll_staff")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.haniwa.gnoll_staff")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-3.haniwa"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-4.boss"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-4.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.myrmidon.adlet_bow")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.myrmidon.adlet_bow")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-4.myrmidon"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-4.miniboss"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-4.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.myrmidon.wooden_spear")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.myrmidon.wooden_spear")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-4.myrmidon"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-4.enemy"),
main_tool: Some(Item("common.items.npc_weapons.biped_small.myrmidon.gnoll_staff")),
second_tool: None,
hands: TwoHanded(Item("common.items.npc_weapons.biped_small.myrmidon.gnoll_staff")),
meta: [
LoadoutAsset("common.loadout.dungeon.tier-4.myrmidon"),

View File

@ -5,12 +5,11 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-5.miniboss"),
main_tool: Some(Choice([
hands: TwoHanded(Choice([
(1.0, Some(Item("common.items.weapons.axe.malachite_axe-0"))),
(1.0, Some(Item("common.items.weapons.sword.bloodsteel-1"))),
(1.0, Some(Item("common.items.weapons.bow.velorite"))),
])),
second_tool: None,
meta: [
LoadoutAsset("common.loadout.dungeon.tier-5.beastmaster"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-5.boss"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,7 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-5.enemy"),
main_tool: Some(Choice([
hands: TwoHanded(Choice([
(1.0, Some(Item("common.items.weapons.axe_1h.orichalcum-0"))),
(2.0, Some(Item("common.items.weapons.sword.cultist"))),
(1.0, Some(Item("common.items.weapons.hammer.cultist_purp_2h-0"))),
@ -13,7 +13,6 @@ EntityConfig (
(1.0, Some(Item("common.items.weapons.bow.velorite"))),
(1.0, Some(Item("common.items.weapons.sceptre.sceptre_velorite_0"))),
])),
second_tool: None,
meta: [
LoadoutAsset("common.loadout.dungeon.tier-5.cultist"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-5.minion"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-5.minion"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [
LoadoutAsset("common.loadout.dungeon.tier-5.husk"),

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-5.miniboss"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Item("common.items.crafting_ing.twigs"),
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,11 +5,10 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-5.enemy"),
main_tool: Some(Choice([
hands: TwoHanded(Choice([
(1.5, Some(Item("common.items.npc_weapons.staff.bipedlarge-cultist"))),
(1.0, Some(Item("common.items.npc_weapons.bow.bipedlarge-velorite"))),
])),
second_tool: None,
meta: [],
)

View File

@ -5,11 +5,10 @@ EntityConfig (
loot: LootTable("common.loot_tables.dungeon.tier-5.enemy"),
main_tool: Some(Choice([
hands: TwoHanded(Choice([
(1.5, Some(Item("common.items.npc_weapons.sword.bipedlarge-cultist"))),
(1.0, Some(Item("common.items.npc_weapons.hammer.bipedlarge-cultist"))),
])),
second_tool: None,
meta: [],
)

View File

@ -17,12 +17,16 @@ EntityConfig (
/// or Uninit (means it should be specified something in the code)
loot: LootTable("common.loot_tables.humanoids"),
/// Main and second tools
/// Can be Option<Item> (with asset_specifier for item)
/// or Choice
/// (array of pairs with weight of choosing some item and Option<Item>)
main_tool: Some(Item("common.items.weapons.axe_1h.orichalcum-0")),
second_tool: None,
/// Hands:
/// - TwoHanded(ItemSpec) for one weapon 2h or 1h,
/// - Paired(ItemSpec) for two 1h weapons aka berserker mode,
/// - Mix {
/// mainhand: ItemSpec,
/// offhand: ItemSpec,
/// } for two different 1h weapons,
/// - Uninit which means that tool should be specified somewhere in code,
/// Where ItemSpec is taken from loadout_builder module
hands: TwoHanded(Item("common.items.weapons.sword.cultist")),
/// Meta Info
/// Possible fields:

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: Some(Item("common.items.weapons.sword.iron-4")),
second_tool: None,
hands: TwoHanded(Item("common.items.weapons.sword.iron-4")),
meta: [
SkillSetAsset("common.skillset.village.guard"),

View File

@ -6,8 +6,7 @@ EntityConfig (
// considering giving some gold/gems/materials?
loot: Uninit,
main_tool: Some(Item("common.items.weapons.bow.eldwood-0")),
second_tool: None,
hands: TwoHanded(Item("common.items.weapons.bow.eldwood-0")),
meta: [
SkillSetAsset("common.skillset.village.merchant"),

View File

@ -6,7 +6,7 @@ EntityConfig (
loot: Uninit,
main_tool: Some(Choice([
hands: TwoHanded(Choice([
(1.0, Some(Item("common.items.weapons.tool.broom"))),
(1.0, Some(Item("common.items.weapons.tool.hoe"))),
(1.0, Some(Item("common.items.weapons.tool.pickaxe"))),
@ -14,7 +14,6 @@ EntityConfig (
(1.0, Some(Item("common.items.weapons.tool.shovel-0"))),
(1.0, Some(Item("common.items.weapons.tool.shovel-1"))),
])),
second_tool: None,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -8,8 +8,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -5,8 +5,7 @@ EntityConfig (
loot: Uninit,
main_tool: None,
second_tool: None,
hands: Uninit,
meta: [],
)

View File

@ -92,17 +92,26 @@ impl ItemSpec {
///
/// # Panics
/// 1) If weights are invalid
pub fn validate(&self, key: EquipSlot) {
/// 2) If item doesn't correspond to `EquipSlot`
pub fn validate(&self, equip_slot: EquipSlot) {
match self {
ItemSpec::Item(specifier) => std::mem::drop(Item::new_from_asset_expect(specifier)),
ItemSpec::Item(specifier) => {
let item = Item::new_from_asset_expect(specifier);
if !equip_slot.can_hold(&item.kind) {
panic!("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 ({:?}: {:?})", key, self,);
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(key));
entry.as_ref().map(|e| e.validate(equip_slot));
}
}
},
@ -389,13 +398,13 @@ impl LoadoutBuilder {
.with_default_equipment(body)
}
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
/// Set default active mainhand weapon based on `body`
pub fn with_default_maintool(self, body: &Body) -> Self {
self.active_mainhand(Some(default_main_tool(body)))
}
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
/// Set default equipement based on `body`
pub fn with_default_equipment(self, body: &Body) -> Self {
let chest = match body {
@ -466,7 +475,7 @@ impl LoadoutBuilder {
}
}
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn with_preset(mut self, preset: Preset) -> Self {
let rng = &mut rand::thread_rng();
match preset {
@ -478,7 +487,7 @@ impl LoadoutBuilder {
self
}
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn with_creator(
mut self,
creator: fn(LoadoutBuilder, Option<&SiteInformation>) -> LoadoutBuilder,
@ -497,7 +506,7 @@ impl LoadoutBuilder {
/// 1) Will panic if there is no asset with such `asset_specifier`
/// 2) Will panic if path to item specified in loadout file doesn't exist
/// 3) Will panic while runs in tests and asset doesn't have "correct" form
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn with_asset_expect(mut self, asset_specifier: &str, rng: &mut impl Rng) -> Self {
let spec = LoadoutSpec::load_expect(asset_specifier).read().0.clone();
for (key, entry) in spec {
@ -573,88 +582,96 @@ impl LoadoutBuilder {
/// Set default armor items for the loadout. This may vary with game
/// updates, but should be safe defaults for a new character.
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn defaults(self) -> Self {
let rng = &mut rand::thread_rng();
self.with_asset_expect("common.loadout.default", rng)
}
#[must_use = "Method consumes builder and returns updated builder."]
fn with_equipment(mut self, equip_slot: EquipSlot, item: Option<Item>) -> Self {
// Panic if item doesn't correspond to slot
assert!(
item.as_ref()
.map_or(true, |item| equip_slot.can_hold(&item.kind))
);
self.0.swap(equip_slot, item);
self
}
#[must_use]
pub fn active_mainhand(self, item: Option<Item>) -> Self {
self.with_equipment(EquipSlot::ActiveMainhand, item)
}
#[must_use]
pub fn active_offhand(self, item: Option<Item>) -> Self {
self.with_equipment(EquipSlot::ActiveOffhand, item)
}
#[must_use]
pub fn inactive_mainhand(self, item: Option<Item>) -> Self {
self.with_equipment(EquipSlot::InactiveMainhand, item)
}
#[must_use]
pub fn inactive_offhand(self, item: Option<Item>) -> Self {
self.with_equipment(EquipSlot::InactiveOffhand, item)
}
#[must_use = "Method consumes builder and returns updated builder."]
fn with_armor(self, armor_slot: ArmorSlot, item: Option<Item>) -> Self {
self.with_equipment(EquipSlot::Armor(armor_slot), item)
}
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn active_mainhand(self, item: Option<Item>) -> Self {
self.with_equipment(EquipSlot::ActiveMainhand, item)
}
#[must_use = "Method consumes builder and returns updated builder."]
pub fn active_offhand(self, item: Option<Item>) -> Self {
self.with_equipment(EquipSlot::ActiveOffhand, item)
}
#[must_use = "Method consumes builder and returns updated builder."]
pub fn inactive_mainhand(self, item: Option<Item>) -> Self {
self.with_equipment(EquipSlot::InactiveMainhand, item)
}
#[must_use = "Method consumes builder and returns updated builder."]
pub fn inactive_offhand(self, item: Option<Item>) -> Self {
self.with_equipment(EquipSlot::InactiveOffhand, item)
}
#[must_use = "Method consumes builder and returns updated builder."]
pub fn shoulder(self, item: Option<Item>) -> Self {
self.with_armor(ArmorSlot::Shoulders, item)
}
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn chest(self, item: Option<Item>) -> Self { self.with_armor(ArmorSlot::Chest, item) }
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn belt(self, item: Option<Item>) -> Self { self.with_armor(ArmorSlot::Belt, item) }
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn hands(self, item: Option<Item>) -> Self { self.with_armor(ArmorSlot::Hands, item) }
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn pants(self, item: Option<Item>) -> Self { self.with_armor(ArmorSlot::Legs, item) }
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn feet(self, item: Option<Item>) -> Self { self.with_armor(ArmorSlot::Feet, item) }
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn back(self, item: Option<Item>) -> Self { self.with_armor(ArmorSlot::Back, item) }
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn ring1(self, item: Option<Item>) -> Self { self.with_armor(ArmorSlot::Ring1, item) }
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn ring2(self, item: Option<Item>) -> Self { self.with_armor(ArmorSlot::Ring2, item) }
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn neck(self, item: Option<Item>) -> Self { self.with_armor(ArmorSlot::Neck, item) }
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn lantern(self, item: Option<Item>) -> Self {
self.with_equipment(EquipSlot::Lantern, item)
}
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn glider(self, item: Option<Item>) -> Self { self.with_equipment(EquipSlot::Glider, item) }
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn head(self, item: Option<Item>) -> Self { self.with_armor(ArmorSlot::Head, item) }
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn tabard(self, item: Option<Item>) -> Self { self.with_armor(ArmorSlot::Tabard, item) }
#[must_use]
#[must_use = "Method consumes builder and returns updated builder."]
pub fn bag(self, which: ArmorSlot, item: Option<Item>) -> Self { self.with_armor(which, item) }
#[must_use]

View File

@ -40,14 +40,23 @@ enum Meta {
}
#[derive(Debug, Deserialize, Clone)]
struct EntityConfig {
enum Hands {
TwoHanded(ItemSpec),
Paired(ItemSpec),
Mix {
mainhand: ItemSpec,
offhand: ItemSpec,
},
Uninit,
}
#[derive(Debug, Deserialize, Clone)]
pub struct EntityConfig {
name: Option<String>,
body: BodyBuilder,
alignment: AlignmentMark,
loot: LootKind,
// TODO: replace with `hands` field to support one 2h weapon/ pair 1h weapons
main_tool: Option<ItemSpec>,
second_tool: Option<ItemSpec>,
hands: Hands,
// Meta fields
meta: Vec<Meta>,
}
@ -58,6 +67,13 @@ impl assets::Asset for EntityConfig {
const EXTENSION: &'static str = "ron";
}
impl EntityConfig {
pub fn from_asset_expect(asset_specifier: &str) -> EntityConfig {
Self::load_owned(asset_specifier)
.unwrap_or_else(|e| panic!("Failed to load {}. Error: {}", asset_specifier, e))
}
}
#[derive(Clone)]
pub struct EntityInfo {
pub pos: Vec3<f32>,
@ -114,14 +130,13 @@ impl EntityInfo {
}
// helper function to apply config
fn with_entity_config(mut self, config: EntityConfig, asset_specifier: Option<&str>) -> Self {
fn with_entity_config(mut self, config: EntityConfig, config_asset: Option<&str>) -> Self {
let EntityConfig {
name,
body,
alignment,
loot,
main_tool,
second_tool,
hands,
meta,
} = config;
@ -161,15 +176,36 @@ impl EntityInfo {
}
let rng = &mut rand::thread_rng();
if let Some(main_tool) =
main_tool.and_then(|i| i.try_to_item(asset_specifier.unwrap_or("??"), rng))
{
self = self.with_main_tool(main_tool);
}
if let Some(second_tool) =
second_tool.and_then(|i| i.try_to_item(asset_specifier.unwrap_or("??"), rng))
{
self = self.with_main_tool(second_tool);
match hands {
Hands::TwoHanded(main_tool) => {
let tool = main_tool.try_to_item(config_asset.unwrap_or("??"), rng);
if let Some(tool) = tool {
self = self.with_main_tool(tool);
}
},
Hands::Paired(tool) => {
//FIXME: very stupid code, which just tries same item two times
//figure out reasonable way to clone item
let main_tool = tool.try_to_item(config_asset.unwrap_or("??"), rng);
let second_tool = tool.try_to_item(config_asset.unwrap_or("??"), rng);
if let Some(main_tool) = main_tool {
self = self.with_main_tool(main_tool);
}
if let Some(second_tool) = second_tool {
self = self.with_second_tool(second_tool);
}
},
Hands::Mix { mainhand, offhand } => {
let main_tool = mainhand.try_to_item(config_asset.unwrap_or("??"), rng);
let second_tool = offhand.try_to_item(config_asset.unwrap_or("??"), rng);
if let Some(main_tool) = main_tool {
self = self.with_main_tool(main_tool);
}
if let Some(second_tool) = second_tool {
self = self.with_second_tool(second_tool);
}
},
Hands::Uninit => {},
}
for field in meta {
@ -337,24 +373,32 @@ mod tests {
#[test]
fn test_all_entity_assets() {
// It just load everything that could
let entity_configs = assets::read_expect_dir::<EntityConfig>("common.entity", true);
for config in entity_configs {
let entity_configs = assets::load_dir::<EntityConfig>("common.entity", true)
.expect("Failed to access entity directory");
for config_asset in entity_configs.ids() {
println!("{}:", config_asset);
let EntityConfig {
main_tool,
second_tool,
hands,
loot,
body,
meta,
name: _name, // can't fail if serialized, it's a boring String
alignment: _alignment, // can't fail if serialized, it's a boring enum
} = config.clone();
} = EntityConfig::from_asset_expect(config_asset);
if let Some(main_tool) = main_tool {
main_tool.validate(EquipSlot::ActiveMainhand);
}
if let Some(second_tool) = second_tool {
second_tool.validate(EquipSlot::ActiveOffhand);
match hands {
Hands::TwoHanded(main_tool) => {
main_tool.validate(EquipSlot::ActiveMainhand);
},
Hands::Paired(tool) => {
tool.validate(EquipSlot::ActiveMainhand);
tool.validate(EquipSlot::ActiveOffhand);
},
Hands::Mix { mainhand, offhand } => {
mainhand.validate(EquipSlot::ActiveMainhand);
offhand.validate(EquipSlot::ActiveOffhand);
},
Hands::Uninit => {},
}
match body {