This commit is contained in:
2026-04-28 19:36:39 +08:00
parent a9febe7678
commit f0471a4f8d
206 changed files with 18456 additions and 10133 deletions

View File

@@ -10,18 +10,25 @@ use crate::{
///
/// 当前仍然保持旧快照态结算口径,不引入 HTTP / AppState / 持久化边界。
pub(crate) struct ForgeRequirementDefinition {
pub(crate) id: &'static str,
pub(crate) label: &'static str,
pub(crate) quantity: i32,
pub(crate) matcher: ForgeRequirementMatcher,
}
#[derive(Clone, Copy)]
pub(crate) enum ForgeRequirementMatcher {
Named(&'static str),
TaggedMaterial(&'static str),
AnyMaterial,
}
pub(crate) struct ForgeRecipeDefinition {
pub(crate) id: &'static str,
pub(crate) name: &'static str,
pub(crate) kind: &'static str,
pub(crate) description: &'static str,
pub(crate) result_label: &'static str,
pub(crate) currency_cost: i32,
pub(crate) requirements: Vec<ForgeRequirementDefinition>,
}
@@ -32,33 +39,134 @@ pub(crate) struct ReforgeCostDefinition {
}
pub(crate) fn forge_recipe_definition(recipe_id: &str) -> Option<ForgeRecipeDefinition> {
match recipe_id {
"synthesis-refined-ingot" => Some(ForgeRecipeDefinition {
forge_recipe_definitions()
.into_iter()
.find(|recipe| recipe.id == recipe_id)
}
pub(crate) fn forge_recipe_definitions() -> Vec<ForgeRecipeDefinition> {
vec![
ForgeRecipeDefinition {
id: "synthesis-refined-ingot",
name: "压炼锭材",
kind: "synthesis",
description: "把零散残片和基础材料压成稳定可用的金属锭材。",
result_label: "精炼锭材",
currency_cost: 18,
requirements: vec![ForgeRequirementDefinition {
id: "material:any",
label: "任意材料",
quantity: 3,
matcher: ForgeRequirementMatcher::AnyMaterial,
}],
}),
"forge-duelist-blade" => Some(ForgeRecipeDefinition {
},
ForgeRecipeDefinition {
id: "synthesis-condensed-silk",
name: "凝光纺丝",
kind: "synthesis",
description: "用灵性残材与粉末纺出适合饰品锻造的凝光纱。",
result_label: "凝光纱",
currency_cost: 24,
requirements: vec![
ForgeRequirementDefinition {
id: "material:any",
label: "任意材料",
quantity: 2,
matcher: ForgeRequirementMatcher::AnyMaterial,
},
ForgeRequirementDefinition {
id: "tag:mana",
label: "含法力标签材料",
quantity: 1,
matcher: ForgeRequirementMatcher::TaggedMaterial("mana"),
},
],
},
ForgeRecipeDefinition {
id: "forge-duelist-blade",
name: "锻造 百炼追风剑",
kind: "forge",
description: "围绕快剑、突进、追击构筑的轻灵主武器。",
result_label: "百炼追风剑",
currency_cost: 72,
requirements: vec![
ForgeRequirementDefinition {
id: "name:精炼锭材",
label: "精炼锭材",
quantity: 2,
matcher: ForgeRequirementMatcher::Named("精炼锭材"),
},
ForgeRequirementDefinition {
id: "name:快剑精粹",
label: "快剑精粹",
quantity: 1,
matcher: ForgeRequirementMatcher::Named("快剑精粹"),
},
ForgeRequirementDefinition {
id: "name:突进精粹",
label: "突进精粹",
quantity: 1,
matcher: ForgeRequirementMatcher::Named("突进精粹"),
},
],
}),
_ => None,
}
},
ForgeRecipeDefinition {
id: "forge-ward-armor",
name: "锻造 镇岳护甲",
kind: "forge",
description: "面向前排承压的护甲,适合守御与护体构筑。",
result_label: "镇岳护甲",
currency_cost: 78,
requirements: vec![
ForgeRequirementDefinition {
id: "name:精炼锭材",
label: "精炼锭材",
quantity: 2,
matcher: ForgeRequirementMatcher::Named("精炼锭材"),
},
ForgeRequirementDefinition {
id: "name:守御精粹",
label: "守御精粹",
quantity: 1,
matcher: ForgeRequirementMatcher::Named("守御精粹"),
},
ForgeRequirementDefinition {
id: "name:护体精粹",
label: "护体精粹",
quantity: 1,
matcher: ForgeRequirementMatcher::Named("护体精粹"),
},
],
},
ForgeRecipeDefinition {
id: "forge-thunder-relic",
name: "锻造 雷纹灵坠",
kind: "forge",
description: "为法修、雷法、过载 build 提供资源与爆发补强。",
result_label: "雷纹灵坠",
currency_cost: 88,
requirements: vec![
ForgeRequirementDefinition {
id: "name:凝光纱",
label: "凝光纱",
quantity: 2,
matcher: ForgeRequirementMatcher::Named("凝光纱"),
},
ForgeRequirementDefinition {
id: "name:法力精粹",
label: "法力精粹",
quantity: 1,
matcher: ForgeRequirementMatcher::Named("法力精粹"),
},
ForgeRequirementDefinition {
id: "name:雷法精粹",
label: "雷法精粹",
quantity: 1,
matcher: ForgeRequirementMatcher::Named("雷法精粹"),
},
],
},
]
}
pub(crate) fn reforge_cost_definition(slot_id: Option<&str>) -> ReforgeCostDefinition {
@@ -66,6 +174,8 @@ pub(crate) fn reforge_cost_definition(slot_id: Option<&str>) -> ReforgeCostDefin
return ReforgeCostDefinition {
currency_cost: 52,
requirements: vec![ForgeRequirementDefinition {
id: "name:凝光纱",
label: "凝光纱",
quantity: 1,
matcher: ForgeRequirementMatcher::Named("凝光纱"),
}],
@@ -74,6 +184,8 @@ pub(crate) fn reforge_cost_definition(slot_id: Option<&str>) -> ReforgeCostDefin
ReforgeCostDefinition {
currency_cost: 46,
requirements: vec![ForgeRequirementDefinition {
id: "name:精炼锭材",
label: "精炼锭材",
quantity: 1,
matcher: ForgeRequirementMatcher::Named("精炼锭材"),
}],
@@ -85,17 +197,28 @@ fn forge_requirement_matches(item: &Value, requirement: &ForgeRequirementDefinit
ForgeRequirementMatcher::Named(name) => {
read_optional_string_field(item, "name").as_deref() == Some(name)
}
ForgeRequirementMatcher::AnyMaterial => {
read_array_field(item, "tags")
.into_iter()
.filter_map(Value::as_str)
.any(|tag| tag == "material")
|| read_optional_string_field(item, "category")
.is_some_and(|category| category.contains("材料"))
ForgeRequirementMatcher::TaggedMaterial(tag) => {
is_material_item(item)
&& read_array_field(item, "tags")
.into_iter()
.filter_map(Value::as_str)
.any(|item_tag| forge_tag_matches(item_tag, tag))
}
ForgeRequirementMatcher::AnyMaterial => is_material_item(item),
}
}
pub(crate) fn count_matching_forge_requirement(
inventory: &[Value],
requirement: &ForgeRequirementDefinition,
) -> i32 {
inventory
.iter()
.filter(|item| forge_requirement_matches(item, requirement))
.map(|item| read_i32_field(item, "quantity").unwrap_or(0).max(0))
.sum()
}
pub(crate) fn apply_forge_requirements_if_possible(
inventory: &[Value],
requirements: &[ForgeRequirementDefinition],
@@ -125,6 +248,19 @@ pub(crate) fn apply_forge_requirements_if_possible(
Some(next_inventory)
}
fn is_material_item(item: &Value) -> bool {
read_array_field(item, "tags")
.into_iter()
.filter_map(Value::as_str)
.any(|tag| tag == "material")
|| read_optional_string_field(item, "category")
.is_some_and(|category| category.contains("材料"))
}
fn forge_tag_matches(item_tag: &str, expected_tag: &str) -> bool {
item_tag == expected_tag || (expected_tag == "mana" && item_tag == "法力")
}
pub fn build_runtime_material_item(
game_state: &Value,
name: &str,
@@ -196,6 +332,9 @@ pub(crate) fn build_forge_recipe_result_item(
"synthesis-refined-ingot" => {
build_runtime_material_item(game_state, "精炼锭材", 1, &["工巧", "守御"], "rare")
}
"synthesis-condensed-silk" => {
build_runtime_material_item(game_state, "凝光纱", 1, &["工巧", "法力"], "rare")
}
"forge-duelist-blade" => build_runtime_equipment_item(
game_state,
"百炼追风剑",
@@ -210,6 +349,38 @@ pub(crate) fn build_forge_recipe_result_item(
"outgoingDamageBonus": 0.20
}),
),
"forge-ward-armor" => build_runtime_equipment_item(
game_state,
"镇岳护甲",
"armor",
"epic",
"厚重但稳定的护甲套件,适合顶住正面压力后再伺机反打。",
"守御",
&["守御", "护体", "先锋"],
&["守御", "护体", "先锋"],
json!({
"maxHpBonus": 56,
"maxManaBonus": 8,
"outgoingDamageBonus": 0.08,
"incomingDamageMultiplier": 0.84
}),
),
"forge-thunder-relic" => build_runtime_equipment_item(
game_state,
"雷纹灵坠",
"relic",
"epic",
"内封雷纹与灵引回路的饰品,能在短窗口内快速放大法术节奏。",
"法修",
&["法修", "雷法", "过载"],
&["法修", "雷法", "过载"],
json!({
"maxHpBonus": 8,
"maxManaBonus": 42,
"outgoingDamageBonus": 0.14,
"incomingDamageMultiplier": 0.92
}),
),
_ => build_runtime_material_item(game_state, "临时锻造产物", 1, &["工巧"], "common"),
}
}