essences/
talent_tree.rs

1use crate::prelude::*;
2
3use crate::currency::{CurrencyId, CurrencyUnit};
4use crate::items::AttributeId;
5use std::collections::BTreeMap;
6
7#[declare]
8pub type TalentId = Uuid;
9
10#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Tsify)]
11pub struct TalentLevelsMap(pub BTreeMap<TalentId, i64>);
12
13impl TalentLevelsMap {
14    pub fn get(&self, id: &TalentId) -> Option<&i64> {
15        self.0.get(id)
16    }
17
18    pub fn insert(&mut self, id: TalentId, level: i64) {
19        self.0.insert(id, level);
20    }
21
22    pub fn values(&self) -> impl Iterator<Item = &i64> {
23        self.0.values()
24    }
25}
26
27/// Настройки дерева талантов
28#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, Tsify)]
29pub struct TalentTreeSettings {
30    #[schemars(title = "Сколько секунд изучения скипает один таймскип билетик")]
31    pub time_skip_ticket_skips_sec: u64,
32
33    #[schemars(
34        title = "Id валюты для скипа изучения талантов (брюли)",
35        schema_with = "currency_link_id_schema"
36    )]
37    pub skip_currency_id: CurrencyId,
38
39    #[schemars(title = "Сколько секунд изучения скипает одна единица валюты")]
40    pub skip_currency_skips_sec: u64,
41}
42
43/// Шаблон таланта
44#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, Tsify)]
45pub struct TalentTemplate {
46    #[schemars(schema_with = "id_schema")]
47    pub id: TalentId,
48
49    #[schemars(title = "Название")]
50    pub name: i18n::I18nString,
51
52    #[schemars(title = "Описание")]
53    pub description: i18n::I18nString,
54
55    #[schemars(
56        title = "Скрипт, возвращающий значения для подстановки в описание",
57        schema_with = "option_script_schema"
58    )]
59    pub description_values_script: Option<String>,
60
61    #[schemars(title = "URL картинки", schema_with = "webp_url_schema")]
62    pub icon_url: String,
63
64    #[schemars(title = "Иконка", schema_with = "asset_talent_icon_schema")]
65    pub icon_path: String,
66
67    #[schemars(title = "Уровни таланта")]
68    pub levels: Vec<TalentLevel>,
69
70    #[schemars(title = "Условие разблокировки")]
71    pub unlock_condition: TalentUnlockCondition,
72
73    #[schemars(title = "Позиция в дереве (для UI)")]
74    pub position: TalentPosition,
75}
76
77/// Уровень таланта (у каждого таланта 1-5 уровней)
78#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, Tsify)]
79pub struct TalentLevel {
80    #[schemars(title = "Номер уровня (1-based)")]
81    pub level: i64,
82
83    #[schemars(title = "Стоимость изучения этого уровня")]
84    pub cost: CurrencyUnit,
85
86    #[schemars(title = "Время изучения в секундах")]
87    pub duration_sec: u64,
88
89    /// Бонусы, применяемые к атрибутам сущности (HP, урон, защита и т.д.)
90    #[schemars(title = "Бонусы атрибутов")]
91    pub attribute_bonuses: Vec<TalentAttributeBonus>,
92
93    /// Модификаторы, обрабатываемые бэкендом напрямую (не через атрибуты и не через скрипты)
94    #[schemars(title = "Бэкенд-модификаторы")]
95    pub backend_modifiers: Vec<TalentBackendModifier>,
96}
97
98/// Бонус атрибута сущности от таланта (плоское значение)
99#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, Tsify)]
100pub struct TalentAttributeBonus {
101    #[schemars(title = "Id атрибута", schema_with = "attribute_link_id_schema")]
102    pub attribute_id: AttributeId,
103
104    #[schemars(title = "Значение (плоское)")]
105    pub value: i64,
106}
107
108/// Модификаторы, которые бэкенд применяет явно в своей логике.
109/// Каждый вариант соответствует конкретному месту в бэкенд-коде.
110#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, Tsify)]
111pub enum TalentBackendModifier {
112    #[schemars(title = "Ускорение исследования талантов (%)")]
113    TalentResearchSpeedPercent(f64),
114}
115
116/// Условие разблокировки таланта
117#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, Tsify)]
118pub struct TalentUnlockCondition {
119    /// Список талантов, которые должны быть полностью изучены (пустой = нет требований)
120    #[schemars(
121        title = "Id требуемых талантов",
122        schema_with = "talent_link_id_array_schema"
123    )]
124    pub required_talents: Vec<TalentId>,
125
126    /// Минимальное суммарное количество вложенных очков талантов (0 = нет требований)
127    #[schemars(title = "Необходимое количество вложенных очков талантов")]
128    pub required_points: i64,
129}
130
131/// Позиция таланта в дереве (для отрисовки на клиенте)
132#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, Tsify)]
133pub struct TalentPosition {
134    #[schemars(title = "Колонка")]
135    pub col: i64,
136
137    #[schemars(title = "Строка")]
138    pub row: i64,
139}