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, i18n::Translate)]
45pub struct TalentTemplate {
46    #[schemars(schema_with = "id_schema")]
47    pub id: TalentId,
48
49    #[schemars(title = "Название")]
50    #[translate]
51    pub name: i18n::I18nString,
52
53    #[schemars(title = "Описание")]
54    #[translate]
55    pub description: i18n::I18nString,
56
57    #[schemars(
58        title = "Скрипт, возвращающий значения для подстановки в описание",
59        schema_with = "option_script_schema"
60    )]
61    pub description_values_script: Option<String>,
62
63    #[schemars(title = "URL картинки", schema_with = "webp_url_schema")]
64    pub icon_url: String,
65
66    #[schemars(title = "Иконка", schema_with = "asset_talent_icon_schema")]
67    pub icon_path: String,
68
69    #[schemars(title = "Уровни таланта")]
70    pub levels: Vec<TalentLevel>,
71
72    #[schemars(title = "Условие разблокировки")]
73    pub unlock_condition: TalentUnlockCondition,
74
75    #[schemars(title = "Позиция в дереве (для UI)")]
76    pub position: TalentPosition,
77}
78
79/// Уровень таланта (у каждого таланта 1-5 уровней)
80#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, Tsify)]
81pub struct TalentLevel {
82    #[schemars(title = "Номер уровня (1-based)")]
83    pub level: i64,
84
85    #[schemars(title = "Стоимость изучения этого уровня")]
86    pub cost: CurrencyUnit,
87
88    #[schemars(title = "Время изучения в секундах")]
89    pub duration_sec: u64,
90
91    /// Бонусы, применяемые к атрибутам сущности (HP, урон, защита и т.д.)
92    #[schemars(title = "Бонусы атрибутов")]
93    pub attribute_bonuses: Vec<TalentAttributeBonus>,
94
95    /// Модификаторы, обрабатываемые бэкендом напрямую (не через атрибуты и не через скрипты)
96    #[schemars(title = "Бэкенд-модификаторы")]
97    pub backend_modifiers: Vec<TalentBackendModifier>,
98}
99
100/// Бонус атрибута сущности от таланта (плоское значение)
101#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, Tsify)]
102pub struct TalentAttributeBonus {
103    #[schemars(title = "Id атрибута", schema_with = "attribute_link_id_schema")]
104    pub attribute_id: AttributeId,
105
106    #[schemars(title = "Значение (плоское)")]
107    pub value: i64,
108}
109
110/// Модификаторы, которые бэкенд применяет явно в своей логике.
111/// Каждый вариант соответствует конкретному месту в бэкенд-коде.
112#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, Tsify)]
113pub enum TalentBackendModifier {
114    #[schemars(title = "Ускорение исследования талантов (%)")]
115    TalentResearchSpeedPercent(f64),
116}
117
118/// Условие разблокировки таланта
119#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, Tsify)]
120pub struct TalentUnlockCondition {
121    /// Список талантов, которые должны быть полностью изучены (пустой = нет требований)
122    #[schemars(
123        title = "Id требуемых талантов",
124        schema_with = "talent_link_id_array_schema"
125    )]
126    pub required_talents: Vec<TalentId>,
127
128    /// Минимальное суммарное количество вложенных очков талантов (0 = нет требований)
129    #[schemars(title = "Необходимое количество вложенных очков талантов")]
130    pub required_points: i64,
131}
132
133/// Позиция таланта в дереве (для отрисовки на клиенте)
134#[derive(Clone, Debug, Deserialize, Serialize, JsonSchema, Tsify)]
135pub struct TalentPosition {
136    #[schemars(title = "Колонка")]
137    pub col: i64,
138
139    #[schemars(title = "Строка")]
140    pub row: i64,
141}