1use crate::prelude::*;
2use event_system::script::types::ESCurrencyUnit;
3
4#[declare]
5pub type CurrencyId = uuid::Uuid;
6
7#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Eq, JsonSchema, Tsify)]
18#[tsify(from_wasm_abi, into_wasm_abi)]
19pub enum CurrencySource {
20 EntityDeath,
21 ItemSell,
22 AutoItemSell,
23 QuestClaim,
24 QuestsTrackReward,
25 VassalTaskCompletion,
26 ReferralLvlUp,
27 ReferralDailyReward,
28 GiftClaim,
29 ArenaTicketBuy,
30 ClaimVassalReward,
31 ClaimSuzerainReward,
32 ArenaMatchmakingRefresh,
33 GachaLevelUp,
34 PetCaseLevelUp,
35 #[default]
39 BundleClaim,
40 AdReward,
41 Cheat,
42 MailReward,
46 DungeonReward,
47 OfferBuy,
48 ChapterReward,
49 NewUserGrant,
50 PvpArenaReward,
51 PvpVassalReward,
52 AfkReward,
53}
54
55impl serde::Serialize for CurrencySource {
56 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
57 where
58 S: serde::Serializer,
59 {
60 let (idx, name) = match self {
67 Self::EntityDeath => (0u32, "EntityDeath"),
68 Self::ItemSell => (1, "ItemSell"),
69 Self::AutoItemSell => (2, "AutoItemSell"),
70 Self::QuestClaim => (3, "QuestClaim"),
71 Self::QuestsTrackReward => (4, "QuestsTrackReward"),
72 Self::VassalTaskCompletion => (5, "VassalTaskCompletion"),
73 Self::ReferralLvlUp => (6, "ReferralLvlUp"),
74 Self::ReferralDailyReward => (7, "ReferralDailyReward"),
75 Self::GiftClaim => (8, "GiftClaim"),
76 Self::ArenaTicketBuy => (9, "ArenaTicketBuy"),
77 Self::ClaimVassalReward => (10, "ClaimVassalReward"),
78 Self::ClaimSuzerainReward => (11, "ClaimSuzerainReward"),
79 Self::ArenaMatchmakingRefresh => (12, "ArenaMatchmakingRefresh"),
80 Self::GachaLevelUp => (13, "GachaLevelUp"),
81 Self::PetCaseLevelUp => (14, "PetCaseLevelUp"),
82 Self::BundleClaim => (15, "BundleClaim"),
83 Self::AdReward => (16, "AdReward"),
84 Self::Cheat => (17, "Cheat"),
85 Self::MailReward
87 | Self::DungeonReward
88 | Self::OfferBuy
89 | Self::ChapterReward
90 | Self::NewUserGrant
91 | Self::PvpArenaReward
92 | Self::PvpVassalReward
93 | Self::AfkReward => (15, "BundleClaim"),
94 };
95 serializer.serialize_unit_variant("CurrencySource", idx, name)
96 }
97}
98
99#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Tsify)]
100#[tsify(from_wasm_abi, into_wasm_abi)]
101pub enum CurrencyConsumer {
102 AbilityCaseOpen,
103 AbilityCaseSlotUpgrade,
104 ItemCaseOpen,
105 GiftSend,
106 DungeonRaid,
107 DungeonFightEnd,
108 ClassChange,
109 OfferBuy,
110 ItemCaseUpgrade,
111 CaseUpgradeSpeedUp,
112 CaseUpgradeSkip,
113 ArenaFight,
114 ArenaMatchmakingRefresh,
115 ArenaTicketBuy,
116 SkinBuy,
117 AfkInstantReward,
118 StatueRoll,
119 TalentUpgrade,
120 TalentUpgradeSkip,
121 PetCaseOpen,
122}
123
124#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema, Tsify, CustomType)]
125pub struct Currency {
126 #[schemars(schema_with = "id_schema")]
127 pub id: CurrencyId,
128 #[schemars(title = "Название")]
129 pub name: i18n::I18nString,
130 #[schemars(title = "Описание")]
131 pub description: i18n::I18nString,
132 #[schemars(title = "URL картинки", schema_with = "webp_url_schema")]
133 pub icon_url: String,
134 #[schemars(title = "Иконка", schema_with = "asset_currency_icon_schema")]
135 pub icon_path: String,
136}
137
138#[derive(
139 Clone,
140 Debug,
141 Serialize,
142 Deserialize,
143 PartialEq,
144 Eq,
145 Hash,
146 JsonSchema,
147 Tsify,
148 CustomType,
149 Default,
150)]
151pub struct CurrencyUnit {
152 #[schemars(schema_with = "currency_link_id_schema")]
153 pub currency_id: CurrencyId,
154 #[schemars(title = "Количество")]
155 pub amount: i64,
156}
157
158impl PartialOrd for CurrencyUnit {
159 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
160 Some(self.cmp(other))
161 }
162}
163
164impl Ord for CurrencyUnit {
165 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
166 match self.currency_id.cmp(&other.currency_id) {
167 std::cmp::Ordering::Equal => self.amount.cmp(&other.amount),
168 ordering => ordering,
169 }
170 }
171}
172
173pub fn increase_currencies(
174 currencies_to_increase: &mut Vec<CurrencyUnit>,
175 currencies_to_add: &[CurrencyUnit],
176) {
177 for add_currency in currencies_to_add {
178 if let Some(unit) = currencies_to_increase
179 .iter_mut()
180 .find(|unit| unit.currency_id == add_currency.currency_id)
181 {
182 unit.amount += add_currency.amount;
183 } else {
184 currencies_to_increase.push(add_currency.clone());
185 }
186 }
187}
188
189pub fn decrease_currencies(
190 currencies_to_decrease: &mut [CurrencyUnit],
191 currencies_to_subtract: &[CurrencyUnit],
192) -> anyhow::Result<()> {
193 for subtract_currency in currencies_to_subtract {
194 if let Some(unit) = currencies_to_decrease
195 .iter_mut()
196 .find(|unit| unit.currency_id == subtract_currency.currency_id)
197 {
198 if unit.amount < subtract_currency.amount {
199 anyhow::bail!(
200 "Required currency {subtract_currency:?} is bigger than available {unit:?}"
201 )
202 }
203
204 unit.amount -= subtract_currency.amount;
205 } else {
206 anyhow::bail!("Given currency {subtract_currency:?} isn't present in currencies")
207 }
208 }
209 Ok(())
210}
211
212pub fn force_decrease_currencies(
213 currencies_to_decrease: &mut Vec<CurrencyUnit>,
214 currencies_to_subtract: &[CurrencyUnit],
215) -> anyhow::Result<()> {
216 for subtract_currency in currencies_to_subtract {
217 if let Some(unit) = currencies_to_decrease
218 .iter_mut()
219 .find(|unit| unit.currency_id == subtract_currency.currency_id)
220 {
221 unit.amount -= subtract_currency.amount;
222 }
223 }
224
225 currencies_to_decrease.retain(|unit| unit.amount != 0);
226
227 Ok(())
228}
229
230pub fn check_can_decrease_currencies(
231 available_currencies: &[CurrencyUnit],
232 required_currencies: &[CurrencyUnit],
233) -> bool {
234 for subtract_currency in required_currencies {
235 if let Some(unit) = available_currencies
236 .iter()
237 .find(|unit| unit.currency_id == subtract_currency.currency_id)
238 {
239 if unit.amount < subtract_currency.amount {
240 return false;
241 }
242 } else {
243 return false;
244 }
245 }
246 true
247}
248
249pub fn from_es_currencies(es_currencies: &[ESCurrencyUnit]) -> Vec<CurrencyUnit> {
250 let mut result = vec![];
251 for es_currency in es_currencies.iter() {
252 result.push(CurrencyUnit {
253 currency_id: es_currency.currency_id,
254 amount: es_currency.amount,
255 });
256 }
257 result
258}