1use super::img_ids;
2use common::{
3 comp::{
4 BuffData, BuffKind,
5 inventory::trade_pricing::TradePricing,
6 item::{
7 Effects, Item, ItemDefinitionId, ItemDesc, ItemI18n, ItemKind, MaterialKind,
8 MaterialStatManifest,
9 armor::{Armor, ArmorKind, Protection},
10 tool::{Hands, Tool, ToolKind},
11 },
12 },
13 effect::Effect,
14 trade::{Good, SitePrices},
15};
16use conrod_core::image;
17use i18n::{FluentValue, Localization, fluent_args};
18use std::{borrow::Cow, fmt::Write};
19
20pub fn price_desc<'a>(
21 prices: &Option<SitePrices>,
22 item_definition_id: ItemDefinitionId<'_>,
23 i18n: &'a Localization,
24) -> Option<(Cow<'a, str>, Cow<'a, str>, f32)> {
25 let prices = prices.as_ref()?;
26 let materials = TradePricing::get_materials(&item_definition_id)?;
27 let coinprice = prices.values.get(&Good::Coin).cloned().unwrap_or(1.0);
28 let buyprice: f32 = materials
29 .iter()
30 .map(|e| prices.values.get(&e.1).cloned().unwrap_or_default() * e.0)
31 .sum();
32 let sellprice: f32 = materials
33 .iter()
34 .map(|e| prices.values.get(&e.1).cloned().unwrap_or_default() * e.0 * e.1.trade_margin())
35 .sum();
36
37 let deal_goodness: f32 = materials
38 .iter()
39 .map(|e| prices.values.get(&e.1).cloned().unwrap_or(0.0))
40 .sum::<f32>()
41 / prices.values.get(&Good::Coin).cloned().unwrap_or(1.0)
42 / (materials.len() as f32);
43 let deal_goodness = deal_goodness.log(2.0);
44
45 let buy_string = i18n.get_msg_ctx("hud-trade-buy", &fluent_args! {
46 "coin_num" => buyprice / coinprice,
47 "coin_formatted" => format!("{:0.1}", buyprice / coinprice),
48 });
49 let sell_string = i18n.get_msg_ctx("hud-trade-sell", &fluent_args! {
50 "coin_num" => sellprice / coinprice,
51 "coin_formatted" => format!("{:0.1}", sellprice / coinprice),
52 });
53
54 let deal_goodness = match deal_goodness {
55 x if x < -2.5 => 0.0,
56 x if x < -1.05 => 0.25,
57 x if x < -0.95 => 0.5,
58 x if x < 0.0 => 0.75,
59 _ => 1.0,
60 };
61 Some((buy_string, sell_string, deal_goodness))
62}
63
64pub fn item_text<'a, I: ItemDesc + ?Sized>(
65 item: &I,
66 i18n: &'a Localization,
67 i18n_spec: &'a ItemI18n,
68) -> (String, String) {
69 let (title, desc) = item.i18n(i18n_spec);
70
71 (i18n.get_content(&title), i18n.get_content(&desc))
72}
73
74pub fn describe<'a, I: ItemDesc + ?Sized>(
75 item: &I,
76 i18n: &'a Localization,
77 i18n_spec: &'a ItemI18n,
78) -> String {
79 let (title, _) = item_text(item, i18n, i18n_spec);
80 let amount = item.amount();
81
82 if amount.get() > 1 {
83 format!("{amount} x {title}")
84 } else {
85 title
86 }
87}
88
89pub fn kind_text<'a>(kind: &ItemKind, i18n: &'a Localization) -> Cow<'a, str> {
90 match kind {
91 ItemKind::Armor(armor) => armor_kind(armor, i18n),
92 ItemKind::Tool(tool) => Cow::Owned(format!(
93 "{} ({})",
94 tool_kind(tool, i18n),
95 tool_hands(tool, i18n)
96 )),
97 ItemKind::ModularComponent(mc) => {
98 if let Some(toolkind) = mc.toolkind() {
99 Cow::Owned(format!(
100 "{} {}",
101 i18n.get_msg(&format!("common-weapons-{}", toolkind.identifier_name())),
102 i18n.get_msg("common-kind-modular_component_partial")
103 ))
104 } else {
105 i18n.get_msg("common-kind-modular_component")
106 }
107 },
108 ItemKind::Glider => i18n.get_msg("common-kind-glider"),
109 ItemKind::Consumable { .. } => i18n.get_msg("common-kind-consumable"),
110 ItemKind::Utility { .. } => i18n.get_msg("common-kind-utility"),
111 ItemKind::Ingredient { .. } => i18n.get_msg("common-kind-ingredient"),
112 ItemKind::Lantern { .. } => i18n.get_msg("common-kind-lantern"),
113 ItemKind::TagExamples { .. } => Cow::Borrowed(""),
114 ItemKind::RecipeGroup { .. } => i18n.get_msg("common-kind-recipegroup"),
115 }
116}
117
118pub fn material_kind_text<'a>(kind: &MaterialKind, i18n: &'a Localization) -> Cow<'a, str> {
119 match kind {
120 MaterialKind::Metal => i18n.get_msg("common-material-metal"),
121 MaterialKind::Gem => i18n.get_msg("common-material-gem"),
122 MaterialKind::Wood => i18n.get_msg("common-material-wood"),
123 MaterialKind::Stone => i18n.get_msg("common-material-stone"),
124 MaterialKind::Cloth => i18n.get_msg("common-material-cloth"),
125 MaterialKind::Hide => i18n.get_msg("common-material-hide"),
126 }
127}
128
129pub fn stats_count(item: &dyn ItemDesc, msm: &MaterialStatManifest) -> usize {
130 let mut count = match &*item.kind() {
131 ItemKind::Armor(armor) => {
132 let armor_stats = armor.stats(msm, item.stats_durability_multiplier());
133 armor_stats.energy_reward.is_some() as usize
134 + armor_stats.energy_max.is_some() as usize
135 + armor_stats.stealth.is_some() as usize
136 + armor_stats.precision_power.is_some() as usize
137 + armor_stats.poise_resilience.is_some() as usize
138 + armor_stats.protection.is_some() as usize
139 + (item.num_slots() > 0) as usize
140 },
141 ItemKind::Tool(_) => 6,
142 ItemKind::Consumable { effects, .. } => match effects {
143 Effects::Any(_) | Effects::One(_) => 1,
144 Effects::All(effects) => effects.len(),
145 },
146 ItemKind::RecipeGroup { recipes } => {
147 recipes.len() + 1
149 },
150 ItemKind::ModularComponent { .. } => 6,
151 _ => 0,
152 };
153 if item.has_durability() {
154 count += 1;
155 }
156 count
157}
158
159pub fn line_count(item: &dyn ItemDesc, msm: &MaterialStatManifest, i18n: &Localization) -> usize {
160 match &*item.kind() {
161 ItemKind::Consumable { effects, .. } => {
162 let descs = consumable_desc(effects, i18n);
163 let mut lines = 0;
164 for desc in descs {
165 lines += desc.matches('\n').count() + 1;
166 }
167
168 lines
169 },
170 _ => stats_count(item, msm),
171 }
172}
173
174fn buff_key(buff: BuffKind) -> &'static str {
178 match buff {
179 BuffKind::Regeneration => "buff-heal",
181 BuffKind::Saturation => "buff-saturation",
182 BuffKind::Potion => "buff-potion",
183 BuffKind::Agility => "buff-agility",
184 BuffKind::RestingHeal => "buff-resting_heal",
185 BuffKind::EnergyRegen => "buff-energy_regen",
186 BuffKind::ComboGeneration => "buff-combo_generation",
187 BuffKind::IncreaseMaxHealth => "buff-increase_max_health",
188 BuffKind::IncreaseMaxEnergy => "buff-increase_max_energy",
189 BuffKind::Invulnerability => "buff-invulnerability",
190 BuffKind::ProtectingWard => "buff-protectingward",
191 BuffKind::Frenzied => "buff-frenzied",
192 BuffKind::Hastened => "buff-hastened",
193 BuffKind::Fortitude => "buff-fortitude",
194 BuffKind::Reckless => "buff-reckless",
195 BuffKind::Flame => "buff-burn",
197 BuffKind::Frigid => "buff-frigid",
198 BuffKind::Lifesteal => "buff-lifesteal",
199 BuffKind::ImminentCritical => "buff-imminentcritical",
200 BuffKind::Fury => "buff-fury",
201 BuffKind::Sunderer => "buff-sunderer",
202 BuffKind::Defiance => "buff-defiance",
203 BuffKind::Bloodfeast => "buff-bloodfeast",
204 BuffKind::Berserk => "buff-berserk",
205 BuffKind::ScornfulTaunt => "buff-scornfultaunt",
206 BuffKind::Tenacity => "buff-tenacity",
207 BuffKind::Resilience => "buff-resilience",
208 BuffKind::Bleeding => "buff-bleed",
210 BuffKind::Cursed => "buff-cursed",
211 BuffKind::Burning => "buff-burn",
212 BuffKind::Crippled => "buff-crippled",
213 BuffKind::Frozen => "buff-frozen",
214 BuffKind::Wet => "buff-wet",
215 BuffKind::Ensnared => "buff-ensnared",
216 BuffKind::Poisoned => "buff-poisoned",
217 BuffKind::Parried => "buff-parried",
218 BuffKind::PotionSickness => "buff-potionsickness",
219 BuffKind::Heatstroke => "buff-heatstroke",
220 BuffKind::Rooted => "buff-rooted",
221 BuffKind::Winded => "buff-winded",
222 BuffKind::Concussion => "buff-concussion",
223 BuffKind::Staggered => "buff-staggered",
224 BuffKind::Polymorphed => "buff-polymorphed",
226 }
227}
228
229pub fn get_buff_title(buff: BuffKind, i18n: &Localization) -> Cow<str> {
231 let key = buff_key(buff);
232
233 i18n.get_msg(key)
234}
235
236pub fn get_buff_desc(buff: BuffKind, data: BuffData, i18n: &Localization) -> Cow<str> {
238 let key = buff_key(buff);
239 if let BuffKind::RestingHeal = buff {
240 i18n.get_attr_ctx(key, "desc", &i18n::fluent_args! {
241 "rate" => data.strength * 100.0
242 })
243 } else {
244 i18n.get_attr(key, "desc")
245 }
246}
247
248fn almost_integer(number: &f32) -> FluentValue {
249 let epsilon = 0.001;
250 if number.fract() < epsilon {
251 FluentValue::from(number.round() as usize)
252 } else {
253 FluentValue::from(format!("{:.<3}", number))
254 }
255}
256pub fn consumable_desc(effects: &Effects, i18n: &Localization) -> Vec<String> {
262 let mut descriptions = Vec::new();
263 match effects {
264 Effects::Any(_) => {
265 descriptions.push(i18n.get_msg("buff-mysterious").into_owned());
266 },
267 Effects::All(_) | Effects::One(_) => {
268 for effect in effects.effects() {
269 let mut description = String::new();
270 if let Effect::Buff(buff) = effect {
271 let strength = buff.data.strength;
272 let duration = buff.data.duration.map(|d| d.0 as f32);
273 let str_total = duration.map_or(strength, |secs| strength * secs);
274 let str_duration = duration.unwrap_or(0.0);
275 let fluent_duration = almost_integer(&str_duration);
276
277 let format_float =
278 |input: f32| format!("{:.1}", input).trim_end_matches(".0").to_string();
279
280 let buff_desc = match buff.kind {
281 BuffKind::Saturation | BuffKind::Regeneration | BuffKind::Potion => {
283 let key = "buff-heal";
284 i18n.get_attr_ctx(key, "stat", &i18n::fluent_args! {
285 "str_total" => format_float(str_total),
286 "duration" => fluent_duration,
287 })
288 },
289 BuffKind::EnergyRegen => {
291 let key = buff_key(buff.kind);
292 i18n.get_attr_ctx(key, "stat", &i18n::fluent_args! {
293 "str_total" => format_float(str_total),
294 "duration" => fluent_duration,
295 })
296 },
297 BuffKind::ComboGeneration => {
298 let key = buff_key(buff.kind);
299 i18n.get_attr_ctx(key, "stat", &i18n::fluent_args! {
300 "str_total" => format_float(str_total),
301 "duration" => fluent_duration,
302 })
303 },
304 BuffKind::IncreaseMaxEnergy
306 | BuffKind::IncreaseMaxHealth => {
307 let key = buff_key(buff.kind);
308 i18n.get_attr_ctx(key, "stat", &i18n::fluent_args! {
309 "strength" => format_float(strength),
310 "duration" => fluent_duration,
311 })
312 },
313 BuffKind::PotionSickness
315 | BuffKind::Agility => {
316 let key = buff_key(buff.kind);
317 i18n.get_attr_ctx(key, "stat", &i18n::fluent_args! {
318 "strength" => format_float(strength * 100.0),
319 "duration" => fluent_duration,
320 })
321 },
322 BuffKind::Invulnerability => {
324 let key = buff_key(buff.kind);
325 i18n.get_attr_ctx(key, "stat", &i18n::fluent_args! {
326 "duration" => fluent_duration,
327 })
328 },
329 BuffKind::Bleeding
331 | BuffKind::Burning
332 | BuffKind::RestingHeal
333 | BuffKind::Cursed
334 | BuffKind::ProtectingWard
335 | BuffKind::Crippled
336 | BuffKind::Frenzied
337 | BuffKind::Frozen
338 | BuffKind::Wet
339 | BuffKind::Ensnared
340 | BuffKind::Poisoned
341 | BuffKind::Hastened
342 | BuffKind::Fortitude
343 | BuffKind::Parried
344 | BuffKind::Reckless
345 | BuffKind::Polymorphed
346 | BuffKind::Flame
347 | BuffKind::Frigid
348 | BuffKind::Lifesteal
349 | BuffKind::ImminentCritical
351 | BuffKind::Fury
352 | BuffKind::Sunderer
353 | BuffKind::Defiance
354 | BuffKind::Bloodfeast
355 | BuffKind::Berserk
356 | BuffKind::Heatstroke
357 | BuffKind::ScornfulTaunt
358 | BuffKind::Rooted
359 | BuffKind::Winded
360 | BuffKind::Concussion
361 | BuffKind::Staggered
362 | BuffKind::Tenacity
363 | BuffKind::Resilience => Cow::Borrowed(""),
364 };
365
366 write!(&mut description, "{}", buff_desc).unwrap();
367 }
368 descriptions.push(description);
369 }
370 },
371 }
372 descriptions
373}
374
375fn armor_kind<'a>(armor: &Armor, i18n: &'a Localization) -> Cow<'a, str> {
377 let kind = match armor.kind {
378 ArmorKind::Shoulder => i18n.get_msg("hud-bag-shoulders"),
379 ArmorKind::Chest => i18n.get_msg("hud-bag-chest"),
380 ArmorKind::Belt => i18n.get_msg("hud-bag-belt"),
381 ArmorKind::Hand => i18n.get_msg("hud-bag-hands"),
382 ArmorKind::Pants => i18n.get_msg("hud-bag-legs"),
383 ArmorKind::Foot => i18n.get_msg("hud-bag-feet"),
384 ArmorKind::Back => i18n.get_msg("hud-bag-back"),
385 ArmorKind::Backpack => i18n.get_msg("hud-bag-backpack"),
386 ArmorKind::Ring => i18n.get_msg("hud-bag-ring"),
387 ArmorKind::Neck => i18n.get_msg("hud-bag-neck"),
388 ArmorKind::Head => i18n.get_msg("hud-bag-head"),
389 ArmorKind::Tabard => i18n.get_msg("hud-bag-tabard"),
390 ArmorKind::Bag => i18n.get_msg("hud-bag-bag"),
391 };
392 kind
393}
394
395fn tool_kind<'a>(tool: &Tool, i18n: &'a Localization) -> Cow<'a, str> {
397 let kind = match tool.kind {
398 ToolKind::Sword => i18n.get_msg("common-weapons-sword"),
399 ToolKind::Axe => i18n.get_msg("common-weapons-axe"),
400 ToolKind::Hammer => i18n.get_msg("common-weapons-hammer"),
401 ToolKind::Bow => i18n.get_msg("common-weapons-bow"),
402 ToolKind::Dagger => i18n.get_msg("common-weapons-dagger"),
403 ToolKind::Staff => i18n.get_msg("common-weapons-staff"),
404 ToolKind::Sceptre => i18n.get_msg("common-weapons-sceptre"),
405 ToolKind::Shield => i18n.get_msg("common-weapons-shield"),
406 ToolKind::Spear => i18n.get_msg("common-weapons-spear"),
407 ToolKind::Blowgun => i18n.get_msg("common-weapons-blowgun"),
408 ToolKind::Natural => i18n.get_msg("common-weapons-natural"),
409 ToolKind::Debug => i18n.get_msg("common-tool-debug"),
410 ToolKind::Farming => i18n.get_msg("common-tool-farming"),
411 ToolKind::Instrument => i18n.get_msg("common-tool-instrument"),
412 ToolKind::Throwable => i18n.get_msg("common-tool-throwable"),
413 ToolKind::Pick => i18n.get_msg("common-tool-pick"),
414 ToolKind::Shovel => i18n.get_msg("common-tool-shovel"),
415 ToolKind::Empty => i18n.get_msg("common-empty"),
416 };
417 kind
418}
419
420pub fn tool_hands<'a>(tool: &Tool, i18n: &'a Localization) -> Cow<'a, str> {
422 let hands = match tool.hands {
423 Hands::One => i18n.get_msg("common-hands-one"),
424 Hands::Two => i18n.get_msg("common-hands-two"),
425 };
426 hands
427}
428
429pub fn comparison<T: PartialOrd>(first: T, other: T) -> (&'static str, conrod_core::Color) {
431 if first == other {
432 ("•", conrod_core::color::GREY)
433 } else if other < first {
434 ("▲", conrod_core::color::GREEN)
435 } else {
436 ("▼", conrod_core::color::RED)
437 }
438}
439
440pub fn option_comparison<T: PartialOrd>(
442 first: &Option<T>,
443 other: &Option<T>,
444) -> (&'static str, conrod_core::Color) {
445 if let Some(first) = first {
446 if let Some(other) = other {
447 if first == other {
448 ("•", conrod_core::color::GREY)
449 } else if other < first {
450 ("▲", conrod_core::color::GREEN)
451 } else {
452 ("▼", conrod_core::color::RED)
453 }
454 } else {
455 ("▲", conrod_core::color::GREEN)
456 }
457 } else if other.is_some() {
458 ("▼", conrod_core::color::RED)
459 } else {
460 ("•", conrod_core::color::GREY)
461 }
462}
463
464pub fn protec2string(stat: Protection) -> String {
466 match stat {
467 Protection::Normal(a) => format!("{:.1}", a),
468 Protection::Invincible => "Inf".to_string(),
469 }
470}
471
472pub fn item_durability(item: &dyn ItemDesc) -> Option<u32> {
474 let durability = item
475 .durability_lost()
476 .or_else(|| item.has_durability().then_some(0));
477 durability.map(|d| Item::MAX_DURABILITY - d)
478}
479
480pub fn ability_image(imgs: &img_ids::Imgs, ability_id: &str) -> image::Id {
481 match ability_id {
482 "common.abilities.debug.forwardboost" => imgs.flyingrod_m1,
484 "common.abilities.debug.upboost" => imgs.flyingrod_m2,
485 "common.abilities.debug.possess" => imgs.snake_arrow_0,
486 "veloren.core.pseudo_abilities.sword.heavy_stance" => imgs.sword_heavy_stance,
488 "veloren.core.pseudo_abilities.sword.agile_stance" => imgs.sword_agile_stance,
489 "veloren.core.pseudo_abilities.sword.defensive_stance" => imgs.sword_defensive_stance,
490 "veloren.core.pseudo_abilities.sword.crippling_stance" => imgs.sword_crippling_stance,
491 "veloren.core.pseudo_abilities.sword.cleaving_stance" => imgs.sword_cleaving_stance,
492 "veloren.core.pseudo_abilities.sword.double_slash" => imgs.sword_double_slash,
493 "common.abilities.sword.basic_double_slash" => imgs.sword_basic_double_slash,
494 "common.abilities.sword.heavy_double_slash" => imgs.sword_heavy_double_slash,
495 "common.abilities.sword.agile_double_slash" => imgs.sword_agile_double_slash,
496 "common.abilities.sword.defensive_double_slash" => imgs.sword_defensive_double_slash,
497 "common.abilities.sword.crippling_double_slash" => imgs.sword_crippling_double_slash,
498 "common.abilities.sword.cleaving_double_slash" => imgs.sword_cleaving_double_slash,
499 "veloren.core.pseudo_abilities.sword.secondary_ability" => imgs.sword_secondary_ability,
500 "common.abilities.sword.basic_thrust" => imgs.sword_basic_thrust,
501 "common.abilities.sword.heavy_slam" => imgs.sword_heavy_slam,
502 "common.abilities.sword.agile_perforate" => imgs.sword_agile_perforate,
503 "common.abilities.sword.agile_dual_perforate" => imgs.sword_agile_perforate,
504 "common.abilities.sword.defensive_vital_jab" => imgs.sword_defensive_vital_jab,
505 "common.abilities.sword.crippling_deep_rend" => imgs.sword_crippling_deep_rend,
506 "common.abilities.sword.cleaving_spiral_slash" => imgs.sword_cleaving_spiral_slash,
507 "common.abilities.sword.cleaving_dual_spiral_slash" => imgs.sword_cleaving_spiral_slash,
508 "veloren.core.pseudo_abilities.sword.crescent_slash" => imgs.sword_crescent_slash,
509 "common.abilities.sword.basic_crescent_slash" => imgs.sword_basic_crescent_slash,
510 "common.abilities.sword.heavy_crescent_slash" => imgs.sword_heavy_crescent_slash,
511 "common.abilities.sword.agile_crescent_slash" => imgs.sword_agile_crescent_slash,
512 "common.abilities.sword.defensive_crescent_slash" => imgs.sword_defensive_crescent_slash,
513 "common.abilities.sword.crippling_crescent_slash" => imgs.sword_crippling_crescent_slash,
514 "common.abilities.sword.cleaving_crescent_slash" => imgs.sword_cleaving_crescent_slash,
515 "veloren.core.pseudo_abilities.sword.fell_strike" => imgs.sword_fell_strike,
516 "common.abilities.sword.basic_fell_strike" => imgs.sword_basic_fell_strike,
517 "common.abilities.sword.heavy_fell_strike" => imgs.sword_heavy_fell_strike,
518 "common.abilities.sword.agile_fell_strike" => imgs.sword_agile_fell_strike,
519 "common.abilities.sword.defensive_fell_strike" => imgs.sword_defensive_fell_strike,
520 "common.abilities.sword.crippling_fell_strike" => imgs.sword_crippling_fell_strike,
521 "common.abilities.sword.cleaving_fell_strike" => imgs.sword_cleaving_fell_strike,
522 "veloren.core.pseudo_abilities.sword.skewer" => imgs.sword_skewer,
523 "common.abilities.sword.basic_skewer" => imgs.sword_basic_skewer,
524 "common.abilities.sword.heavy_skewer" => imgs.sword_heavy_skewer,
525 "common.abilities.sword.agile_skewer" => imgs.sword_agile_skewer,
526 "common.abilities.sword.defensive_skewer" => imgs.sword_defensive_skewer,
527 "common.abilities.sword.crippling_skewer" => imgs.sword_crippling_skewer,
528 "common.abilities.sword.cleaving_skewer" => imgs.sword_cleaving_skewer,
529 "veloren.core.pseudo_abilities.sword.cascade" => imgs.sword_cascade,
530 "common.abilities.sword.basic_cascade" => imgs.sword_basic_cascade,
531 "common.abilities.sword.heavy_cascade" => imgs.sword_heavy_cascade,
532 "common.abilities.sword.agile_cascade" => imgs.sword_agile_cascade,
533 "common.abilities.sword.defensive_cascade" => imgs.sword_defensive_cascade,
534 "common.abilities.sword.crippling_cascade" => imgs.sword_crippling_cascade,
535 "common.abilities.sword.cleaving_cascade" => imgs.sword_cleaving_cascade,
536 "veloren.core.pseudo_abilities.sword.cross_cut" => imgs.sword_cross_cut,
537 "common.abilities.sword.basic_cross_cut" => imgs.sword_basic_cross_cut,
538 "common.abilities.sword.heavy_cross_cut" => imgs.sword_heavy_cross_cut,
539 "common.abilities.sword.agile_cross_cut" => imgs.sword_agile_cross_cut,
540 "common.abilities.sword.defensive_cross_cut" => imgs.sword_defensive_cross_cut,
541 "common.abilities.sword.crippling_cross_cut" => imgs.sword_crippling_cross_cut,
542 "common.abilities.sword.cleaving_cross_cut" => imgs.sword_cleaving_cross_cut,
543 "common.abilities.sword.basic_dual_cross_cut" => imgs.sword_basic_cross_cut,
544 "common.abilities.sword.heavy_dual_cross_cut" => imgs.sword_heavy_cross_cut,
545 "common.abilities.sword.agile_dual_cross_cut" => imgs.sword_agile_cross_cut,
546 "common.abilities.sword.defensive_dual_cross_cut" => imgs.sword_defensive_cross_cut,
547 "common.abilities.sword.crippling_dual_cross_cut" => imgs.sword_crippling_cross_cut,
548 "common.abilities.sword.cleaving_dual_cross_cut" => imgs.sword_cleaving_cross_cut,
549 "veloren.core.pseudo_abilities.sword.finisher" => imgs.sword_finisher,
550 "common.abilities.sword.basic_mighty_strike" => imgs.sword_basic_mighty_strike,
551 "common.abilities.sword.heavy_guillotine" => imgs.sword_heavy_guillotine,
552 "common.abilities.sword.agile_hundred_cuts" => imgs.sword_agile_hundred_cuts,
553 "common.abilities.sword.defensive_counter" => imgs.sword_defensive_counter,
554 "common.abilities.sword.crippling_mutilate" => imgs.sword_crippling_mutilate,
555 "common.abilities.sword.cleaving_bladestorm" => imgs.sword_cleaving_bladestorm,
556 "common.abilities.sword.cleaving_dual_bladestorm" => imgs.sword_cleaving_bladestorm,
557 "common.abilities.sword.heavy_sweep" => imgs.sword_heavy_sweep,
558 "common.abilities.sword.heavy_pommel_strike" => imgs.sword_heavy_pommel_strike,
559 "common.abilities.sword.agile_quick_draw" => imgs.sword_agile_quick_draw,
560 "common.abilities.sword.agile_feint" => imgs.sword_agile_feint,
561 "common.abilities.sword.defensive_riposte" => imgs.sword_defensive_riposte,
562 "common.abilities.sword.defensive_disengage" => imgs.sword_defensive_disengage,
563 "common.abilities.sword.crippling_gouge" => imgs.sword_crippling_gouge,
564 "common.abilities.sword.crippling_hamstring" => imgs.sword_crippling_hamstring,
565 "common.abilities.sword.cleaving_whirlwind_slice" => imgs.sword_cleaving_whirlwind_slice,
566 "common.abilities.sword.cleaving_dual_whirlwind_slice" => {
567 imgs.sword_cleaving_whirlwind_slice
568 },
569 "common.abilities.sword.cleaving_earth_splitter" => imgs.sword_cleaving_earth_splitter,
570 "common.abilities.sword.heavy_fortitude" => imgs.sword_heavy_fortitude,
571 "common.abilities.sword.heavy_pillar_thrust" => imgs.sword_heavy_pillar_thrust,
572 "common.abilities.sword.agile_dancing_edge" => imgs.sword_agile_dancing_edge,
573 "common.abilities.sword.agile_flurry" => imgs.sword_agile_flurry,
574 "common.abilities.sword.agile_dual_flurry" => imgs.sword_agile_flurry,
575 "common.abilities.sword.defensive_stalwart_sword" => imgs.sword_defensive_stalwart_sword,
576 "common.abilities.sword.defensive_deflect" => imgs.sword_defensive_deflect,
577 "common.abilities.sword.crippling_eviscerate" => imgs.sword_crippling_eviscerate,
578 "common.abilities.sword.crippling_bloody_gash" => imgs.sword_crippling_bloody_gash,
579 "common.abilities.sword.cleaving_blade_fever" => imgs.sword_cleaving_blade_fever,
580 "common.abilities.sword.cleaving_sky_splitter" => imgs.sword_cleaving_sky_splitter,
581 "common.abilities.axe.triple_chop" => imgs.axe_triple_chop,
583 "common.abilities.axe.cleave" => imgs.axe_cleave,
584 "common.abilities.axe.brutal_swing" => imgs.axe_brutal_swing,
585 "common.abilities.axe.berserk" => imgs.axe_berserk,
586 "common.abilities.axe.rising_tide" => imgs.axe_rising_tide,
587 "common.abilities.axe.savage_sense" => imgs.axe_savage_sense,
588 "common.abilities.axe.adrenaline_rush" => imgs.axe_adrenaline_rush,
589 "common.abilities.axe.execute" => imgs.axe_execute,
590 "common.abilities.axe.maelstrom" => imgs.axe_maelstrom,
591 "common.abilities.axe.rake" => imgs.axe_rake,
592 "common.abilities.axe.bloodfeast" => imgs.axe_bloodfeast,
593 "common.abilities.axe.fierce_raze" => imgs.axe_fierce_raze,
594 "common.abilities.axe.dual_fierce_raze" => imgs.axe_fierce_raze,
595 "common.abilities.axe.furor" => imgs.axe_furor,
596 "common.abilities.axe.fracture" => imgs.axe_fracture,
597 "common.abilities.axe.lacerate" => imgs.axe_lacerate,
598 "common.abilities.axe.riptide" => imgs.axe_riptide,
599 "common.abilities.axe.skull_bash" => imgs.axe_skull_bash,
600 "common.abilities.axe.sunder" => imgs.axe_sunder,
601 "common.abilities.axe.plunder" => imgs.axe_plunder,
602 "common.abilities.axe.defiance" => imgs.axe_defiance,
603 "common.abilities.axe.keelhaul" => imgs.axe_keelhaul,
604 "common.abilities.axe.bulkhead" => imgs.axe_bulkhead,
605 "common.abilities.axe.capsize" => imgs.axe_capsize,
606 "common.abilities.hammer.solid_smash" => imgs.hammer_solid_smash,
608 "common.abilities.hammer.wide_wallop" => imgs.hammer_wide_wallop,
609 "common.abilities.hammer.scornful_swipe" => imgs.hammer_scornful_swipe,
610 "common.abilities.hammer.tremor" => imgs.hammer_tremor,
611 "common.abilities.hammer.vigorous_bash" => imgs.hammer_vigorous_bash,
612 "common.abilities.hammer.heavy_whorl" => imgs.hammer_heavy_whorl,
613 "common.abilities.hammer.dual_heavy_whorl" => imgs.hammer_heavy_whorl,
614 "common.abilities.hammer.intercept" => imgs.hammer_intercept,
615 "common.abilities.hammer.dual_intercept" => imgs.hammer_intercept,
616 "common.abilities.hammer.retaliate" => imgs.hammer_retaliate,
617 "common.abilities.hammer.spine_cracker" => imgs.hammer_spine_cracker,
618 "common.abilities.hammer.breach" => imgs.hammer_breach,
619 "common.abilities.hammer.pile_driver" => imgs.hammer_pile_driver,
620 "common.abilities.hammer.lung_pummel" => imgs.hammer_lung_pummel,
621 "common.abilities.hammer.helm_crusher" => imgs.hammer_helm_crusher,
622 "common.abilities.hammer.iron_tempest" => imgs.hammer_iron_tempest,
623 "common.abilities.hammer.dual_iron_tempest" => imgs.hammer_iron_tempest,
624 "common.abilities.hammer.upheaval" => imgs.hammer_upheaval,
625 "common.abilities.hammer.dual_upheaval" => imgs.hammer_upheaval,
626 "common.abilities.hammer.rampart" => imgs.hammer_rampart,
627 "common.abilities.hammer.tenacity" => imgs.hammer_tenacity,
628 "common.abilities.hammer.thunderclap" => imgs.hammer_thunderclap,
629 "common.abilities.hammer.seismic_shock" => imgs.hammer_seismic_shock,
630 "common.abilities.hammer.earthshaker" => imgs.hammer_earthshaker,
631 "common.abilities.hammer.judgement" => imgs.hammer_judgement,
632 "common.abilities.bow.charged" => imgs.bow_m1,
634 "common.abilities.bow.repeater" => imgs.bow_m2,
635 "common.abilities.bow.shotgun" => imgs.skill_bow_jump_burst,
636 "common.abilities.staff.firebomb" => imgs.fireball,
638 "common.abilities.staff.flamethrower" => imgs.flamethrower,
639 "common.abilities.staff.fireshockwave" => imgs.fire_aoe,
640 "common.abilities.sceptre.lifestealbeam" => imgs.skill_sceptre_lifesteal,
642 "common.abilities.sceptre.healingaura" => imgs.skill_sceptre_heal,
643 "common.abilities.sceptre.wardingaura" => imgs.skill_sceptre_aura,
644 "common.abilities.shield.singlestrike" => imgs.onehshield_m1,
646 "common.abilities.shield.power_guard" => imgs.onehshield_m1,
647 "common.abilities.dagger.tempbasic" => imgs.onehdagger_m1,
649 "common.abilities.pick.swing" => imgs.mining,
651 "common.abilities.shovel.dig" => imgs.dig,
653 "common.abilities.music.bass" => imgs.instrument,
655 "common.abilities.music.flute" => imgs.instrument,
656 "common.abilities.music.harp" => imgs.instrument,
657 "common.abilities.music.perc" => imgs.instrument,
658 "common.abilities.music.kalimba" => imgs.instrument,
659 "common.abilities.music.melodica" => imgs.instrument,
660 "common.abilities.music.lute" => imgs.instrument,
661 "common.abilities.music.oud" => imgs.instrument,
662 "common.abilities.music.guitar" => imgs.instrument,
663 "common.abilities.music.dark_guitar" => imgs.instrument,
664 "common.abilities.music.sitar" => imgs.instrument,
665 "common.abilities.music.double_bass" => imgs.instrument,
666 "common.abilities.music.glass_flute" => imgs.instrument,
667 "common.abilities.music.lyre" => imgs.instrument,
668 "common.abilities.music.wildskin_drum" => imgs.instrument,
669 "common.abilities.music.icy_talharpa" => imgs.instrument,
670 "common.abilities.music.washboard" => imgs.instrument,
671 "common.abilities.music.steeltonguedrum" => imgs.instrument,
672 "common.abilities.music.shamisen" => imgs.instrument,
673 "common.abilities.music.kora" => imgs.instrument,
674 "common.abilities.music.banjo" => imgs.instrument,
675 "common.abilities.music.viola_pizzicato" => imgs.instrument,
676 "common.abilities.music.starlight_conch" => imgs.instrument,
677 "common.abilities.music.timbrel_of_chaos" => imgs.instrument,
678 "common.abilities.music.rhythmo" => imgs.instrument,
679 "common.abilities.debug.glide_boost" => imgs.flyingrod_m2,
681 "common.abilities.debug.glide_speeder" => imgs.flyingrod_m1,
682 _ => imgs.not_found,
683 }
684}
685
686pub fn ability_description<'a>(
687 ability_id: &str,
688 loc: &'a Localization,
689) -> (Cow<'a, str>, Cow<'a, str>) {
690 let ability_i18n_key = ability_id.replace('.', "-");
691 match ability_i18n_key.as_str() {
692 "common-abilities-axe-execute"
693 | "common-abilities-axe-maelstrom"
694 | "common-abilities-axe-lacerate"
695 | "common-abilities-axe-riptide"
696 | "common-abilities-axe-bulkhead"
697 | "common-abilities-axe-capsize" => (
698 loc.get_msg(&ability_i18n_key),
699 loc.get_attr_ctx(&ability_i18n_key, "desc", &i18n::fluent_args! {
700 "min_combo" => 25,
701 "min_combo_upg" => 40,
702 }),
703 ),
704 ability_i18n_key => (
706 loc.get_msg(ability_i18n_key),
707 loc.get_attr(ability_i18n_key, "desc"),
708 ),
709 }
710}