mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Support modular weapon components made from a tagged material using the material as a multiplier.
This commit is contained in:
parent
af01c69456
commit
77aeb43247
@ -5,5 +5,5 @@ ItemDef(
|
||||
kind: "BloodsteelIngot",
|
||||
),
|
||||
quality: Common,
|
||||
tags: [],
|
||||
)
|
||||
tags: [MetalIngot(1.75)],
|
||||
)
|
||||
|
@ -5,5 +5,5 @@ ItemDef(
|
||||
kind: "BronzeIngot",
|
||||
),
|
||||
quality: Common,
|
||||
tags: [],
|
||||
)
|
||||
tags: [MetalIngot(0.75)],
|
||||
)
|
||||
|
@ -5,5 +5,5 @@ ItemDef(
|
||||
kind: "CobaltIngot",
|
||||
),
|
||||
quality: Common,
|
||||
tags: [],
|
||||
)
|
||||
tags: [MetalIngot(1.5)],
|
||||
)
|
||||
|
@ -5,5 +5,5 @@ ItemDef(
|
||||
kind: "CopperIngot",
|
||||
),
|
||||
quality: Common,
|
||||
tags: [],
|
||||
)
|
||||
tags: [MetalIngot(0.4)],
|
||||
)
|
||||
|
@ -5,5 +5,5 @@ ItemDef(
|
||||
kind: "IronIngot",
|
||||
),
|
||||
quality: Common,
|
||||
tags: [],
|
||||
)
|
||||
tags: [MetalIngot(1.0)],
|
||||
)
|
||||
|
@ -0,0 +1,17 @@
|
||||
ItemDef(
|
||||
name: "Metal sword blade",
|
||||
description: "A sword blade made of metal.",
|
||||
kind: ModularComponent((
|
||||
toolkind: Sword,
|
||||
modkind: Damage,
|
||||
stats: (
|
||||
equip_time_millis: 250,
|
||||
power: 1.0,
|
||||
poise_strength: 0.75,
|
||||
speed: 0.0,
|
||||
),
|
||||
)),
|
||||
quality: Common,
|
||||
tags: [ModularComponent((toolkind: Sword, modkind: Damage))],
|
||||
)
|
||||
|
@ -5,5 +5,5 @@ ItemDef(
|
||||
kind: "SteelIngot",
|
||||
),
|
||||
quality: Common,
|
||||
tags: [],
|
||||
)
|
||||
tags: [MetalIngot(1.25)],
|
||||
)
|
||||
|
@ -5,5 +5,5 @@ ItemDef(
|
||||
kind: "TinIngot",
|
||||
),
|
||||
quality: Common,
|
||||
tags: [],
|
||||
)
|
||||
tags: [MetalIngot(0.25)],
|
||||
)
|
||||
|
@ -18,6 +18,5 @@ ItemDef(
|
||||
],
|
||||
),
|
||||
quality: Common,
|
||||
tags: [ClothItem],
|
||||
tags: [],
|
||||
)
|
||||
|
||||
|
19
assets/common/items/tag_examples/metal_ingot.ron
Normal file
19
assets/common/items/tag_examples/metal_ingot.ron
Normal file
@ -0,0 +1,19 @@
|
||||
ItemDef(
|
||||
name: "Any metal ingot",
|
||||
description: "Ingots made from various metals.",
|
||||
kind: TagExamples(
|
||||
item_ids: [
|
||||
"common.items.crafting_ing.bloodsteel_ingot",
|
||||
"common.items.crafting_ing.bronze_ingot",
|
||||
"common.items.crafting_ing.cobalt_ingot",
|
||||
"common.items.crafting_ing.copper_ingot",
|
||||
"common.items.crafting_ing.iron_ingot",
|
||||
"common.items.crafting_ing.steel_ingot",
|
||||
"common.items.crafting_ing.tin_ingot",
|
||||
],
|
||||
),
|
||||
quality: Common,
|
||||
tags: [],
|
||||
)
|
||||
|
||||
|
@ -363,4 +363,11 @@
|
||||
(Item("common.items.crafting_tools.sewing_set"), 0),
|
||||
]
|
||||
),
|
||||
"metal_blade": (
|
||||
("common.items.crafting_ing.modular.damage.sword.metal_blade", 1),
|
||||
[
|
||||
(Tag(MetalIngot(0.0)), 5),
|
||||
(Item("common.items.crafting_tools.craftsman_hammer"), 0),
|
||||
]
|
||||
),
|
||||
}
|
||||
|
@ -87,10 +87,25 @@ pub trait TagExampleInfo {
|
||||
fn exemplar_identifier(&self) -> &'static str;
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
pub enum ItemTag {
|
||||
ClothItem,
|
||||
ModularComponent(ModularComponentTag),
|
||||
MetalIngot(f32),
|
||||
}
|
||||
|
||||
// The PartialEq implementation for ItemTag is used for determining whether a
|
||||
// RecipeInput matches
|
||||
impl PartialEq for ItemTag {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
use ItemTag::*;
|
||||
match (self, other) {
|
||||
(ClothItem, ClothItem) => true,
|
||||
(ModularComponent(a), ModularComponent(b)) => a == b,
|
||||
(MetalIngot(_), MetalIngot(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TagExampleInfo for ItemTag {
|
||||
@ -98,6 +113,7 @@ impl TagExampleInfo for ItemTag {
|
||||
match self {
|
||||
ItemTag::ClothItem => "cloth item",
|
||||
ItemTag::ModularComponent(kind) => kind.name(),
|
||||
ItemTag::MetalIngot(_) => "metal ingot",
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,6 +121,7 @@ impl TagExampleInfo for ItemTag {
|
||||
match self {
|
||||
ItemTag::ClothItem => "common.items.tag_examples.cloth_item",
|
||||
ItemTag::ModularComponent(tag) => tag.exemplar_identifier(),
|
||||
ItemTag::MetalIngot(_) => "common.items.tag_examples.metal_ingot",
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -245,7 +262,7 @@ impl ItemDef {
|
||||
ItemKind::Tool(tool::Tool {
|
||||
stats: tool::StatKind::Modular,
|
||||
..
|
||||
})
|
||||
}) | ItemKind::ModularComponent(_)
|
||||
)
|
||||
}
|
||||
|
||||
@ -644,6 +661,7 @@ pub trait ItemDesc {
|
||||
fn num_slots(&self) -> u16;
|
||||
fn item_definition_id(&self) -> &str;
|
||||
fn components(&self) -> &[Item];
|
||||
fn tags(&self) -> &[ItemTag];
|
||||
}
|
||||
|
||||
impl ItemDesc for Item {
|
||||
@ -660,6 +678,8 @@ impl ItemDesc for Item {
|
||||
fn item_definition_id(&self) -> &str { &self.item_def.item_definition_id }
|
||||
|
||||
fn components(&self) -> &[Item] { &self.components }
|
||||
|
||||
fn tags(&self) -> &[ItemTag] { &self.item_def.tags }
|
||||
}
|
||||
|
||||
impl ItemDesc for ItemDef {
|
||||
@ -676,6 +696,8 @@ impl ItemDesc for ItemDef {
|
||||
fn item_definition_id(&self) -> &str { &self.item_definition_id }
|
||||
|
||||
fn components(&self) -> &[Item] { &[] }
|
||||
|
||||
fn tags(&self) -> &[ItemTag] { &self.tags }
|
||||
}
|
||||
|
||||
impl Component for Item {
|
||||
|
@ -3,11 +3,18 @@
|
||||
|
||||
use crate::{
|
||||
assets::{self, Asset},
|
||||
comp::{item::ItemKind, skills::Skill, CharacterAbility, Item},
|
||||
comp::{
|
||||
item::{ItemDesc, ItemKind, ItemTag},
|
||||
skills::Skill,
|
||||
CharacterAbility, Item,
|
||||
},
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
use std::{
|
||||
ops::{AddAssign, MulAssign},
|
||||
time::Duration,
|
||||
};
|
||||
use tracing::error;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
@ -71,6 +78,22 @@ impl Stats {
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<Stats> for Stats {
|
||||
fn add_assign(&mut self, other: Stats) {
|
||||
self.equip_time_millis += other.equip_time_millis;
|
||||
self.power += other.power;
|
||||
self.poise_strength += other.poise_strength;
|
||||
self.speed += other.speed;
|
||||
}
|
||||
}
|
||||
impl MulAssign<f32> for Stats {
|
||||
fn mul_assign(&mut self, scalar: f32) {
|
||||
self.power *= scalar;
|
||||
self.poise_strength *= scalar;
|
||||
self.speed *= scalar;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum StatKind {
|
||||
Direct(Stats),
|
||||
@ -83,14 +106,33 @@ impl StatKind {
|
||||
StatKind::Direct(stats) => *stats,
|
||||
StatKind::Modular => Stats::zeroed(),
|
||||
};
|
||||
let mut best_multiplier: Option<f32> = None;
|
||||
for item in components.iter() {
|
||||
if let ItemKind::ModularComponent(mc) = item.kind() {
|
||||
stats.equip_time_millis += mc.stats.equip_time_millis;
|
||||
stats.power += mc.stats.power;
|
||||
stats.poise_strength += mc.stats.poise_strength;
|
||||
stats.speed += mc.stats.speed;
|
||||
match item.kind() {
|
||||
ItemKind::ModularComponent(mc) => {
|
||||
let inner_stats = StatKind::Direct(mc.stats).resolve_stats(item.components());
|
||||
stats += inner_stats;
|
||||
},
|
||||
ItemKind::Ingredient { .. } => {
|
||||
for tag in item.tags() {
|
||||
// exhaustive match to ensure that new tags get stats counted
|
||||
match tag {
|
||||
ItemTag::ClothItem => {},
|
||||
ItemTag::ModularComponent(_) => {},
|
||||
ItemTag::MetalIngot(multiplier) => {
|
||||
best_multiplier =
|
||||
Some(best_multiplier.unwrap_or(*multiplier).max(*multiplier));
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
// TODO: add stats from enhancement slots, unless those end up as tagged
|
||||
// ingredients
|
||||
_ => (),
|
||||
}
|
||||
// TODO: add stats from enhancement slots
|
||||
}
|
||||
if let Some(multiplier) = best_multiplier {
|
||||
stats *= multiplier;
|
||||
}
|
||||
// if an item has 0.0 speed, that panics due to being infinite duration, so
|
||||
// enforce speed >= 0.1
|
||||
|
@ -1,6 +1,6 @@
|
||||
use common::comp::item::{
|
||||
armor::{Armor, ArmorKind, Protection},
|
||||
tool::{Hands, Tool, ToolKind},
|
||||
tool::{Hands, StatKind, Tool, ToolKind},
|
||||
Item, ItemDesc, ItemKind, ModularComponent,
|
||||
};
|
||||
use std::{borrow::Cow, fmt::Write};
|
||||
@ -24,7 +24,11 @@ pub fn item_text<'a>(item: &'a impl ItemDesc) -> (&'_ str, Cow<'a, str>) {
|
||||
Cow::Owned(armor_desc(armor, item.description(), item.num_slots()))
|
||||
},
|
||||
ItemKind::Tool(tool) => Cow::Owned(tool_desc(&tool, item.components(), item.description())),
|
||||
ItemKind::ModularComponent(mc) => Cow::Owned(modular_component_desc(mc)),
|
||||
ItemKind::ModularComponent(mc) => Cow::Owned(modular_component_desc(
|
||||
mc,
|
||||
item.components(),
|
||||
item.description(),
|
||||
)),
|
||||
ItemKind::Glider(_glider) => Cow::Owned(glider_desc(item.description())),
|
||||
ItemKind::Consumable { .. } => Cow::Owned(consumable_desc(item.description())),
|
||||
ItemKind::Throwable { .. } => Cow::Owned(throwable_desc(item.description())),
|
||||
@ -39,8 +43,21 @@ pub fn item_text<'a>(item: &'a impl ItemDesc) -> (&'_ str, Cow<'a, str>) {
|
||||
}
|
||||
|
||||
// TODO: localization
|
||||
fn modular_component_desc(mc: &ModularComponent) -> String {
|
||||
format!("Modular Component\n\n{:?}", mc)
|
||||
fn modular_component_desc(mc: &ModularComponent, components: &[Item], description: &str) -> String {
|
||||
let mut result = format!(
|
||||
"Modular Component\n\n{:?}\n\n{}",
|
||||
StatKind::Direct(mc.stats).resolve_stats(components),
|
||||
description
|
||||
);
|
||||
if !components.is_empty() {
|
||||
result += "Made from:\n";
|
||||
for component in components {
|
||||
result += component.name();
|
||||
result += "\n"
|
||||
}
|
||||
result += "\n";
|
||||
}
|
||||
result
|
||||
}
|
||||
fn glider_desc(desc: &str) -> String { format!("Glider\n\n{}\n\n<Right-Click to use>", desc) }
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user