diff --git a/assets/common/items/boss_drops/exp_flask.ron b/assets/common/items/boss_drops/exp_flask.ron index 9f0aba0363..7eddd6dac5 100644 --- a/assets/common/items/boss_drops/exp_flask.ron +++ b/assets/common/items/boss_drops/exp_flask.ron @@ -1,11 +1,8 @@ ItemDef( name: "Flask of Velorite Dust", - description: "Increases Exp by 250\n\nTake with plenty of water", - kind: Consumable( - kind: "PotionExp", - effect: [ - /*Xp(250),*/ - ] + description: "Take with plenty of water", + kind: Ingredient( + kind: "PotionExp", ), quality: High, ) diff --git a/assets/common/items/boss_drops/xp_potion.ron b/assets/common/items/boss_drops/xp_potion.ron index f2227265b3..cff913c7ac 100644 --- a/assets/common/items/boss_drops/xp_potion.ron +++ b/assets/common/items/boss_drops/xp_potion.ron @@ -1,11 +1,8 @@ ItemDef( name: "Potion of Skill", - description: "Provides 250 XP to the drinker", - kind: Consumable( - kind: "Potion", - effect: [ - /*Xp(250),*/ - ] + description: "It doesn't seem to be doing anything...", + kind: Ingredient( + kind: "Potion", ), quality: High, ) diff --git a/assets/common/items/ore/velorite.ron b/assets/common/items/ore/velorite.ron index 5136847ae3..74f0ec0634 100644 --- a/assets/common/items/ore/velorite.ron +++ b/assets/common/items/ore/velorite.ron @@ -1,11 +1,8 @@ ItemDef( name: "Velorite", - description: "Increases Exp by 20\n\nJust a slight touch makes you feel the knowledge of ancient times", - kind: Consumable( - kind: "Velorite", - effect: [ - /*Xp(20),*/ - ] + description: "Just a slight touch makes you feel\n\the knowledge of ancient times", + kind: Ingredient( + kind: "Velorite", ), quality: High, ) diff --git a/assets/common/items/ore/veloritefrag.ron b/assets/common/items/ore/veloritefrag.ron index a63d5391db..b5e050e131 100644 --- a/assets/common/items/ore/veloritefrag.ron +++ b/assets/common/items/ore/veloritefrag.ron @@ -1,11 +1,8 @@ ItemDef( name: "Velorite Fragment", - description: "Increases Exp by 10\n\nSmall runes sparkle on its surface", - kind: Consumable( - kind: "VeloriteFrag", - effect: [ - /*Xp(10),*/ - ] + description: "Small runes sparkle on its surface", + kind: Ingredient( + kind: "VeloriteFrag", ), quality: Moderate, ) diff --git a/assets/common/loot_tables/loot_table_cultists.ron b/assets/common/loot_tables/loot_table_cultists.ron index b046ac92da..f6d17a68ce 100644 --- a/assets/common/loot_tables/loot_table_cultists.ron +++ b/assets/common/loot_tables/loot_table_cultists.ron @@ -211,7 +211,4 @@ (0.01, "common.items.armor.pants.cultist_legs_purple"), (0.01, "common.items.armor.shoulder.cultist_shoulder_purple"), (0.005, "common.items.armor.back.dungeon_purple-0"), - (0.1, "common.items.boss_drops.exp_flask"), - (0.2, "common.items.boss_drops.potions"), - ] diff --git a/assets/voxygen/i18n/en/hud/sct.ron b/assets/voxygen/i18n/en/hud/sct.ron index d8ed744fd1..e044a9ebb4 100644 --- a/assets/voxygen/i18n/en/hud/sct.ron +++ b/assets/voxygen/i18n/en/hud/sct.ron @@ -5,9 +5,8 @@ string_map: { // SCT outputs "hud.sct.experience": "{amount} Exp", - "hud.sct.block": "BLOCKED", - "hud.rank_up": "New Rank", - }, + "hud.sct.block": "BLOCKED", + }, vector_map: { diff --git a/assets/voxygen/i18n/en/skills.ron b/assets/voxygen/i18n/en/skills.ron new file mode 100644 index 0000000000..de1dd23b5d --- /dev/null +++ b/assets/voxygen/i18n/en/skills.ron @@ -0,0 +1,36 @@ +/// WARNING: Localization files shall be saved in UTF-8 format without BOM + +/// Localization for "global" English +( + string_map: { + "hud.rank_up": "New Skillpoint", + "hud.skills.sp_available": "{number} Skillpoints available", + "hud.skills.not_unlocked": "Not yet unlocked", + // Skills + // General Tree + "hud.skills.inc_health_title": "Increase Health", + "hud.skills.inc_health": "Increases max health by 5{}", + "hud.skills.inc_stam_title": "Increase Stamina", + "hud.skills.inc_stam": "Increases max stamina by 5{}", + "hud.skills.unlck_sword_title": "Unlock Sword", + "hud.skills.unlck_sword": "Unlocks sword skill tree{}", + "hud.skills.unlck_axe_title": "Unlock Axe", + "hud.skills.unlck_axe": "Unlocks axe skill tree{}", + "hud.skills.unlck_hammer_title": "Unlock Hammer", + "hud.skills.unlck_hammer": "Unlocks hammer skill tree{}", + "hud.skills.unlck_bow_title": "Unlock Bow", + "hud.skills.unlck_bow": "Unlocks bow skill tree{}", + "hud.skills.unlck_staff_title": "Unlock Staff", + "hud.skills.unlck_staff": "Unlocks staff skill tree{}", + "hud.skills.unlck_sceptre_title": "Unlock Sceptre", + "hud.skills.unlck_sceptre": "Unlocks sceptre skill tree{}", + "hud.skills.dodge_title": "Dodge", + "hud.skills.dodge": "Dodging avoids melee attacks{}", + "hud.skills.dodge_title": "Roll Stamina Cost", + "hud.skills.dodge": "Rolling uses 20% less stamina{}", + }, + + + vector_map: { + } +) diff --git a/common/src/comp/skills.rs b/common/src/comp/skills.rs index 37b71f8abf..ce98e4b1b8 100644 --- a/common/src/comp/skills.rs +++ b/common/src/comp/skills.rs @@ -222,7 +222,9 @@ pub enum SkillGroupType { impl SkillGroupType { /// Gets the cost in experience of earning a skill point - pub fn skill_point_cost(self) -> u16 { 200 } + pub fn skill_point_cost(self, level: u16) -> u16 { + 10 * (35.0 * (0.8 * level as f32 - 1.5).atan() + 50.0).floor() as u16 + } /// Gets the total amount of skill points that can be spent in a particular /// skill group @@ -549,6 +551,20 @@ impl SkillSet { && (sg.earned_sp - sg.available_sp) < sg.skill_group_type.get_max_skill_points() }) } + + /// Checks how much experience is needed for the next skill point in a tree + pub fn get_skill_point_cost(&self, skill_group: SkillGroupType) -> u16 { + if let Some(level) = self + .skill_groups + .iter() + .find(|sg| sg.skill_group_type == skill_group) + .map(|sg| sg.earned_sp) + { + skill_group.skill_point_cost(level) + } else { + skill_group.skill_point_cost(0) + } + } } impl Skill { diff --git a/common/sys/src/stats.rs b/common/sys/src/stats.rs index af5ca5ef5f..0433ad695a 100644 --- a/common/sys/src/stats.rs +++ b/common/sys/src/stats.rs @@ -86,7 +86,11 @@ impl<'a> System<'a> for Sys { let stat = stats.get_unchecked(); { for skill_group in stat.skill_set.skill_groups.iter() { - if skill_group.exp >= skill_group.skill_group_type.skill_point_cost() { + if skill_group.exp + >= stat + .skill_set + .get_skill_point_cost(skill_group.skill_group_type) + { skills_to_level.insert(skill_group.skill_group_type); } } @@ -95,8 +99,10 @@ impl<'a> System<'a> for Sys { if !skills_to_level.is_empty() { let mut stat = stats.get_mut_unchecked(); for skill_group in skills_to_level.drain() { - stat.skill_set - .change_experience(skill_group, -(skill_group.skill_point_cost() as i32)); + stat.skill_set.change_experience( + skill_group, + -(stat.skill_set.get_skill_point_cost(skill_group) as i32), + ); stat.skill_set.add_skill_points(skill_group, 1); outcomes.push(Outcome::SkillPointGain { uid: *uid, diff --git a/voxygen/src/hud/diary.rs b/voxygen/src/hud/diary.rs index 7657265df3..e0ee461e6f 100644 --- a/voxygen/src/hud/diary.rs +++ b/voxygen/src/hud/diary.rs @@ -355,7 +355,7 @@ impl<'a> Widget for Diary<'a> { } else { img.down_from(state.weapon_btns[i.0 - 1], tweak!(5.0)) }; - let tooltip_txt = if !locked { "" } else { "Not yet unlocked" }; + let tooltip_txt = if !locked { "" } else { &self.localized_strings.get("hud.skills.not_unlocked") }; img.w_h(tweak!(50.0), tweak!(50.0)) .set(state.weapon_imgs[i.0], ui); // Lock Image @@ -420,13 +420,13 @@ impl<'a> Widget for Diary<'a> { } // Exp Bars and Rank Display let current_exp = self.stats.skill_set.get_experience(*sel_tab) as f64; - let max_exp = sel_tab.skill_point_cost() as f64; + let max_exp = self.stats.skill_set.get_skill_point_cost(*sel_tab) as f64; let exp_percentage = current_exp / max_exp; let rank = self.stats.skill_set.get_earned_sp(*sel_tab); let rank_txt = format!("{}", rank); let exp_txt = format!("{}/{}", current_exp, max_exp); let available_pts = self.stats.skill_set.get_available_sp(*sel_tab); - let available_pts_txt = format!("{} SP available!", available_pts); + let available_pts_txt = format!("{}", available_pts); Image::new(self.imgs.diary_exp_bg) .w_h(480.0, 76.0) .mid_bottom_with_margin_on(state.content_align, tweak!(10.0)) @@ -465,8 +465,8 @@ impl<'a> Widget for Diary<'a> { .color(TEXT_COLOR) .set(state.exp_bar_rank, ui); if available_pts > 0 { - Text::new(&available_pts_txt) - .mid_top_with_margin_on(state.content_align, tweak!(42.0)) + Text::new(&self.localized_strings.get("hud.skills.sp_available").replace("{number}", &available_pts_txt)) + .mid_top_with_margin_on(state.content_align, tweak!(700.0)) .font_id(self.fonts.cyri.conrod_id) .font_size(self.fonts.cyri.scale(tweak!(28))) .color(Color::Rgba(0.92, 0.76, 0.0, frame_ani)) @@ -677,9 +677,9 @@ impl<'a> Widget for Diary<'a> { ) .with_tooltip( self.tooltip_manager, - "Increase Health", + &self.localized_strings.get("hud.skills.inc_health_title"), &add_sp_cost_tooltip( - "Increases max health by 5{}", + &self.localized_strings.get("hud.skills.inc_health"), skill, &self.stats.skill_set, ), @@ -702,9 +702,9 @@ impl<'a> Widget for Diary<'a> { ) .with_tooltip( self.tooltip_manager, - "Increase Stamina", + &self.localized_strings.get("hud.skills.inc_stam_title"), &add_sp_cost_tooltip( - "Increases max stamina by 5{}", + &self.localized_strings.get("hud.skills.inc_stam"), skill, &self.stats.skill_set, ), @@ -728,9 +728,9 @@ impl<'a> Widget for Diary<'a> { ) .with_tooltip( self.tooltip_manager, - "Unlock Sword", + &self.localized_strings.get("hud.skills.unlck_sword_title"), &add_sp_cost_tooltip( - "Unlocks sword skill tree{}", + &self.localized_strings.get("hud.skills.unlck_sword"), skill, &self.stats.skill_set, ), @@ -753,8 +753,8 @@ impl<'a> Widget for Diary<'a> { ) .with_tooltip( self.tooltip_manager, - "Unlock Axe", - &add_sp_cost_tooltip("Unlocks axe skill tree{}", skill, &self.stats.skill_set), + &self.localized_strings.get("hud.skills.unlck_axe_title"), + &add_sp_cost_tooltip(&self.localized_strings.get("hud.skills.unlck_axe"), skill, &self.stats.skill_set), &diary_tooltip, TEXT_COLOR, ) @@ -774,9 +774,9 @@ impl<'a> Widget for Diary<'a> { ) .with_tooltip( self.tooltip_manager, - "Unlock Hammer", + &self.localized_strings.get("hud.skills.unlck_hammer_title"), &add_sp_cost_tooltip( - "Unlocks hammer skill tree{}", + &self.localized_strings.get("hud.skills.unlck_hammer"), skill, &self.stats.skill_set, ), @@ -799,8 +799,8 @@ impl<'a> Widget for Diary<'a> { ) .with_tooltip( self.tooltip_manager, - "Unlock Bow", - &add_sp_cost_tooltip("Unlocks bow skill tree{}", skill, &self.stats.skill_set), + &self.localized_strings.get("hud.skills.unlck_bow_title"), + &add_sp_cost_tooltip(&self.localized_strings.get("hud.skills.unlck_bow"), skill, &self.stats.skill_set), &diary_tooltip, TEXT_COLOR, ) @@ -820,9 +820,9 @@ impl<'a> Widget for Diary<'a> { ) .with_tooltip( self.tooltip_manager, - "Unlock Staff", + &self.localized_strings.get("hud.skills.unlck_staff_title"), &add_sp_cost_tooltip( - "Unlocks staff skill tree{}", + &self.localized_strings.get("hud.skills.unlck_staff"), skill, &self.stats.skill_set, ), @@ -845,9 +845,9 @@ impl<'a> Widget for Diary<'a> { ) .with_tooltip( self.tooltip_manager, - "Unlock Sceptre", + &self.localized_strings.get("hud.skills.unlck_sceptre_title"), &add_sp_cost_tooltip( - "Unlocks sceptre skill tree{}", + &self.localized_strings.get("hud.skills.unlck_sceptre"), skill, &self.stats.skill_set, ), @@ -871,9 +871,9 @@ impl<'a> Widget for Diary<'a> { ) .with_tooltip( self.tooltip_manager, - "Dodge", + &self.localized_strings.get("hud.skills.dodge_title"), &add_sp_cost_tooltip( - "While rolling, you dodge all melee attacks{}", + &self.localized_strings.get("hud.skills.dodge"), skill, &self.stats.skill_set, ), @@ -3081,7 +3081,6 @@ fn create_skill_button<'a>( } else { CRITICAL_HP_COLOR }) - .label_color(TEXT_COLOR) .label_font_size(fonts.cyri.scale(tweak!(16))) .label_font_id(fonts.cyri.conrod_id) .image_color(if skill_set.prerequisites_met(skill) { diff --git a/voxygen/src/hud/group.rs b/voxygen/src/hud/group.rs index 6c7ddfb6e4..0c58e1f693 100644 --- a/voxygen/src/hud/group.rs +++ b/voxygen/src/hud/group.rs @@ -25,6 +25,7 @@ use conrod_core::{ widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; use specs::{saveload::MarkerAllocator, WorldExt}; + widget_ids! { pub struct Ids { group_button, @@ -351,7 +352,7 @@ impl<'a> Widget for Group<'a> { let y = if debug_on { i % 8 } else { i % 12 }; let back = Image::new(self.imgs.member_bg).top_left_with_margins_on( ui.window, - 50.0 + offset + y as f64 * 65.0, + 50.0 + offset + y as f64 * 77.0, 10.0 + x as f64 * 180.0, ); let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer diff --git a/voxygen/src/hud/overhead.rs b/voxygen/src/hud/overhead.rs index acd62f4e3a..44947d6f86 100644 --- a/voxygen/src/hud/overhead.rs +++ b/voxygen/src/hud/overhead.rs @@ -283,15 +283,17 @@ impl<'a> Widget for Overhead<'a> { .set(timer_id, ui); }); } - // Name - Text::new(name) + // Name + // Text::new(name) + Text::new(&format!("{} [{:?}]", name, combat_rating)) // <- Uncomment to debug combat ratings .font_id(self.fonts.cyri.conrod_id) .font_size(font_size) .color(Color::Rgba(0.0, 0.0, 0.0, 1.0)) .x_y(-1.0, name_y) .parent(id) .set(state.ids.name_bg, ui); - Text::new(name) + // Text::new(name) + Text::new(&format!("{} [{:?}]", name, combat_rating)) // <- Uncomment to debug combat ratings .font_id(self.fonts.cyri.conrod_id) .font_size(font_size) .color(if self.in_group { @@ -373,31 +375,35 @@ impl<'a> Widget for Overhead<'a> { .parent(id) .set(state.ids.health_bar_fg, ui); - // TODO: Add strength comparison here, this is just an example - // Factors to take into account: - // Maximum HP - // Protection - // Mainhand Weapon DPS - // "Boss Factor" (?) - // For players: Highest skilltree rank + // TODO: Add strength comparison here, this is just an example + + // Thresholds (lower) + let common = tweak!(4.3); + let moderate = tweak!(6.0); + let high = tweak!(10.8); + let epic = tweak!(14.1); + let legendary = tweak!(79.0); + let artifact = tweak!(122.0); + let debug = tweak!(200.0); let indicator_col = match combat_rating { - x if (0.0..0.5).contains(&x) => QUALITY_LOW, - x if (0.5..1.0).contains(&x) => QUALITY_COMMON, - x if (1.0..1.5).contains(&x) => QUALITY_MODERATE, - x if (1.5..2.0).contains(&x) => QUALITY_HIGH, - x if (2.0..2.5).contains(&x) => QUALITY_EPIC, - x if (2.5..3.0).contains(&x) => QUALITY_LEGENDARY, - x if (2.0..3.5).contains(&x) => QUALITY_ARTIFACT, - x if x >= 3.5 => QUALITY_DEBUG, + x if (0.0..common).contains(&x) => QUALITY_LOW, + x if (common..moderate).contains(&x) => QUALITY_COMMON, + x if (moderate..high).contains(&x) => QUALITY_MODERATE, + x if (high..epic).contains(&x) => QUALITY_HIGH, + x if (epic..legendary).contains(&x) => QUALITY_EPIC, + x if (legendary..artifact).contains(&x) => QUALITY_LEGENDARY, + x if (artifact..debug).contains(&x) => QUALITY_ARTIFACT, + x if x >= debug => QUALITY_DEBUG, _ => XP_COLOR, - }; + }; + Image::new(self.imgs.indicator_bubble) .w_h(5.0 * BARSIZE, 5.0 * BARSIZE) .x_y(tweak!(-37.0) * BARSIZE, MANA_BAR_Y + tweak!(7.5)) .color(Some(indicator_col)) .parent(id) - .set(state.ids.level, ui); + .set(state.ids.level, ui); } } // Speech bubble diff --git a/voxygen/src/hud/social.rs b/voxygen/src/hud/social.rs index fb0dd8e63e..91a1c71daa 100644 --- a/voxygen/src/hud/social.rs +++ b/voxygen/src/hud/social.rs @@ -304,7 +304,7 @@ impl<'a> Widget for Social<'a> { if Button::image(self.imgs.nothing) .w_h(133.0, 18.0) .mid_top_with_margin_on(state.ids.frame, 52.0) - .label(&self.localized_strings.get("hud.social.name")) + .label(&self.localized_strings.get("")) .label_font_size(self.fonts.cyri.scale(14)) .label_y(conrod_core::position::Relative::Scalar(0.0)) .label_font_id(self.fonts.cyri.conrod_id)