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