diff --git a/mona_core/src/attribute/attribute.rs b/mona_core/src/attribute/attribute.rs index 03a703c8..81944ad2 100644 --- a/mona_core/src/attribute/attribute.rs +++ b/mona_core/src/attribute/attribute.rs @@ -112,40 +112,70 @@ impl AttributeCommon for T { let key1 = AttributeName::atk_ratio_name_by_element(element); let key2 = AttributeName::atk_ratio_name_by_skill_type(skill); + let value2 = if let Some(name) = key2 { + self.get_value(name) + } else { + 0.0 + }; + self.get_value(AttributeName::ATKRatioBase) - + self.get_value(key1) + self.get_value(key2) + + self.get_value(key1) + value2 } fn get_def_ratio(&self, element: Element, skill: SkillType) -> f64 { let key1 = AttributeName::def_ratio_name_by_element(element); let key2 = AttributeName::def_ratio_name_by_skill_type(skill); + let value2 = if let Some(name) = key2 { + self.get_value(name) + } else { + 0.0 + }; + self.get_value(AttributeName::DEFRatioBase) - + self.get_value(key1) + self.get_value(key2) + + self.get_value(key1) + value2 } fn get_hp_ratio(&self, element: Element, skill: SkillType) -> f64 { let key1 = AttributeName::hp_ratio_name_by_element(element); let key2 = AttributeName::hp_ratio_name_by_skill_type(skill); + let value2 = if let Some(name) = key2 { + self.get_value(name) + } else { + 0.0 + }; + self.get_value(AttributeName::HPRatioBase) - + self.get_value(key1) + self.get_value(key2) + + self.get_value(key1) + value2 } fn get_extra_damage(&self, element: Element, skill: SkillType) -> f64 { let key1 = AttributeName::extra_dmg_name_by_element(element); let key2 = AttributeName::extra_dmg_name_by_skill_type(skill); + let value2 = if let Some(name) = key2 { + self.get_value(name) + } else { + 0.0 + }; + self.get_value(AttributeName::ExtraDmgBase) - + self.get_value(key1) + self.get_value(key2) + + self.get_value(key1) + value2 } fn get_bonus(&self, element: Element, skill: SkillType) -> f64 { let key1 = AttributeName::bonus_name_by_element(element); let key2 = AttributeName::bonus_name_by_skill_type(skill); + let value2 = if let Some(name) = key2 { + self.get_value(name) + } else { + 0.0 + }; + let mut temp = self.get_value(AttributeName::BonusBase) - + self.get_value(key1) + self.get_value(key2); + + self.get_value(key1) + value2; // todo refactor if element != Element::Physical && skill == SkillType::NormalAttack { temp += self.get_value(AttributeName::BonusNormalAndElemental); @@ -157,16 +187,28 @@ impl AttributeCommon for T { let key1 = AttributeName::critical_rate_name_by_element(element); let key2 = AttributeName::critical_rate_name_by_skill_type(skill); + let value2 = if let Some(name) = key2 { + self.get_value(name) + } else { + 0.0 + }; + self.get_value(AttributeName::CriticalBase) + self.get_value(AttributeName::CriticalAttacking) - + self.get_value(key1) + self.get_value(key2) + + self.get_value(key1) + value2 } fn get_critical_damage(&self, element: Element, skill: SkillType) -> f64 { let key1 = AttributeName::critical_damage_name_by_element(element); let key2 = AttributeName::critical_damage_name_by_skill_name(skill); + let value2 = if let Some(name) = key2 { + self.get_value(name) + } else { + 0.0 + }; + self.get_value(AttributeName::CriticalDamageBase) - + self.get_value(key1) + self.get_value(key2) + + self.get_value(key1) + value2 } fn get_enemy_res_minus(&self, element: Element, _skill: SkillType) -> f64 { diff --git a/mona_core/src/attribute/attribute_name.rs b/mona_core/src/attribute/attribute_name.rs index ebc05851..47a814da 100644 --- a/mona_core/src/attribute/attribute_name.rs +++ b/mona_core/src/attribute/attribute_name.rs @@ -189,13 +189,14 @@ impl AttributeName { } } - pub fn bonus_name_by_skill_type(skill_type: SkillType) -> AttributeName { + pub fn bonus_name_by_skill_type(skill_type: SkillType) -> Option { match skill_type { - SkillType::NormalAttack => AttributeName::BonusNormalAttack, - SkillType::ChargedAttack => AttributeName::BonusChargedAttack, - SkillType::PlungingAttackOnGround | SkillType::PlungingAttackInAction => AttributeName::BonusPlungingAttack, - SkillType::ElementalSkill => AttributeName::BonusElementalSkill, - SkillType::ElementalBurst => AttributeName::BonusElementalBurst, + SkillType::NormalAttack => Some(AttributeName::BonusNormalAttack), + SkillType::ChargedAttack => Some(AttributeName::BonusChargedAttack), + SkillType::PlungingAttackOnGround | SkillType::PlungingAttackInAction => Some(AttributeName::BonusPlungingAttack), + SkillType::ElementalSkill => Some(AttributeName::BonusElementalSkill), + SkillType::ElementalBurst => Some(AttributeName::BonusElementalBurst), + SkillType::NoneType => None, } } @@ -212,13 +213,14 @@ impl AttributeName { } } - pub fn critical_rate_name_by_skill_type(skill_type: SkillType) -> AttributeName { + pub fn critical_rate_name_by_skill_type(skill_type: SkillType) -> Option { match skill_type { - SkillType::NormalAttack => AttributeName::CriticalNormalAttack, - SkillType::ChargedAttack => AttributeName::CriticalChargedAttack, - SkillType::PlungingAttackOnGround | SkillType::PlungingAttackInAction => AttributeName::CriticalPlungingAttack, - SkillType::ElementalSkill => AttributeName::CriticalElementalSkill, - SkillType::ElementalBurst => AttributeName::CriticalElementalBurst, + SkillType::NormalAttack => Some(AttributeName::CriticalNormalAttack), + SkillType::ChargedAttack => Some(AttributeName::CriticalChargedAttack), + SkillType::PlungingAttackOnGround | SkillType::PlungingAttackInAction => Some(AttributeName::CriticalPlungingAttack), + SkillType::ElementalSkill => Some(AttributeName::CriticalElementalSkill), + SkillType::ElementalBurst => Some(AttributeName::CriticalElementalBurst), + SkillType::NoneType => None, } } @@ -235,13 +237,14 @@ impl AttributeName { } } - pub fn critical_damage_name_by_skill_name(skill_type: SkillType) -> AttributeName { + pub fn critical_damage_name_by_skill_name(skill_type: SkillType) -> Option { match skill_type { - SkillType::NormalAttack => AttributeName::CriticalDamageNormalAttack, - SkillType::ChargedAttack => AttributeName::CriticalDamageChargedAttack, - SkillType::PlungingAttackOnGround | SkillType::PlungingAttackInAction => AttributeName::CriticalDamagePlungingAttack, - SkillType::ElementalSkill => AttributeName::CriticalDamageElementalSkill, - SkillType::ElementalBurst => AttributeName::CriticalDamageElementalBurst, + SkillType::NormalAttack => Some(AttributeName::CriticalDamageNormalAttack), + SkillType::ChargedAttack => Some(AttributeName::CriticalDamageChargedAttack), + SkillType::PlungingAttackOnGround | SkillType::PlungingAttackInAction => Some(AttributeName::CriticalDamagePlungingAttack), + SkillType::ElementalSkill => Some(AttributeName::CriticalDamageElementalSkill), + SkillType::ElementalBurst => Some(AttributeName::CriticalDamageElementalBurst), + SkillType::NoneType => None, } } @@ -258,13 +261,14 @@ impl AttributeName { } } - pub fn hp_ratio_name_by_skill_type(skill_type: SkillType) -> AttributeName { + pub fn hp_ratio_name_by_skill_type(skill_type: SkillType) -> Option { match skill_type { - SkillType::NormalAttack => AttributeName::HPRatioNormalAttack, - SkillType::ChargedAttack => AttributeName::HPRatioChargedAttack, - SkillType::PlungingAttackOnGround | SkillType::PlungingAttackInAction => AttributeName::HPRatioPlungingAttack, - SkillType::ElementalSkill => AttributeName::HPRatioElementalSkill, - SkillType::ElementalBurst => AttributeName::HPRatioElementalBurst, + SkillType::NormalAttack => Some(AttributeName::HPRatioNormalAttack), + SkillType::ChargedAttack => Some(AttributeName::HPRatioChargedAttack), + SkillType::PlungingAttackOnGround | SkillType::PlungingAttackInAction => Some(AttributeName::HPRatioPlungingAttack), + SkillType::ElementalSkill => Some(AttributeName::HPRatioElementalSkill), + SkillType::ElementalBurst => Some(AttributeName::HPRatioElementalBurst), + SkillType::NoneType => None, } } @@ -281,13 +285,14 @@ impl AttributeName { } } - pub fn def_ratio_name_by_skill_type(skill_type: SkillType) -> AttributeName { + pub fn def_ratio_name_by_skill_type(skill_type: SkillType) -> Option { match skill_type { - SkillType::NormalAttack => AttributeName::DEFRatioNormalAttack, - SkillType::ChargedAttack => AttributeName::DEFRatioChargedAttack, - SkillType::PlungingAttackOnGround | SkillType::PlungingAttackInAction => AttributeName::DEFRatioPlungingAttack, - SkillType::ElementalSkill => AttributeName::DEFRatioElementalSkill, - SkillType::ElementalBurst => AttributeName::DEFRatioElementalBurst, + SkillType::NormalAttack => Some(AttributeName::DEFRatioNormalAttack), + SkillType::ChargedAttack => Some(AttributeName::DEFRatioChargedAttack), + SkillType::PlungingAttackOnGround | SkillType::PlungingAttackInAction => Some(AttributeName::DEFRatioPlungingAttack), + SkillType::ElementalSkill => Some(AttributeName::DEFRatioElementalSkill), + SkillType::ElementalBurst => Some(AttributeName::DEFRatioElementalBurst), + SkillType::NoneType => None, } } @@ -304,13 +309,14 @@ impl AttributeName { } } - pub fn atk_ratio_name_by_skill_type(skill_type: SkillType) -> AttributeName { + pub fn atk_ratio_name_by_skill_type(skill_type: SkillType) -> Option { match skill_type { - SkillType::NormalAttack => AttributeName::ATKRatioNormalAttack, - SkillType::ChargedAttack => AttributeName::ATKRatioChargedAttack, - SkillType::PlungingAttackOnGround | SkillType::PlungingAttackInAction => AttributeName::ATKRatioPlungingAttack, - SkillType::ElementalSkill => AttributeName::ATKRatioElementalSkill, - SkillType::ElementalBurst => AttributeName::ATKRatioElementalBurst, + SkillType::NormalAttack => Some(AttributeName::ATKRatioNormalAttack), + SkillType::ChargedAttack => Some(AttributeName::ATKRatioChargedAttack), + SkillType::PlungingAttackOnGround | SkillType::PlungingAttackInAction => Some(AttributeName::ATKRatioPlungingAttack), + SkillType::ElementalSkill => Some(AttributeName::ATKRatioElementalSkill), + SkillType::ElementalBurst => Some(AttributeName::ATKRatioElementalBurst), + SkillType::NoneType => None, } } @@ -327,13 +333,14 @@ impl AttributeName { } } - pub fn extra_dmg_name_by_skill_type(skill_type: SkillType) -> AttributeName { + pub fn extra_dmg_name_by_skill_type(skill_type: SkillType) -> Option { match skill_type { - SkillType::NormalAttack => AttributeName::ExtraDmgNormalAttack, - SkillType::ChargedAttack => AttributeName::ExtraDmgChargedAttack, - SkillType::PlungingAttackOnGround | SkillType::PlungingAttackInAction => AttributeName::ExtraDmgPlungingAttack, - SkillType::ElementalSkill => AttributeName::ExtraDmgElementalSkill, - SkillType::ElementalBurst => AttributeName::ExtraDmgElementalBurst, + SkillType::NormalAttack => Some(AttributeName::ExtraDmgNormalAttack), + SkillType::ChargedAttack => Some(AttributeName::ExtraDmgChargedAttack), + SkillType::PlungingAttackOnGround | SkillType::PlungingAttackInAction => Some(AttributeName::ExtraDmgPlungingAttack), + SkillType::ElementalSkill => Some(AttributeName::ExtraDmgElementalSkill), + SkillType::ElementalBurst => Some(AttributeName::ExtraDmgElementalBurst), + SkillType::NoneType => None, } } diff --git a/mona_core/src/attribute/complicated_attribute_graph.rs b/mona_core/src/attribute/complicated_attribute_graph.rs index 60d95074..eec24d55 100644 --- a/mona_core/src/attribute/complicated_attribute_graph.rs +++ b/mona_core/src/attribute/complicated_attribute_graph.rs @@ -191,11 +191,16 @@ impl ComplicatedAttributeGraph { } pub fn get_critical_composition(&self, element: Element, skill: SkillType) -> EntryType { - self.get_composition_merge(&vec![ + let skill_type_critical_name = AttributeName::critical_rate_name_by_skill_type(skill); + let mut names = vec![ AttributeName::CriticalBase, AttributeName::CriticalAttacking, AttributeName::critical_rate_name_by_element(element), - AttributeName::critical_rate_name_by_skill_type(skill) - ]) + ]; + if let Some(name) = skill_type_critical_name { + names.push(name); + } + + self.get_composition_merge(&names) } } \ No newline at end of file diff --git a/mona_core/src/character/character_name.rs b/mona_core/src/character/character_name.rs index 71a7e0d2..76bb60c9 100644 --- a/mona_core/src/character/character_name.rs +++ b/mona_core/src/character/character_name.rs @@ -111,4 +111,5 @@ pub enum CharacterName { Clorinde, Sigewinne, Sethos, + Emilie, } \ No newline at end of file diff --git a/mona_core/src/character/characters/dendro/emilie.rs b/mona_core/src/character/characters/dendro/emilie.rs new file mode 100644 index 00000000..dcb5e6bf --- /dev/null +++ b/mona_core/src/character/characters/dendro/emilie.rs @@ -0,0 +1,250 @@ +use crate::{attribute::Attribute, character::macros::damage_enum, common::ChangeAttribute, attribute::AttributeCommon}; +use crate::attribute::AttributeName; +use crate::character::{CharacterConfig, CharacterName, CharacterStaticData}; +use crate::character::character_common_data::CharacterCommonData; +use crate::character::character_sub_stat::CharacterSubStatFamily; +use crate::character::characters::kirara::KiraraDamageEnum; +use crate::character::characters::kirara::KiraraDamageEnum::{Plunging1, Plunging2, Plunging3}; +use crate::character::macros::{damage_ratio, skill_map, skill_type}; +use crate::character::skill_config::CharacterSkillConfig; +use crate::character::traits::{CharacterSkillMap, CharacterTrait}; +use crate::common::{Element, SkillType, WeaponType}; +use crate::common::i18n::{charged_dmg, hit_n_dmg, plunging_dmg}; +use crate::common::i18n::locale; +use crate::common::item_config_type::{ItemConfig, ItemConfigType}; +use crate::damage::damage_builder::DamageBuilder; +use crate::damage::DamageContext; +use crate::target_functions::TargetFunction; +use crate::team::TeamQuantization; +use crate::weapon::weapon_common_data::WeaponCommonData; +use crate::character::traits::{CharacterSkillMapItem}; + +pub struct EmilieSkillType { + pub normal_dmg1: [f64; 15], + pub normal_dmg2: [f64; 15], + pub normal_dmg3: [f64; 15], + pub normal_dmg4: [f64; 15], + pub charged_dmg: [f64; 15], + pub plunging_dmg1: [f64; 15], + pub plunging_dmg2: [f64; 15], + pub plunging_dmg3: [f64; 15], + + pub e_dmg1: [f64; 15], + pub e_dmg2: [f64; 15], + pub e_dmg3: [f64; 15], + pub e_dmg4: [f64; 15], + + pub q_dmg1: [f64; 15], +} + +pub const EMILIE_SKILL: EmilieSkillType = EmilieSkillType { + normal_dmg1: [0.4856, 0.5251, 0.5647, 0.6211, 0.6607, 0.7058, 0.7679, 0.8301, 0.8922, 0.9599, 1.0277, 1.0954, 1.1632, 1.231, 1.2987], + normal_dmg2: [0.449, 0.4855, 0.522, 0.5742, 0.6108, 0.6526, 0.71, 0.7674, 0.8248, 0.8875, 0.9501, 1.0128, 1.0754, 1.138, 1.2007], + normal_dmg3: [0.593, 0.6413, 0.6895, 0.7585, 0.8068, 0.8619, 0.9378, 1.0136, 1.0895, 1.1722, 1.255, 1.3377, 1.4205, 1.5032, 1.5859], + normal_dmg4: [0.751, 0.8122, 0.8733, 0.9606, 1.0217, 1.0916, 1.1877, 1.2837, 1.3798, 1.4846, 1.5894, 1.6942, 1.799, 1.9038, 2.0086], + charged_dmg: [0.9133, 0.9877, 1.062, 1.1682, 1.2425, 1.3275, 1.4443, 1.5611, 1.678, 1.8054, 1.9328, 2.0603, 2.1877, 2.3152, 2.4426], + plunging_dmg1: [0.6393, 0.6914, 0.7434, 0.8177, 0.8698, 0.9293, 1.011, 1.0928, 1.1746, 1.2638, 1.353, 1.4422, 1.5314, 1.6206, 1.7098], + plunging_dmg2: [1.2784, 1.3824, 1.4865, 1.6351, 1.7392, 1.8581, 2.0216, 2.1851, 2.3486, 2.527, 2.7054, 2.8838, 3.0622, 3.2405, 3.4189], + plunging_dmg3: [1.5968, 1.7267, 1.8567, 2.0424, 2.1723, 2.3209, 2.5251, 2.7293, 2.9336, 3.1564, 3.3792, 3.602, 3.8248, 4.0476, 4.2704], + e_dmg1: [0.4708, 0.5061, 0.5414, 0.5885, 0.6238, 0.6591, 0.7062, 0.7533, 0.8004, 0.8474, 0.8945, 0.9416, 1.0005, 1.0593, 1.1182], + e_dmg2: [0.396, 0.4257, 0.4554, 0.495, 0.5247, 0.5544, 0.594, 0.6336, 0.6732, 0.7128, 0.7524, 0.792, 0.8415, 0.891, 0.9405], + e_dmg3: [0.84, 0.903, 0.966, 1.05, 1.113, 1.176, 1.26, 1.344, 1.428, 1.512, 1.596, 1.68, 1.785, 1.89, 1.995], + e_dmg4: [0.3852, 0.4141, 0.443, 0.4815, 0.5104, 0.5393, 0.5778, 0.6163, 0.6548, 0.6934, 0.7319, 0.7704, 0.8186, 0.8667, 0.9149], + q_dmg1: [2.172, 2.3349, 2.4978, 2.715, 2.8779, 3.0408, 3.258, 3.4752, 3.6924, 3.9096, 4.1268, 4.344, 4.6155, 4.887, 5.1585], +}; + +damage_enum!( + EmilieDamageEnum + Normal1 + Normal2 + Normal3 + Normal4 + Charged + Plunging1 + Plunging2 + Plunging3 + E1 + E2 + E3 + E4 + Q1 + Talent1 +); + +impl EmilieDamageEnum { + pub fn get_skill_type(&self) -> SkillType { + use EmilieDamageEnum::*; + match *self { + Normal1 | Normal2 | Normal3 | Normal4 => SkillType::NormalAttack, + Charged => SkillType::ChargedAttack, + Plunging1 => SkillType::PlungingAttackInAction, + Plunging2 | Plunging3 => SkillType::PlungingAttackOnGround, + E1 | E2 | E3 | E4 => SkillType::ElementalSkill, + Q1 => SkillType::ElementalBurst, + Talent1 => SkillType::NoneType + } + } + + pub fn get_element(&self, use_c6: bool) -> Element { + use EmilieDamageEnum::*; + if use_c6 { + match *self { + Plunging1 | Plunging2 | Plunging3 => Element::Physical, + _ => Element::Dendro, + } + } else { + match *self { + Normal1 | Normal2 | Normal3 | Normal4 | Charged | Plunging1 | Plunging2 | Plunging3 => Element::Physical, + _ => Element::Dendro, + } + } + } +} + +pub struct Emilie; + +impl CharacterTrait for Emilie { + const STATIC_DATA: CharacterStaticData = CharacterStaticData { + name: CharacterName::Emilie, + internal_name: "Emilie", + name_locale: locale!( + zh_cn: "艾梅莉埃", + en: "Emilie" + ), + element: Element::Dendro, + hp: [1056, 2740, 3646, 5455, 6099, 7016, 7874, 8802, 9445, 10381, 11025, 11971, 12615, 13568], + atk: [26, 68, 90, 135, 151, 173, 194, 217, 233, 256, 272, 295, 311, 335], + def: [57, 147, 196, 294, 328, 378, 424, 474, 508, 559, 593, 644, 679, 730], + sub_stat: CharacterSubStatFamily::CriticalDamage384, + weapon_type: WeaponType::Polearm, + star: 5, + skill_name1: locale!( + zh_cn: "普通攻击·逐影枪术·改", + en: "Normal Attack: Shadow-Hunting Spear (Custom)" + ), + skill_name2: locale!( + zh_cn: "撷萃调香", + en: "Fragrance Extraction" + ), + skill_name3: locale!( + zh_cn: "香氛演绎", + en: "Aromatic Explication" + ), + }; + type SkillType = EmilieSkillType; + const SKILL: Self::SkillType = EMILIE_SKILL; + type DamageEnumType = EmilieDamageEnum; + type RoleEnum = (); + + #[cfg(not(target_family = "wasm"))] + const SKILL_MAP: CharacterSkillMap = CharacterSkillMap { + skill1: skill_map!( + EmilieDamageEnum + Normal1 hit_n_dmg!(1) + Normal2 hit_n_dmg!(2) + Normal3 hit_n_dmg!(3) + Normal4 hit_n_dmg!(4) + Charged charged_dmg!() + Plunging1 plunging_dmg!(1) + Plunging2 plunging_dmg!(2) + Plunging3 plunging_dmg!(3) + ), + skill2: skill_map!( + EmilieDamageEnum + E1 locale!(zh_cn: "技能伤害", en: "Skill DMG") + E2 locale!(zh_cn: "柔灯之匣·一阶攻击伤害", en: "Level 1 Lumidouce Case Attack DMG") + E3 locale!(zh_cn: "柔灯之匣·二阶攻击伤害", en: "Level 2 Lumidouce Case Attack DMG") + E4 locale!(zh_cn: "灵息之刺伤害", en: "Spiritbreath Thorn DMG") + Talent1 locale!(zh_cn: "「清露香氛」", en: "Cleardew Cologne") + ), + skill3: skill_map!( + EmilieDamageEnum + Q1 locale!(zh_cn: "柔灯之匣·三阶攻击伤害", en: "Level 3 Lumidouce Case Attack DMG") + ), + }; + + #[cfg(not(target_family = "wasm"))] + const CONFIG_SKILL: Option<&'static [ItemConfig]> = Some(&[ + ItemConfig { + name: "enemy_burn", + title: locale!( + zh_cn: "敌人处于燃烧状态", + en: "Enemy is Burnt" + ), + config: ItemConfigType::Bool { default: false } + }, + ItemConfig { + name: "use_c6", + title: locale!( + zh_cn: "C6「茉洁香迹」", + en: "C6: Marcotte Sillage" + ), + config: ItemConfigType::Bool { default: false } + } + ]); + + fn damage_internal(context: &DamageContext<'_, D::AttributeType>, s: usize, config: &CharacterSkillConfig, fumo: Option) -> D::Result { + let s: EmilieDamageEnum = num::FromPrimitive::from_usize(s).unwrap(); + let (s1, s2, s3) = context.character_common_data.get_3_skill(); + + let mut builder = D::new(); + use EmilieDamageEnum::*; + + let (enemy_burn, use_c6) = match *config { + CharacterSkillConfig::Emilie { enemy_burn, use_c6 } => (enemy_burn, use_c6), + _ => (false, false) + }; + + let ratio = match s { + Normal1 => EMILIE_SKILL.normal_dmg1[s1], + Normal2 => EMILIE_SKILL.normal_dmg2[s1], + Normal3 => EMILIE_SKILL.normal_dmg3[s1], + Normal4 => EMILIE_SKILL.normal_dmg4[s1], + Charged => EMILIE_SKILL.charged_dmg[s1], + Plunging1 => EMILIE_SKILL.plunging_dmg1[s1], + Plunging2 => EMILIE_SKILL.plunging_dmg2[s1], + Plunging3 => EMILIE_SKILL.plunging_dmg3[s1], + E1 => EMILIE_SKILL.e_dmg1[s2], + E2 => EMILIE_SKILL.e_dmg2[s2], + E3 => EMILIE_SKILL.e_dmg3[s2], + E4 => EMILIE_SKILL.e_dmg4[s2], + Q1 => EMILIE_SKILL.q_dmg1[s3], + Talent1 => 6.0 + }; + builder.add_atk_ratio("技能倍率", ratio); + if context.character_common_data.constellation >= 1 && s == Talent1 { + builder.add_extra_bonus("C1「淡香浸析」", 0.2); + } + let use_c6 = use_c6 && context.character_common_data.constellation >= 6; + + let skill_type = s.get_skill_type(); + let element = s.get_element(use_c6); + + if use_c6 && (skill_type == SkillType::NormalAttack || skill_type == SkillType::ChargedAttack) { + builder.add_atk_ratio("C6「」茉洁香迹", 3.0); + } + + if enemy_burn && context.character_common_data.has_talent2 { + let atk = context.attribute.get_value(AttributeName::ATK); + let bonus = ((atk / 1000.0).floor() * 0.15).min(0.36); + builder.add_extra_bonus("天赋「精馏」", bonus); + } + + builder.damage( + &context.attribute, + &context.enemy, + element, + skill_type, + context.character_common_data.level, + fumo + ) + } + + fn new_effect(common_data: &CharacterCommonData, config: &CharacterConfig) -> Option>> { + None + } + + fn get_target_function_by_role(role_index: usize, team: &TeamQuantization, c: &CharacterCommonData, w: &WeaponCommonData) -> Box { + unimplemented!() + } +} diff --git a/mona_core/src/character/characters/dendro/mod.rs b/mona_core/src/character/characters/dendro/mod.rs index 58abe708..ee7f0a19 100644 --- a/mona_core/src/character/characters/dendro/mod.rs +++ b/mona_core/src/character/characters/dendro/mod.rs @@ -6,6 +6,7 @@ pub mod alhaitham; pub mod kaveh; pub mod baizhu; pub mod kirara; +mod emilie; pub use collei::Collei; pub use tighnari::Tighnari; @@ -15,3 +16,4 @@ pub use alhaitham::Alhaitham; pub use kaveh::Kaveh; pub use baizhu::Baizhu; pub use kirara::Kirara; +pub use emilie::Emilie; diff --git a/mona_core/src/character/skill_config.rs b/mona_core/src/character/skill_config.rs index 82a731cc..929865db 100644 --- a/mona_core/src/character/skill_config.rs +++ b/mona_core/src/character/skill_config.rs @@ -48,5 +48,6 @@ pub enum CharacterSkillConfig { Gaming { pyro: bool }, Arlecchino { bond_of_life: f64 }, Clorinde { bond_of_life: f64 }, + Emilie { enemy_burn: bool, use_c6: bool }, NoConfig, } diff --git a/mona_core/src/common/skill_type.rs b/mona_core/src/common/skill_type.rs index ffe8877b..50d21444 100644 --- a/mona_core/src/common/skill_type.rs +++ b/mona_core/src/common/skill_type.rs @@ -3,6 +3,7 @@ use serde::{Serialize, Deserialize}; #[derive(Serialize, Deserialize)] #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)] pub enum SkillType { + NoneType, NormalAttack, ChargedAttack, PlungingAttackInAction, diff --git a/mona_core/src/damage/complicated_damage_builder.rs b/mona_core/src/damage/complicated_damage_builder.rs index d7d1511f..dc32179b 100644 --- a/mona_core/src/damage/complicated_damage_builder.rs +++ b/mona_core/src/damage/complicated_damage_builder.rs @@ -430,11 +430,14 @@ impl ComplicatedDamageBuilder { } fn get_extra_damage_composition(&self, attribute: &ComplicatedAttributeGraph, element: Element, skill: SkillType) -> EntryType { - let mut comp = attribute.get_composition_merge(&vec![ + let mut names = vec![ AttributeName::ExtraDmgBase, AttributeName::extra_dmg_name_by_element(element), - AttributeName::extra_dmg_name_by_skill_type(skill) - ]); + ]; + if let Some(name) = AttributeName::extra_dmg_name_by_skill_type(skill) { + names.push(name); + } + let mut comp = attribute.get_composition_merge(&names); comp.merge(&self.extra_damage); comp } @@ -490,11 +493,14 @@ impl ComplicatedDamageBuilder { } fn get_critical_damage_composition(&self, attribute: &ComplicatedAttributeGraph, element: Element, skill: SkillType) -> EntryType { - let mut comp = attribute.get_composition_merge(&vec![ + let mut names = vec![ AttributeName::CriticalDamageBase, AttributeName::critical_damage_name_by_element(element), - AttributeName::critical_damage_name_by_skill_name(skill) - ]); + ]; + if let Some(name) = AttributeName::critical_damage_name_by_skill_name(skill) { + names.push(name); + } + let mut comp = attribute.get_composition_merge(&names); comp.merge(&self.extra_critical_damage); comp } @@ -506,11 +512,14 @@ impl ComplicatedDamageBuilder { } fn get_bonus_composition(&self, attribute: &ComplicatedAttributeGraph, element: Element, skill: SkillType) -> EntryType { - let mut comp = attribute.get_composition_merge(&vec![ + let mut names = vec![ AttributeName::BonusBase, AttributeName::bonus_name_by_element(element), - AttributeName::bonus_name_by_skill_type(skill) - ]); + ]; + if let Some(name) = AttributeName::bonus_name_by_skill_type(skill) { + names.push(name); + } + let mut comp = attribute.get_composition_merge(&names); if element != Element::Physical && skill == SkillType::NormalAttack { // todo refactor comp.merge(&attribute.get_attribute_composition(AttributeName::BonusNormalAndElemental)); @@ -528,11 +537,14 @@ impl ComplicatedDamageBuilder { } fn get_atk_ratio_composition(&self, attribute: &ComplicatedAttributeGraph, element: Element, skill: SkillType) -> EntryType { - let mut atk_ratio_comp = attribute.get_composition_merge(&vec![ + let mut names = vec![ AttributeName::ATKRatioBase, AttributeName::atk_ratio_name_by_element(element), - AttributeName::atk_ratio_name_by_skill_type(skill) - ]); + ]; + if let Some(name) = AttributeName::atk_ratio_name_by_skill_type(skill) { + names.push(name) + } + let mut atk_ratio_comp = attribute.get_composition_merge(&names); atk_ratio_comp.merge(&self.ratio_atk); atk_ratio_comp @@ -550,11 +562,14 @@ impl ComplicatedDamageBuilder { } fn get_def_ratio_composition(&self, attribute: &ComplicatedAttributeGraph, element: Element, skill: SkillType) -> EntryType { - let mut def_ratio_comp = attribute.get_composition_merge(&vec![ + let mut names = vec![ AttributeName::DEFRatioBase, AttributeName::def_ratio_name_by_element(element), - AttributeName::def_ratio_name_by_skill_type(skill) - ]); + ]; + if let Some(name) = AttributeName::def_ratio_name_by_skill_type(skill) { + names.push(name); + } + let mut def_ratio_comp = attribute.get_composition_merge(&names); def_ratio_comp.merge(&self.ratio_def); def_ratio_comp @@ -581,11 +596,14 @@ impl ComplicatedDamageBuilder { } fn get_hp_ratio_composition(&self, attribute: &ComplicatedAttributeGraph, element: Element, skill: SkillType) -> EntryType { - let mut hp_ratio_comp = attribute.get_composition_merge(&vec![ + let mut names = vec![ AttributeName::HPRatioBase, AttributeName::hp_ratio_name_by_element(element), - AttributeName::hp_ratio_name_by_skill_type(skill) - ]); + ]; + if let Some(name) = AttributeName::hp_ratio_name_by_skill_type(skill) { + names.push(name) + } + let mut hp_ratio_comp = attribute.get_composition_merge(&names); hp_ratio_comp.merge(&self.ratio_hp); hp_ratio_comp diff --git a/mona_core/src/target_functions/target_function_name.rs b/mona_core/src/target_functions/target_function_name.rs index 3c1f8e61..1992380b 100644 --- a/mona_core/src/target_functions/target_function_name.rs +++ b/mona_core/src/target_functions/target_function_name.rs @@ -101,4 +101,5 @@ pub enum TargetFunctionName { ClorindeDefault, SigewinneDefault, SethosDefault, + EmilieDefault, } diff --git a/mona_core/src/target_functions/target_functions/dendro/emilie_default.rs b/mona_core/src/target_functions/target_functions/dendro/emilie_default.rs new file mode 100644 index 00000000..81e3e57f --- /dev/null +++ b/mona_core/src/target_functions/target_functions/dendro/emilie_default.rs @@ -0,0 +1,72 @@ +use crate::artifacts::Artifact; +use crate::artifacts::effect_config::ArtifactEffectConfig; +use crate::attribute::SimpleAttributeGraph2; +use crate::character::{Character, CharacterName}; +use crate::character::character_common_data::CharacterCommonData; +use crate::character::characters::Emilie; +use crate::character::skill_config::CharacterSkillConfig; +use crate::character::traits::CharacterTrait; +use crate::common::i18n::locale; +use crate::damage::{DamageContext, SimpleDamageBuilder}; +use crate::enemies::Enemy; +use crate::target_functions::target_function::TargetFunctionMetaTrait; +use crate::target_functions::target_function_meta::{TargetFunctionFor, TargetFunctionMeta, TargetFunctionMetaImage}; +use crate::target_functions::target_function_opt_config::TargetFunctionOptConfig; +use crate::target_functions::{TargetFunction, TargetFunctionConfig, TargetFunctionName}; +use crate::team::TeamQuantization; +use crate::weapon::Weapon; +use crate::weapon::weapon_common_data::WeaponCommonData; + +pub struct EmilieDefaultTargetFunction; + +impl TargetFunction for EmilieDefaultTargetFunction { + fn get_target_function_opt_config(&self) -> TargetFunctionOptConfig { + unimplemented!() + } + + fn get_default_artifact_config(&self, team_config: &TeamQuantization) -> ArtifactEffectConfig { + Default::default() + } + + fn target(&self, attribute: &SimpleAttributeGraph2, character: &Character, weapon: &Weapon, artifacts: &[&Artifact], enemy: &Enemy) -> f64 { + let context: DamageContext<'_, SimpleAttributeGraph2> = DamageContext { + character_common_data: &character.common_data, + attribute, + enemy + }; + + type S = ::DamageEnumType; + let damage = Emilie::damage::( + &context, S::E2, + &CharacterSkillConfig::Emilie { + enemy_burn: true, + use_c6: true, + }, + None + ); + + damage.normal.expectation + } +} + +impl TargetFunctionMetaTrait for EmilieDefaultTargetFunction { + #[cfg(not(target_family = "wasm"))] + const META_DATA: TargetFunctionMeta = TargetFunctionMeta { + name: TargetFunctionName::EmilieDefault, + name_locale: locale!( + zh_cn: "艾梅莉埃-「千缕之踪」", + en: "Emilie-A Thousand Scents Traced", + ), + description: locale!( + zh_cn: "最大化E伤害(敌人燃烧)", + en: "Maximize E DMG(Use Talent 2)" + ), + tags: "", + four: TargetFunctionFor::SomeWho(CharacterName::Emilie), + image: TargetFunctionMetaImage::Avatar, + }; + + fn create(character: &CharacterCommonData, weapon: &WeaponCommonData, config: &TargetFunctionConfig) -> Box { + Box::new(EmilieDefaultTargetFunction) + } +} diff --git a/mona_core/src/target_functions/target_functions/dendro/mod.rs b/mona_core/src/target_functions/target_functions/dendro/mod.rs index cf3a549f..171126e7 100644 --- a/mona_core/src/target_functions/target_functions/dendro/mod.rs +++ b/mona_core/src/target_functions/target_functions/dendro/mod.rs @@ -1,7 +1,9 @@ -pub mod tighnari_default; -pub mod nahida_default; -pub mod alhaitham_default; +mod tighnari_default; +mod nahida_default; +mod alhaitham_default; +mod emilie_default; pub use tighnari_default::TighnariDefaultTargetFunction; pub use nahida_default::NahidaDefaultTargetFunction; pub use alhaitham_default::AlhaithamDefaultTargetFunction; +pub use emilie_default::EmilieDefaultTargetFunction; diff --git a/mona_core/src/weapon/weapon_config.rs b/mona_core/src/weapon/weapon_config.rs index 3fc327df..a350e854 100644 --- a/mona_core/src/weapon/weapon_config.rs +++ b/mona_core/src/weapon/weapon_config.rs @@ -76,6 +76,7 @@ pub enum WeaponConfig { BalladOfTheFjords { use_effect: bool }, ProspectorsDrill { stack: f64 }, CrimsonMoonsSemblance { rate1: f64, rate2: f64 }, + LumidouceElegy { stack: f64 }, // Catalyst LostPrayerToTheSacredWinds { stack: f64 }, diff --git a/mona_core/src/weapon/weapon_name.rs b/mona_core/src/weapon/weapon_name.rs index cd0104a7..a45158a0 100644 --- a/mona_core/src/weapon/weapon_name.rs +++ b/mona_core/src/weapon/weapon_name.rs @@ -126,6 +126,7 @@ pub enum WeaponName { ProspectorsDrill, DialoguesOfTheDesertSages, CrimsonMoonsSemblance, + LumidouceElegy, // catalyst LostPrayerToTheSacredWinds, diff --git a/mona_core/src/weapon/weapons/polearms/lumidouce_elegy.rs b/mona_core/src/weapon/weapons/polearms/lumidouce_elegy.rs new file mode 100644 index 00000000..b71727bc --- /dev/null +++ b/mona_core/src/weapon/weapons/polearms/lumidouce_elegy.rs @@ -0,0 +1,63 @@ +use crate::attribute::{Attribute, AttributeCommon, AttributeName}; +use crate::character::character_common_data::CharacterCommonData; +use crate::common::i18n::locale; +use crate::common::item_config_type::ItemConfig; +use crate::common::WeaponType; +use crate::weapon::weapon_common_data::WeaponCommonData; +use crate::weapon::weapon_effect::WeaponEffect; +use crate::weapon::weapon_static_data::WeaponStaticData; +use crate::weapon::weapon_trait::WeaponTrait; +use crate::weapon::{WeaponConfig, WeaponName}; +use crate::weapon::weapon_base_atk::WeaponBaseATKFamily; +use crate::weapon::weapon_sub_stat::WeaponSubStatFamily; + +pub struct LumidouceElegyEffect { + pub stack: f64, +} + +impl WeaponEffect for LumidouceElegyEffect { + fn apply(&self, data: &WeaponCommonData, attribute: &mut A) { + let refine = data.refine as f64; + attribute.add_atk_percentage("柔灯挽歌被动", 0.11 + 0.04 * refine); + attribute.set_value_by(AttributeName::BonusBase, "柔灯挽歌被动", self.stack * (0.13 + 0.05 * refine)); + } +} + +pub struct LumidouceElegy; + +impl WeaponTrait for LumidouceElegy { + const META_DATA: WeaponStaticData = WeaponStaticData { + name: WeaponName::LumidouceElegy, + internal_name: "Pole_Muguet", + weapon_type: WeaponType::Polearm, + weapon_sub_stat: Some(WeaponSubStatFamily::CriticalRate72), + weapon_base: WeaponBaseATKFamily::ATK608, + star: 5, + #[cfg(not(target_family = "wasm"))] + effect: Some(locale!( + zh_cn: "攻击力提升15%-19%-23%-27%-31%;装备者对敌人触发燃烧反应或对处于燃烧状态下的敌人造成草元素伤害后,造成的伤害提高18%-23%-28%-33%-38%。该效果持续8秒,至多叠加2层;叠加至2层或2层的持续时间刷新时,恢复12-13-14-15-16点元素能量,每12秒至多通过这种方式恢复一次元素能量。上述2种效果角色处于队伍后台时也能触发。", + en: "ATK increased by 15%-19%-23%-27%-31%. When the equipping character triggers Burning on an opponent or deals Dendro DMG to Burning opponents, the DMG dealt is increased by 18%-23%-28%-33%-38%. This effect lasts for 8s, max 2 stacks. When 2 stacks are reached or when the duration of the 2nd stack is refreshed, restore 12-13-14-15-16 Energy. Energy can be restored this way once every 12s. The 2 aforementioned effects can be triggered even when the character is off-field." + )), + #[cfg(not(target_family = "wasm"))] + name_locale: locale!( + zh_cn: "柔灯挽歌", + en: "Lumidouce Elegy" + ), + }; + + #[cfg(not(target_family = "wasm"))] + const CONFIG_DATA: Option<&'static [ItemConfig]> = Some(&[ + ItemConfig::STACK02 + ]); + + fn get_effect(character: &CharacterCommonData, config: &WeaponConfig) -> Option>> { + match *config { + WeaponConfig::LumidouceElegy { stack } => { + Some(Box::new(LumidouceElegyEffect { + stack + })) + } + _ => None + } + } +} \ No newline at end of file diff --git a/mona_core/src/weapon/weapons/polearms/mod.rs b/mona_core/src/weapon/weapons/polearms/mod.rs index 74dc86e0..7ab2e937 100644 --- a/mona_core/src/weapon/weapons/polearms/mod.rs +++ b/mona_core/src/weapon/weapons/polearms/mod.rs @@ -29,6 +29,7 @@ pub use rightful_reward::RightfulReward; pub use prospectors_drill::ProspectorsDrill; pub use dialogues_of_the_desert_sages::DialoguesOfTheDesertSages; pub use crimson_moons_semblance::CrimsonMoonsSemblance; +pub use lumidouce_elegy::LumidouceElegy; pub mod engulfing_lightning; pub mod skyward_spine; @@ -61,4 +62,5 @@ pub mod rightful_reward; pub mod prospectors_drill; pub mod dialogues_of_the_desert_sages; pub mod crimson_moons_semblance; +mod lumidouce_elegy; diff --git a/mona_wasm/Cargo.lock b/mona_wasm/Cargo.lock index 14459761..668b0de1 100644 --- a/mona_wasm/Cargo.lock +++ b/mona_wasm/Cargo.lock @@ -463,6 +463,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + [[package]] name = "opaque-debug" version = "0.2.3" @@ -765,9 +771,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.78" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "serde", @@ -777,24 +783,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.78" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", - "syn 1.0.84", + "syn 2.0.60", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.78" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -802,22 +808,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.78" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.84", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.78" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" diff --git a/mona_wasm/Cargo.toml b/mona_wasm/Cargo.toml index 2ae4f526..8acb3f91 100644 --- a/mona_wasm/Cargo.toml +++ b/mona_wasm/Cargo.toml @@ -20,7 +20,7 @@ strip = true [dependencies] mona = { path = "../mona_core" } mona_dsl = { path = "../mona_dsl" } -wasm-bindgen = { version = "0.2.63", features = ["serde-serialize"] } +wasm-bindgen = { version = "0.2.92", features = ["serde-serialize"] } lazy_static = "1.4.0" rand = "0.8.4" serde = { version = "1.0.133", features = ["derive"] } diff --git a/package.json b/package.json index 48ed5dc3..5558b6e0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "genshin_artifacts", - "version": "5.24.0", + "version": "5.25.0", "private": true, "scripts": { "serve": "cross-env ENV_FILE=.env.development.yaml vue-cli-service serve", diff --git a/src/images/characters/Emilie_splash.png b/src/images/characters/Emilie_splash.png new file mode 100644 index 00000000..724125cf Binary files /dev/null and b/src/images/characters/Emilie_splash.png differ diff --git a/src/pages/NewArtifactPlanPage/NewArtifactPlanPage.vue b/src/pages/NewArtifactPlanPage/NewArtifactPlanPage.vue index bbeea6b7..8e4edc72 100644 --- a/src/pages/NewArtifactPlanPage/NewArtifactPlanPage.vue +++ b/src/pages/NewArtifactPlanPage/NewArtifactPlanPage.vue @@ -1480,15 +1480,23 @@ function getArtifactsToBeCalculated(): IArtifactWasm[] { function handleOptimizeArtifact() { const start = new Date() + + const optimizeInterface = getOptimizeArtifactWasmInterface() + const artifacts = getArtifactsToBeCalculated() + + if (artifacts.length === 0) { + ElMessage.error({ + message: "没有圣遗物,请先添加圣遗物" + }) + return + } + const loading = ElLoading.service({ lock: true, fullscreen: true, text: "莫娜占卜中" }) - const optimizeInterface = getOptimizeArtifactWasmInterface() - const artifacts = getArtifactsToBeCalculated() - wasmSingleOptimize(optimizeInterface, artifacts).then(results => { const end = new Date() // @ts-ignore