diff --git a/CHANGELOG.md b/CHANGELOG.md index 4466ae1851..99fa93a4cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -85,6 +85,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Meat drops from animals - New ores, plants and hides to be looted from the world and processed into craft ingredients - Added more crafting stations, loom, spinning wheel, tanning rack, forge +- Added a skill tree for mining, which gains xp from mining ores and gems. ### Changed diff --git a/assets/common/skill_trees/skill_max_levels.ron b/assets/common/skill_trees/skill_max_levels.ron index 275c23b15b..a319299903 100644 --- a/assets/common/skill_trees/skill_max_levels.ron +++ b/assets/common/skill_trees/skill_max_levels.ron @@ -76,4 +76,7 @@ Climb(Cost): Some(2), Climb(Speed): Some(2), Swim(Speed): Some(2), + Pick(Speed): Some(3), + Pick(OreGain): Some(3), + Pick(GemGain): Some(3), }) diff --git a/assets/common/skill_trees/skills_skill-groups_manifest.ron b/assets/common/skill_trees/skills_skill-groups_manifest.ron index 220f2b1e97..641ba74520 100644 --- a/assets/common/skill_trees/skills_skill-groups_manifest.ron +++ b/assets/common/skill_trees/skills_skill-groups_manifest.ron @@ -109,4 +109,9 @@ Sceptre(ARange), Sceptre(ACost), ], + Weapon(Pick): [ + Pick(Speed), + Pick(OreGain), + Pick(GemGain), + ], }) diff --git a/assets/server/manifests/resource_experience_manifest.ron b/assets/server/manifests/resource_experience_manifest.ron new file mode 100644 index 0000000000..6345e0d392 --- /dev/null +++ b/assets/server/manifests/resource_experience_manifest.ron @@ -0,0 +1,19 @@ +ResourceExperienceManifest({ + "common.items.mineral.gem.amethyst": 20, + "common.items.mineral.gem.sapphire": 50, + "common.items.mineral.gem.topaz": 20, + "common.items.mineral.gem.diamond": 100, + "common.items.mineral.gem.emerald": 50, + "common.items.mineral.gem.ruby": 75, + + "common.items.mineral.ore.coal": 25, + "common.items.mineral.ore.gold": 100, + "common.items.mineral.ore.iron": 20, + "common.items.mineral.ore.silver": 75, + "common.items.mineral.ore.velorite": 30, + "common.items.mineral.ore.veloritefrag": 20, + "common.items.mineral.ore.bloodstone": 100, + "common.items.mineral.ore.cobalt": 75, + "common.items.mineral.ore.copper": 10, + "common.items.mineral.ore.tin": 10, +}) diff --git a/assets/voxygen/element/skills/pickaxe_gemgain.png b/assets/voxygen/element/skills/pickaxe_gemgain.png new file mode 100644 index 0000000000..3615cd1d7d --- /dev/null +++ b/assets/voxygen/element/skills/pickaxe_gemgain.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87cb3de9b1db989b909b5db2b4d4f0f91773f881df5caeac5e7b92644c52b955 +size 1780 diff --git a/assets/voxygen/element/skills/pickaxe_oregain.png b/assets/voxygen/element/skills/pickaxe_oregain.png new file mode 100644 index 0000000000..9d42b64f7d --- /dev/null +++ b/assets/voxygen/element/skills/pickaxe_oregain.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b3de05de2d4ca7a76769aa93369c92bbd18fe98c2b337a412c380d726808e4e +size 1790 diff --git a/assets/voxygen/element/skills/pickaxe_speed.png b/assets/voxygen/element/skills/pickaxe_speed.png new file mode 100644 index 0000000000..7a462f3940 --- /dev/null +++ b/assets/voxygen/element/skills/pickaxe_speed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27f66e968c4f475123d726c096e80bb34c2ebea856c4c0bf1d20969ac4d01dbc +size 1734 diff --git a/assets/voxygen/element/weapons/pickaxe.png b/assets/voxygen/element/weapons/pickaxe.png new file mode 100644 index 0000000000..0f4ec67ac9 --- /dev/null +++ b/assets/voxygen/element/weapons/pickaxe.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff8c3173b5d87c4bf00233d222d2b47045bbb3cf602afea5814d85167ce9f9da +size 1720 diff --git a/assets/voxygen/i18n/en/skills.ron b/assets/voxygen/i18n/en/skills.ron index 93ae9ffb7e..66250941ff 100644 --- a/assets/voxygen/i18n/en/skills.ron +++ b/assets/voxygen/i18n/en/skills.ron @@ -238,6 +238,15 @@ "hud.skill.axe_leap_cost": "Decreases cost of leap by 25%{SP}", "hud.skill.axe_leap_distance_title": "Leap Distance", "hud.skill.axe_leap_distance": "Increases distance of leap by 20%{SP}", + // Pick + "hud.skill.pick_strike_title": "Pickaxe Strike", + "hud.skill.pick_strike": "Hit rocks with the pickaxe to gain ore and gems and experience", + "hud.skill.pick_strike_speed_title": "Pickaxe Strike Speed", + "hud.skill.pick_strike_speed": "Mine rocks faster{SP}", + "hud.skill.pick_strike_oregain_title": "Pickaxe Strike Ore Yield", + "hud.skill.pick_strike_oregain": "Chance to gain extra ore (5% per level){SP}", + "hud.skill.pick_strike_gemgain_title": "Pickaxe Strike Gem Yield", + "hud.skill.pick_strike_gemgain": "Chance to gain extra gems (5% per level){SP}", }, diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron index 5bb8796f1c..e0d711ad6a 100644 --- a/assets/voxygen/item_image_manifest.ron +++ b/assets/voxygen/item_image_manifest.ron @@ -65,6 +65,10 @@ "voxel.weapon.sceptre.wood-nature", (-1.0, 0.0, 0.0), (-90.0, 55.0, 0.0), 1.0, ), + Tool("example_pick"): VoxTrans( + "voxel.weapon.tool.pickaxe_green-0", + (0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.0, + ), Tool("example_dagger"): VoxTrans( "voxel.weapon.dagger.dagger_basic-0", (0.0, 0.0, 0.0), (90.0, 90.0, 0.0), 1.0, diff --git a/common/src/cmd.rs b/common/src/cmd.rs index e8f9054605..d8752cffd5 100644 --- a/common/src/cmd.rs +++ b/common/src/cmd.rs @@ -127,7 +127,7 @@ lazy_static! { .iter() .map(|s| s.to_string()) .collect(); - static ref SKILL_TREES: Vec = vec!["general", "sword", "axe", "hammer", "bow", "staff", "sceptre"] + static ref SKILL_TREES: Vec = vec!["general", "sword", "axe", "hammer", "bow", "staff", "sceptre", "pick"] .iter() .map(|s| s.to_string()) .collect(); diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 8ab75b8928..bab3f56117 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -1174,6 +1174,23 @@ impl CharacterAbility { _ => {}, } }, + Some(ToolKind::Pick) => { + use skills::PickSkill::*; + if let BasicMelee { + ref mut buildup_duration, + ref mut swing_duration, + ref mut recover_duration, + .. + } = self + { + if let Ok(Some(level)) = skillset.skill_level(Pick(Speed)) { + let speed = 1.1_f32.powi(level.into()); + *buildup_duration /= speed; + *swing_duration /= speed; + *recover_duration /= speed; + } + } + }, None => { if let CharacterAbility::Roll { ref mut energy_cost, diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index e91b52c0de..c0f3ee2d03 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -50,6 +50,21 @@ impl ToolKind { ToolKind::Empty => "empty", } } + + pub fn gains_combat_xp(&self) -> bool { + matches!( + self, + ToolKind::Sword + | ToolKind::Axe + | ToolKind::Hammer + | ToolKind::Bow + | ToolKind::Dagger + | ToolKind::Staff + | ToolKind::Spear + | ToolKind::Sceptre + | ToolKind::Shield + ) + } } #[derive(Clone, Copy, Debug, Serialize, Deserialize)] diff --git a/common/src/comp/skills.rs b/common/src/comp/skills.rs index e1c113d8f2..c130b067c9 100644 --- a/common/src/comp/skills.rs +++ b/common/src/comp/skills.rs @@ -107,6 +107,7 @@ pub enum Skill { Roll(RollSkill), Climb(ClimbSkill), Swim(SwimSkill), + Pick(PickSkill), } pub enum SkillError { @@ -263,6 +264,13 @@ pub enum SwimSkill { Speed, } +#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] +pub enum PickSkill { + Speed, + OreGain, + GemGain, +} + #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)] pub enum SkillGroupKind { General, @@ -344,7 +352,10 @@ impl Default for SkillSet { /// player fn default() -> Self { Self { - skill_groups: vec![SkillGroup::new(SkillGroupKind::General)], + skill_groups: vec![ + SkillGroup::new(SkillGroupKind::General), + SkillGroup::new(SkillGroupKind::Weapon(ToolKind::Pick)), + ], skills: HashMap::new(), modify_health: false, modify_energy: false, @@ -365,7 +376,7 @@ impl SkillSet { /// let mut skillset = SkillSet::default(); /// skillset.unlock_skill_group(SkillGroupKind::Weapon(ToolKind::Sword)); /// - /// assert_eq!(skillset.skill_groups.len(), 2); + /// assert_eq!(skillset.skill_groups.len(), 3); /// ``` pub fn unlock_skill_group(&mut self, skill_group_kind: SkillGroupKind) { if !self.contains_skill_group(skill_group_kind) { @@ -668,13 +679,13 @@ mod tests { skillset.add_skill_points(SkillGroupKind::Weapon(ToolKind::Axe), 1); skillset.unlock_skill(Skill::Axe(AxeSkill::UnlockLeap)); - assert_eq!(skillset.skill_groups[1].available_sp, 0); + assert_eq!(skillset.skill_groups[2].available_sp, 0); assert_eq!(skillset.skills.len(), 1); assert!(skillset.has_skill(Skill::Axe(AxeSkill::UnlockLeap))); skillset.refund_skill(Skill::Axe(AxeSkill::UnlockLeap)); - assert_eq!(skillset.skill_groups[1].available_sp, 1); + assert_eq!(skillset.skill_groups[2].available_sp, 1); assert_eq!(skillset.skills.get(&Skill::Axe(AxeSkill::UnlockLeap)), None); } @@ -683,9 +694,9 @@ mod tests { let mut skillset = SkillSet::default(); skillset.unlock_skill_group(SkillGroupKind::Weapon(ToolKind::Axe)); - assert_eq!(skillset.skill_groups.len(), 2); + assert_eq!(skillset.skill_groups.len(), 3); assert_eq!( - skillset.skill_groups[1], + skillset.skill_groups[2], SkillGroup::new(SkillGroupKind::Weapon(ToolKind::Axe)) ); } @@ -697,13 +708,13 @@ mod tests { skillset.unlock_skill_group(SkillGroupKind::Weapon(ToolKind::Axe)); skillset.add_skill_points(SkillGroupKind::Weapon(ToolKind::Axe), 1); - assert_eq!(skillset.skill_groups[1].available_sp, 1); + assert_eq!(skillset.skill_groups[2].available_sp, 1); assert_eq!(skillset.skills.len(), 0); // Try unlocking a skill with enough skill points skillset.unlock_skill(Skill::Axe(AxeSkill::UnlockLeap)); - assert_eq!(skillset.skill_groups[1].available_sp, 0); + assert_eq!(skillset.skill_groups[2].available_sp, 0); assert_eq!(skillset.skills.len(), 1); assert!(skillset.has_skill(Skill::Axe(AxeSkill::UnlockLeap))); @@ -720,6 +731,6 @@ mod tests { skillset.unlock_skill_group(SkillGroupKind::Weapon(ToolKind::Axe)); skillset.add_skill_points(SkillGroupKind::Weapon(ToolKind::Axe), 1); - assert_eq!(skillset.skill_groups[1].available_sp, 1); + assert_eq!(skillset.skill_groups[2].available_sp, 1); } } diff --git a/common/src/event.rs b/common/src/event.rs index 1c507d0876..d21eee05c5 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -164,6 +164,7 @@ pub enum ServerEvent { }, // Attempt to mine a block, turning it into an item MineBlock { + entity: EcsEntity, pos: Vec3, tool: Option, }, diff --git a/common/systems/src/melee.rs b/common/systems/src/melee.rs index 561b9a4b5b..46a3b004fd 100644 --- a/common/systems/src/melee.rs +++ b/common/systems/src/melee.rs @@ -86,6 +86,7 @@ impl<'a> System<'a> for Sys { < (rad + scale * melee_attack.range).powi(2) { server_emitter.emit(ServerEvent::MineBlock { + entity: attacker, pos: block_pos, tool, }); diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 926b439588..eb6af36349 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -2610,6 +2610,7 @@ fn parse_skill_tree(skill_tree: &str) -> CmdResult "bow" => Ok(SkillGroupKind::Weapon(ToolKind::Bow)), "staff" => Ok(SkillGroupKind::Weapon(ToolKind::Staff)), "sceptre" => Ok(SkillGroupKind::Weapon(ToolKind::Sceptre)), + "pick" => Ok(SkillGroupKind::Weapon(ToolKind::Pick)), _ => Err(format!("{} is not a skill group!", skill_tree)), } } diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 78b14d3517..c559ba19b6 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -992,13 +992,12 @@ fn handle_exp_gain( // Closure to add xp pool corresponding to weapon type equipped in a particular // EquipSlot let mut add_tool_from_slot = |equip_slot| { - let tool_kind = inventory.equipped(equip_slot).and_then(|i| { - if let ItemKind::Tool(tool) = &i.kind() { - Some(tool.kind) - } else { - None - } - }); + let tool_kind = inventory + .equipped(equip_slot) + .and_then(|i| match &i.kind() { + ItemKind::Tool(tool) if tool.kind.gains_combat_xp() => Some(tool.kind), + _ => None, + }); if let Some(weapon) = tool_kind { // Only adds to xp pools if entity has that skill group available if skill_set.contains_skill_group(SkillGroupKind::Weapon(weapon)) { diff --git a/server/src/events/interaction.rs b/server/src/events/interaction.rs index e8c4a5e0e9..3220a8a25b 100644 --- a/server/src/events/interaction.rs +++ b/server/src/events/interaction.rs @@ -3,6 +3,7 @@ use tracing::error; use vek::*; use common::{ + assets, comp::{ self, agent::{AgentEvent, Sound, MAX_LISTEN_DIST}, @@ -11,7 +12,7 @@ use common::{ item, slot::Slot, tool::ToolKind, - Inventory, Pos, + Inventory, Pos, SkillGroupKind, }, consts::{MAX_MOUNT_RANGE, SOUND_TRAVEL_DIST_PER_VOLUME}, outcome::Outcome, @@ -27,6 +28,10 @@ use crate::{ Server, }; +use hashbrown::HashMap; +use lazy_static::lazy_static; +use serde::Deserialize; + pub fn handle_lantern(server: &mut Server, entity: EcsEntity, enable: bool) { let ecs = server.state_mut().ecs(); @@ -281,13 +286,80 @@ fn within_mounting_range(player_position: Option<&Pos>, mount_position: Option<& } } -pub fn handle_mine_block(server: &mut Server, pos: Vec3, tool: Option) { +#[derive(Deserialize)] +struct ResourceExperienceManifest(HashMap); + +impl assets::Asset for ResourceExperienceManifest { + type Loader = assets::RonLoader; + + const EXTENSION: &'static str = "ron"; +} + +lazy_static! { + static ref RESOURCE_EXPERIENCE_MANIFEST: assets::AssetHandle = + assets::AssetExt::load_expect("server.manifests.resource_experience_manifest"); +} + +pub fn handle_mine_block( + server: &mut Server, + entity: EcsEntity, + pos: Vec3, + tool: Option, +) { let state = server.state_mut(); if state.can_set_block(pos) { let block = state.terrain().get(pos).ok().copied(); if let Some(block) = block.filter(|b| b.mine_tool().map_or(false, |t| Some(t) == tool)) { // Drop item if one is recoverable from the block - if let Some(item) = comp::Item::try_reclaim_from_block(block) { + if let Some(mut item) = comp::Item::try_reclaim_from_block(block) { + if let Some(mut skillset) = state + .ecs() + .write_storage::() + .get_mut(entity) + { + if let (Some(tool), Some(uid), Some(exp_reward)) = ( + tool, + state.ecs().uid_from_entity(entity), + RESOURCE_EXPERIENCE_MANIFEST + .read() + .0 + .get(item.item_definition_id()), + ) { + skillset.change_experience(SkillGroupKind::Weapon(tool), *exp_reward); + state + .ecs() + .write_resource::>() + .push(Outcome::ExpChange { + uid, + exp: *exp_reward, + }); + } + use common::comp::skills::{PickSkill, Skill}; + use rand::Rng; + let mut rng = rand::thread_rng(); + if item.item_definition_id().contains("mineral.ore.") + && rng.gen_bool( + 0.05 * skillset + .skill_level(Skill::Pick(PickSkill::OreGain)) + .ok() + .flatten() + .unwrap_or(0) as f64, + ) + { + let _ = item.increase_amount(1); + } + if item.item_definition_id().contains("mineral.gem.") + && rng.gen_bool( + 0.05 * skillset + .skill_level(Skill::Pick(PickSkill::GemGain)) + .ok() + .flatten() + .unwrap_or(0) as f64, + ) + { + let _ = item.increase_amount(1); + } + } state .create_object(Default::default(), comp::object::Body::Pouch) .with(comp::Pos(pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0))) diff --git a/server/src/events/mod.rs b/server/src/events/mod.rs index c808e8f28a..7079b3bda3 100644 --- a/server/src/events/mod.rs +++ b/server/src/events/mod.rs @@ -207,7 +207,9 @@ impl Server { handle_combo_change(&self, entity, change) }, ServerEvent::RequestSiteInfo { entity, id } => handle_site_info(&self, entity, id), - ServerEvent::MineBlock { pos, tool } => handle_mine_block(self, pos, tool), + ServerEvent::MineBlock { entity, pos, tool } => { + handle_mine_block(self, entity, pos, tool) + }, ServerEvent::TeleportTo { entity, target, diff --git a/server/src/migrations/V41__mining_tree.sql b/server/src/migrations/V41__mining_tree.sql new file mode 100644 index 0000000000..e4cd339df7 --- /dev/null +++ b/server/src/migrations/V41__mining_tree.sql @@ -0,0 +1,7 @@ +-- Every character should have the pick skilltree unlocked by default. +-- This is handled by `SkillSet::default()` for new characters (and their skill +-- sets serialize properly during character creation), but since the database +-- deserialization builds the SkillSet fields from empty Vecs/HashMaps, the skill +-- tree needs to manually be added to each character. +INSERT INTO skill_group (entity_id, skill_group_kind, exp, available_sp, earned_sp) + SELECT character_id, 'Weapon Pick', 0, 0, 0 FROM character; diff --git a/server/src/persistence/json_models.rs b/server/src/persistence/json_models.rs index 81d9531022..b74955ae46 100644 --- a/server/src/persistence/json_models.rs +++ b/server/src/persistence/json_models.rs @@ -40,8 +40,8 @@ pub fn skill_to_db_string(skill: comp::skills::Skill) -> String { use comp::{ item::tool::ToolKind, skills::{ - AxeSkill, BowSkill, ClimbSkill, GeneralSkill, HammerSkill, RollSkill, SceptreSkill, - Skill::*, SkillGroupKind, StaffSkill, SwimSkill, SwordSkill, + AxeSkill, BowSkill, ClimbSkill, GeneralSkill, HammerSkill, PickSkill, RollSkill, + SceptreSkill, Skill::*, SkillGroupKind, StaffSkill, SwimSkill, SwordSkill, }, }; let skill_string = match skill { @@ -135,6 +135,9 @@ pub fn skill_to_db_string(skill: comp::skills::Skill) -> String { Climb(ClimbSkill::Cost) => "Climb Cost", Climb(ClimbSkill::Speed) => "Climb Speed", Swim(SwimSkill::Speed) => "Swim Speed", + Pick(PickSkill::Speed) => "Pick Speed", + Pick(PickSkill::OreGain) => "Pick OreGain", + Pick(PickSkill::GemGain) => "Pick GemGain", UnlockGroup(SkillGroupKind::Weapon(ToolKind::Sword)) => "Unlock Weapon Sword", UnlockGroup(SkillGroupKind::Weapon(ToolKind::Axe)) => "Unlock Weapon Axe", UnlockGroup(SkillGroupKind::Weapon(ToolKind::Hammer)) => "Unlock Weapon Hammer", @@ -160,8 +163,8 @@ pub fn db_string_to_skill(skill_string: &str) -> comp::skills::Skill { use comp::{ item::tool::ToolKind, skills::{ - AxeSkill, BowSkill, ClimbSkill, GeneralSkill, HammerSkill, RollSkill, SceptreSkill, - Skill::*, SkillGroupKind, StaffSkill, SwimSkill, SwordSkill, + AxeSkill, BowSkill, ClimbSkill, GeneralSkill, HammerSkill, PickSkill, RollSkill, + SceptreSkill, Skill::*, SkillGroupKind, StaffSkill, SwimSkill, SwordSkill, }, }; match skill_string { @@ -255,6 +258,9 @@ pub fn db_string_to_skill(skill_string: &str) -> comp::skills::Skill { "Climb Cost" => Climb(ClimbSkill::Cost), "Climb Speed" => Climb(ClimbSkill::Speed), "Swim Speed" => Swim(SwimSkill::Speed), + "Pick Speed" => Pick(PickSkill::Speed), + "Pick GemGain" => Pick(PickSkill::GemGain), + "Pick OreGain" => Pick(PickSkill::OreGain), "Unlock Weapon Sword" => UnlockGroup(SkillGroupKind::Weapon(ToolKind::Sword)), "Unlock Weapon Axe" => UnlockGroup(SkillGroupKind::Weapon(ToolKind::Axe)), "Unlock Weapon Hammer" => UnlockGroup(SkillGroupKind::Weapon(ToolKind::Hammer)), @@ -280,12 +286,12 @@ pub fn skill_group_to_db_string(skill_group: comp::skills::SkillGroupKind) -> St Weapon(ToolKind::Bow) => "Weapon Bow", Weapon(ToolKind::Staff) => "Weapon Staff", Weapon(ToolKind::Sceptre) => "Weapon Sceptre", + Weapon(ToolKind::Pick) => "Weapon Pick", Weapon(ToolKind::Dagger) | Weapon(ToolKind::Shield) | Weapon(ToolKind::Spear) | Weapon(ToolKind::Debug) | Weapon(ToolKind::Farming) - | Weapon(ToolKind::Pick) | Weapon(ToolKind::Empty) | Weapon(ToolKind::Natural) => panic!( "Tried to add unsupported skill group to database: {:?}", @@ -305,6 +311,7 @@ pub fn db_string_to_skill_group(skill_group_string: &str) -> comp::skills::Skill "Weapon Bow" => Weapon(ToolKind::Bow), "Weapon Staff" => Weapon(ToolKind::Staff), "Weapon Sceptre" => Weapon(ToolKind::Sceptre), + "Weapon Pick" => Weapon(ToolKind::Pick), _ => panic!( "Tried to convert an unsupported string from the database: {}", skill_group_string diff --git a/voxygen/src/hud/diary.rs b/voxygen/src/hud/diary.rs index 2e679c6362..48182bda38 100644 --- a/voxygen/src/hud/diary.rs +++ b/voxygen/src/hud/diary.rs @@ -149,6 +149,11 @@ widget_ids! { skill_sceptre_aura_2, skill_sceptre_aura_3, skill_sceptre_aura_4, + pick_render, + skill_pick_m1, + skill_pick_m1_0, + skill_pick_m1_1, + skill_pick_m1_2, general_combat_render_0, general_combat_render_1, skill_general_stat_0, @@ -227,7 +232,7 @@ impl<'a> Diary<'a> { pub type SelectedSkillTree = skills::SkillGroupKind; -const TREES: [&str; 7] = [ +const TREES: [&str; 8] = [ "General Combat", "Sword", "Hammer", @@ -235,6 +240,7 @@ const TREES: [&str; 7] = [ "Sceptre", "Bow", "Fire Staff", + "Pickaxe", ]; pub enum Event { @@ -353,6 +359,7 @@ impl<'a> Widget for Diary<'a> { "Sceptre" => self.imgs.sceptre, "Bow" => self.imgs.bow, "Fire Staff" => self.imgs.staff, + "Pickaxe" => self.imgs.pickaxe, _ => self.imgs.nothing, }); @@ -500,6 +507,9 @@ impl<'a> Widget for Diary<'a> { SelectedSkillTree::Weapon(ToolKind::Staff) => { self.localized_strings.get("common.weapons.staff") }, + SelectedSkillTree::Weapon(ToolKind::Pick) => { + self.localized_strings.get("common.tool.pick") + }, _ => "Unknown", }; self.create_new_text(&tree_title, state.content_align, 2.0, 34, TEXT_COLOR) @@ -531,6 +541,7 @@ impl<'a> Widget for Diary<'a> { SelectedSkillTree::Weapon(ToolKind::Bow) => 6, SelectedSkillTree::Weapon(ToolKind::Staff) => 4, SelectedSkillTree::Weapon(ToolKind::Sceptre) => 5, + SelectedSkillTree::Weapon(ToolKind::Pick) => 4, _ => 0, }; let skills_top_r = match sel_tab { @@ -1976,6 +1987,65 @@ impl<'a> Widget for Diary<'a> { &diary_tooltip, ); }, + SelectedSkillTree::Weapon(ToolKind::Pick) => { + use skills::PickSkill::*; + // Pick + Image::new(animate_by_pulse( + &self + .item_imgs + .img_ids_or_not_found_img(Tool("example_pick".to_string())), + self.pulse, + )) + .wh(art_size) + .middle_of(state.content_align) + .color(Some(Color::Rgba(1.0, 1.0, 1.0, 1.0))) + .set(state.pick_render, ui); + // Top Left skills + // 5 1 6 + // 3 0 4 + // 8 2 7 + Button::image(self.imgs.pickaxe) + .w_h(74.0, 74.0) + .mid_top_with_margin_on(state.skills_top_l[0], 3.0) + .with_tooltip( + self.tooltip_manager, + &self.localized_strings.get("hud.skill.pick_strike_title"), + &self.localized_strings.get("hud.skill.pick_strike"), + &diary_tooltip, + TEXT_COLOR, + ) + .set(state.skill_pick_m1, ui); + self.create_unlock_skill_button( + Skill::Pick(Speed), + self.imgs.pickaxe_speed_skill, + state.skills_top_l[1], + "pick_strike_speed", + state.skill_pick_m1_0, + ui, + &mut events, + &diary_tooltip, + ); + self.create_unlock_skill_button( + Skill::Pick(OreGain), + self.imgs.pickaxe_oregain_skill, + state.skills_top_l[2], + "pick_strike_oregain", + state.skill_pick_m1_1, + ui, + &mut events, + &diary_tooltip, + ); + self.create_unlock_skill_button( + Skill::Pick(GemGain), + self.imgs.pickaxe_gemgain_skill, + state.skills_top_l[3], + "pick_strike_gemgain", + state.skill_pick_m1_2, + ui, + &mut events, + &diary_tooltip, + ); + }, _ => {}, } @@ -2034,6 +2104,7 @@ fn skill_tree_from_str(string: &str) -> Option { "Sceptre" => Some(SelectedSkillTree::Weapon(ToolKind::Sceptre)), "Bow" => Some(SelectedSkillTree::Weapon(ToolKind::Bow)), "Fire Staff" => Some(SelectedSkillTree::Weapon(ToolKind::Staff)), + "Pickaxe" => Some(SelectedSkillTree::Weapon(ToolKind::Pick)), _ => None, } } diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index f96bd8b610..e451dd3409 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -78,6 +78,7 @@ image_ids! { hammer: "voxygen.element.weapons.hammer", bow: "voxygen.element.weapons.bow", staff: "voxygen.element.weapons.staff", + pickaxe: "voxygen.element.weapons.pickaxe", lock: "voxygen.element.ui.diary.buttons.lock", wpn_icon_border_skills: "voxygen.element.ui.diary.buttons.border_skills", wpn_icon_border: "voxygen.element.ui.generic.buttons.border", @@ -303,6 +304,10 @@ image_ids! { utility_speed_skill: "voxygen.element.skills.skilltree.utility_speed", utility_duration_skill: "voxygen.element.skills.skilltree.utility_duration", + pickaxe_speed_skill: "voxygen.element.skills.pickaxe_speed", + pickaxe_oregain_skill: "voxygen.element.skills.pickaxe_oregain", + pickaxe_gemgain_skill: "voxygen.element.skills.pickaxe_gemgain", + // Skillbar level_up: "voxygen.element.ui.skillbar.level_up", bar_content: "voxygen.element.ui.skillbar.bar_content", diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 585361849d..90aef9563f 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -1353,6 +1353,7 @@ impl Hud { Weapon(ToolKind::Sceptre) => &i18n.get("common.weapons.sceptre"), Weapon(ToolKind::Bow) => &i18n.get("common.weapons.bow"), Weapon(ToolKind::Staff) => &i18n.get("common.weapons.staff"), + Weapon(ToolKind::Pick) => &i18n.get("common.tool.pick"), _ => "Unknown", }; Text::new(skill)