1use crate::prelude::*;
2use event_system::script::types::ESCurrencyUnit;
3
4#[declare]
5pub type CurrencyId = uuid::Uuid;
6
7#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Tsify)]
8#[tsify(from_wasm_abi, into_wasm_abi)]
9pub enum CurrencySource {
10 EntityDeath,
11 ItemSell,
12 AutoItemSell,
13 QuestClaim,
14 QuestsTrackReward,
15 VassalTaskCompletion,
16 ReferralLvlUp,
17 ReferralDailyReward,
18 GiftClaim,
19 ArenaTicketBuy,
20 ClaimVassalReward,
21 ClaimSuzerainReward,
22 ArenaMatchmakingRefresh,
23 GachaLevelUp,
24 PetCaseLevelUp,
25 BundleClaim,
26 AdReward,
27 Cheat,
28}
29
30#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Tsify)]
31#[tsify(from_wasm_abi, into_wasm_abi)]
32pub enum CurrencyConsumer {
33 AbilityCaseOpen,
34 AbilityCaseSlotUpgrade,
35 ItemCaseOpen,
36 GiftSend,
37 DungeonRaid,
38 DungeonFightEnd,
39 ClassChange,
40 OfferBuy,
41 ItemCaseUpgrade,
42 CaseUpgradeSpeedUp,
43 CaseUpgradeSkip,
44 ArenaFight,
45 ArenaMatchmakingRefresh,
46 ArenaTicketBuy,
47 SkinBuy,
48 AfkInstantReward,
49 StatueRoll,
50 TalentUpgrade,
51 TalentUpgradeSkip,
52 PetCaseOpen,
53}
54
55#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Tsify, CustomType)]
56pub struct Currency {
57 #[schemars(schema_with = "id_schema")]
58 pub id: CurrencyId,
59 #[schemars(title = "Название")]
60 pub name: i18n::I18nString,
61 #[schemars(title = "Описание")]
62 pub description: i18n::I18nString,
63 #[schemars(title = "URL картинки", schema_with = "webp_url_schema")]
64 pub icon_url: String,
65 #[schemars(title = "Иконка", schema_with = "asset_currency_icon_schema")]
66 pub icon_path: String,
67}
68
69#[derive(
70 Clone,
71 Debug,
72 Serialize,
73 Deserialize,
74 PartialEq,
75 Eq,
76 Hash,
77 JsonSchema,
78 Tsify,
79 CustomType,
80 Default,
81)]
82pub struct CurrencyUnit {
83 #[schemars(schema_with = "currency_link_id_schema")]
84 pub currency_id: CurrencyId,
85 #[schemars(title = "Количество")]
86 pub amount: i64,
87}
88
89impl PartialOrd for CurrencyUnit {
90 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
91 Some(self.cmp(other))
92 }
93}
94
95impl Ord for CurrencyUnit {
96 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
97 match self.currency_id.cmp(&other.currency_id) {
98 std::cmp::Ordering::Equal => self.amount.cmp(&other.amount),
99 ordering => ordering,
100 }
101 }
102}
103
104pub fn increase_currencies(
105 currencies_to_increase: &mut Vec<CurrencyUnit>,
106 currencies_to_add: &[CurrencyUnit],
107) {
108 for add_currency in currencies_to_add {
109 if let Some(unit) = currencies_to_increase
110 .iter_mut()
111 .find(|unit| unit.currency_id == add_currency.currency_id)
112 {
113 unit.amount += add_currency.amount;
114 } else {
115 currencies_to_increase.push(add_currency.clone());
116 }
117 }
118}
119
120pub fn decrease_currencies(
121 currencies_to_decrease: &mut [CurrencyUnit],
122 currencies_to_subtract: &[CurrencyUnit],
123) -> anyhow::Result<()> {
124 for subtract_currency in currencies_to_subtract {
125 if let Some(unit) = currencies_to_decrease
126 .iter_mut()
127 .find(|unit| unit.currency_id == subtract_currency.currency_id)
128 {
129 if unit.amount < subtract_currency.amount {
130 anyhow::bail!(
131 "Required currency {subtract_currency:?} is bigger than available {unit:?}"
132 )
133 }
134
135 unit.amount -= subtract_currency.amount;
136 } else {
137 anyhow::bail!("Given currency {subtract_currency:?} isn't present in currencies")
138 }
139 }
140 Ok(())
141}
142
143pub fn force_decrease_currencies(
144 currencies_to_decrease: &mut Vec<CurrencyUnit>,
145 currencies_to_subtract: &[CurrencyUnit],
146) -> anyhow::Result<()> {
147 for subtract_currency in currencies_to_subtract {
148 if let Some(unit) = currencies_to_decrease
149 .iter_mut()
150 .find(|unit| unit.currency_id == subtract_currency.currency_id)
151 {
152 unit.amount -= subtract_currency.amount;
153 }
154 }
155
156 currencies_to_decrease.retain(|unit| unit.amount != 0);
157
158 Ok(())
159}
160
161pub fn check_can_decrease_currencies(
162 available_currencies: &[CurrencyUnit],
163 required_currencies: &[CurrencyUnit],
164) -> bool {
165 for subtract_currency in required_currencies {
166 if let Some(unit) = available_currencies
167 .iter()
168 .find(|unit| unit.currency_id == subtract_currency.currency_id)
169 {
170 if unit.amount < subtract_currency.amount {
171 return false;
172 }
173 } else {
174 return false;
175 }
176 }
177 true
178}
179
180pub fn from_es_currencies(es_currencies: &[ESCurrencyUnit]) -> Vec<CurrencyUnit> {
181 let mut result = vec![];
182 for es_currency in es_currencies.iter() {
183 result.push(CurrencyUnit {
184 currency_id: es_currency.currency_id,
185 amount: es_currency.amount,
186 });
187 }
188 result
189}