essences/
items.rs

1use crate::prelude::*;
2use chrono::{DateTime, Utc};
3use enum_iterator::Sequence;
4use strum_macros::{Display, EnumIter, EnumString};
5
6use crate::class::ClassId;
7use crate::currency::CurrencyUnit;
8use crate::skins::SkinId;
9
10#[declare]
11pub type AttributeId = Uuid;
12
13#[derive(PartialEq, Eq, Default, Hash, Debug, Clone, Deserialize, Serialize, Tsify, JsonSchema)]
14pub struct Attribute {
15    #[schemars(schema_with = "id_schema")]
16    pub id: AttributeId,
17
18    #[schemars(title = "Название атрибута")]
19    pub name: i18n::I18nString,
20
21    #[schemars(title = "Префикс аттрибута")]
22    pub prefix: Option<i18n::I18nString>,
23
24    #[schemars(title = "Суффикс атрибута")]
25    pub suffix: Option<i18n::I18nString>,
26
27    #[schemars(title = "Код атрибута")]
28    pub code: String,
29
30    #[schemars(title = "Иконка аттрибута", schema_with = "webp_url_schema")]
31    pub icon: String,
32
33    #[schemars(title = "Иконка", schema_with = "asset_attribute_icon_schema")]
34    pub icon_path: String,
35
36    #[schemars(title = "Технический идентификатор", range(min = 0, max = 63))]
37    pub db_code: u8,
38
39    #[schemars(title = "Делитель значения аттрибута")]
40    pub denominator: Option<i64>,
41
42    #[schemars(title = "Является ли значение процентом")]
43    pub is_percent: bool,
44
45    #[schemars(
46        title = "Нативная функция вычисления значения",
47        description = "Имя нативной функции категории item_attribute, вычисляющей значение атрибута.",
48        schema_with = "item_attribute_ref_schema"
49    )]
50    #[serde(default)]
51    pub calculation_behavior: Option<String>,
52
53    #[schemars(
54        title = "Приоритет атрибута",
55        description = "Приоритет атрибута, чем меньше значение - тем выше приоритет"
56    )]
57    pub order: i64,
58
59    #[schemars(title = "Показывать ли атрибут в ui")]
60    pub is_ui_visible: bool,
61
62    #[schemars(title = "Описание аттрибута")]
63    pub description: i18n::I18nString,
64
65    #[schemars(
66        title = "Базовое значение атрибута",
67        description = "Стартовое значение стата до бонусов (например received_damage = 10000 = 100%). \
68            Применяется в get_entity_stat. null = нет базового значения."
69    )]
70    #[serde(default)]
71    pub base_value: Option<i64>,
72}
73
74#[derive(
75    Debug,
76    Clone,
77    Copy,
78    EnumString,
79    Sequence,
80    Display,
81    Deserialize,
82    Serialize,
83    Hash,
84    Eq,
85    PartialEq,
86    EnumIter,
87    Default,
88    JsonSchema,
89    Tsify,
90)]
91#[tsify(namespace)]
92pub enum ItemType {
93    #[default]
94    Weapon,
95    Torso,
96    Head,
97    Legs,
98    Shoulders,
99    Boots,
100    Gloves,
101    Waist,
102    Neck,
103    Ring,
104    Artifact,
105}
106
107#[declare]
108pub type ItemRarityId = Uuid;
109
110#[derive(Default, PartialEq, Eq, Hash, Debug, Clone, Serialize, Deserialize, Tsify, JsonSchema)]
111pub struct ItemRarity {
112    #[schemars(schema_with = "id_schema")]
113    pub id: ItemRarityId,
114    #[schemars(title = "Код редкости (числовой тир, для генерации оппонентов)")]
115    #[serde(default)]
116    pub code: i64,
117    #[schemars(title = "Название редкости")]
118    pub name: i18n::I18nString,
119    #[schemars(title = "Цвет редкости текста", schema_with = "color_schema")]
120    pub text_color: String,
121    #[schemars(title = "URL картинки редкости", schema_with = "webp_url_schema")]
122    pub rarity_icon: String,
123    #[schemars(title = "Картинка", schema_with = "asset_item_rarity_icon_schema")]
124    pub rarity_icon_path: String,
125    #[schemars(
126        title = "URL картинки ленточки под айтемом",
127        schema_with = "webp_url_schema"
128    )]
129    pub ribbon_icon: String,
130    #[schemars(
131        title = "Лента-подложка",
132        schema_with = "asset_item_ribbon_icon_schema"
133    )]
134    pub ribbon_icon_path: String,
135    #[schemars(
136        title = "Приоритет редкости",
137        description = "Приоритет редкости, чем меньше значение - тем выше приоритет"
138    )]
139    pub order: i64,
140
141    #[schemars(
142        title = "Качество редкости (q)",
143        description = "Множитель силы предметов этой редкости (item_rarity_q). Используется в balance::eff_item."
144    )]
145    #[serde(default)]
146    pub q: i64,
147}
148
149#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema, Tsify)]
150pub struct ItemAttributeSettings {
151    #[schemars(title = "Количество опциональных атрибутов у элемента")]
152    pub optional_attributes_count: u64,
153
154    #[schemars(
155        title = "Идентификаторы опциональных атрибутов",
156        schema_with = "attribute_link_id_array_schema"
157    )]
158    pub optional_attributes_ids: Vec<AttributeId>,
159}
160
161#[declare]
162pub type ItemTemplateId = Uuid;
163
164#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema, Tsify)]
165pub struct ItemTemplate {
166    #[schemars(schema_with = "id_schema")]
167    pub id: ItemTemplateId,
168
169    #[schemars(title = "Название предмета")]
170    pub name: i18n::I18nString,
171
172    #[schemars(title = "URL картинки", schema_with = "webp_url_schema")]
173    pub icon_url: String,
174
175    #[schemars(title = "Иконка", schema_with = "asset_item_icon_schema")]
176    pub icon_path: String,
177
178    #[schemars(title = "Тип предмета")]
179    pub item_type: ItemType,
180
181    #[schemars(title = "Id редкости", schema_with = "item_rarity_link_id_schema")]
182    pub rarity_id: ItemRarityId,
183
184    #[schemars(title = "Настройки атрибутов для предмета")]
185    pub attributes_settings: ItemAttributeSettings,
186
187    #[schemars(title = "Id скина", schema_with = "option_skin_link_id_schema")]
188    pub skin_id: Option<SkinId>,
189
190    #[schemars(title = "Исключить из выдачи мимика")]
191    pub exclude_from_mimic: bool,
192
193    #[schemars(
194        title = "Требуемый класс",
195        description = "Если задан, предмет может быть получен только игроком с этим классом"
196    )]
197    pub required_class: Option<ClassId>,
198
199    #[schemars(
200        title = "Фиксированная сила предмета",
201        description = "Если задано, заменяет случайный разброс силы (item_fixed_power) в balance::attr_spread_for_item."
202    )]
203    #[serde(default)]
204    pub fixed_power: Option<f64>,
205
206    #[schemars(
207        title = "Код предмета для мимика",
208        description = "Если задан, квест может выдать именно этот предмет из сундука: SetCustomValue(next_mimic_item_code, <код>) у персонажа резолвится в этот шаблон через content::get_item_by_code (item_id_by_mimic_code)."
209    )]
210    #[serde(default)]
211    pub next_mimic_item_code: Option<i64>,
212}
213
214#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq, Hash, JsonSchema, Tsify)]
215pub struct ItemAttribute {
216    pub attr_id: AttributeId,
217    pub value: i32,
218}
219
220#[derive(Debug, PartialEq, Eq, Deserialize, Serialize, Clone, Default, Hash, JsonSchema, Tsify)]
221#[tsify(from_wasm_abi)]
222pub struct Item {
223    pub id: Uuid,
224    pub item_template_id: ItemTemplateId,
225    pub item_type: ItemType,
226    pub rarity: ItemRarity,
227    pub level: i64,
228    pub name: i18n::I18nString,
229    pub icon_url: String,
230    pub icon_path: String,
231    pub is_equipped: bool,
232    pub price: Vec<CurrencyUnit>,
233    pub experience: i64,
234    pub attributes: Vec<ItemAttribute>,
235
236    /// Small symmetric power variance applied at roll time (seeded RNG, symmetric
237    /// around 0). Stored and loaded from the `inventories.power_bonus` column.
238    /// Existing items loaded without the column default to 0 (no jitter) via the
239    /// `DEFAULT 0` migration. The jitter is added as a direct additive to the
240    /// computed `character_power` / `item_power` so it affects both the displayed
241    /// Combat-Power and the auto-equip comparison — two items from the same
242    /// template at the same level will show different power if their jitter differs.
243    pub power_bonus: i32,
244
245    /// Срок истечения временного предмета; `None` — постоянный. Истёкший
246    /// удаляется функцией `sweep_expired_items`.
247    pub expires_at: Option<DateTime<Utc>>,
248}