diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ac9b9bf6e..741ec8bb67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Combat music toggle - Spawn rtsim wyverns that travel the world, providing dragon scale loot drops - Hardwood in tropical forests, frostwood in cold forests, and iron wood on the top of giant trees +- Recipe for shovel, which is used to dig in mud and graves ### Changed diff --git a/assets/common/abilities/ability_set_manifest.ron b/assets/common/abilities/ability_set_manifest.ron index 428d693bc1..ed9e0f2547 100644 --- a/assets/common/abilities/ability_set_manifest.ron +++ b/assets/common/abilities/ability_set_manifest.ron @@ -891,6 +891,11 @@ secondary: Simple(None, "common.abilities.pick.swing"), abilities: [], ), + Tool(Shovel): ( + primary: Simple(None, "common.abilities.shovel.dig"), + secondary: Simple(None, "common.abilities.shovel.dig"), + abilities: [], + ), Tool(Empty): ( primary: Simple(None, "common.abilities.empty.basic"), secondary: Simple(None, "common.abilities.empty.basic"), diff --git a/assets/common/abilities/shovel/dig.ron b/assets/common/abilities/shovel/dig.ron new file mode 100644 index 0000000000..dd1c02be5c --- /dev/null +++ b/assets/common/abilities/shovel/dig.ron @@ -0,0 +1,17 @@ +BasicMelee( + energy_cost: 0, + buildup_duration: 0.25, + swing_duration: 0.05, + recover_duration: 0.075, + melee_constructor: ( + kind: Stab( + damage: 5.0, + poise: 0.0, + knockback: 0.0, + energy_regen: 0.0, + ), + range: 4.5, + angle: 20.0, + ), + ori_modifier: 1.0, +) diff --git a/assets/common/items/weapons/tool/shovel-0.ron b/assets/common/items/weapons/tool/shovel-0.ron index 49ad5c2601..5d9e281f64 100644 --- a/assets/common/items/weapons/tool/shovel-0.ron +++ b/assets/common/items/weapons/tool/shovel-0.ron @@ -2,7 +2,7 @@ ItemDef( name: "Shovel", description: "It's covered in manure.", kind: Tool(( - kind: Farming, + kind: Shovel, hands: Two, stats: ( equip_time_secs: 0.4, @@ -15,7 +15,9 @@ ItemDef( buff_strength: 1.0, ), )), - quality: Common, - tags: [], + quality: Moderate, + tags: [ + CraftingTool, + ], ability_spec: None, ) \ No newline at end of file diff --git a/assets/common/items/weapons/tool/shovel-1.ron b/assets/common/items/weapons/tool/shovel-1.ron index c00ef226cd..9638f3e22b 100644 --- a/assets/common/items/weapons/tool/shovel-1.ron +++ b/assets/common/items/weapons/tool/shovel-1.ron @@ -2,7 +2,7 @@ ItemDef( name: "Shovel", description: "It's been recently cleaned.", kind: Tool(( - kind: Farming, + kind: Shovel, hands: Two, stats: ( equip_time_secs: 0.4, @@ -16,6 +16,8 @@ ItemDef( ), )), quality: Common, - tags: [], + tags: [ + CraftingTool, + ], ability_spec: None, ) \ No newline at end of file diff --git a/assets/common/recipe_book.ron b/assets/common/recipe_book.ron index e51747f3a1..76b06606ad 100644 --- a/assets/common/recipe_book.ron +++ b/assets/common/recipe_book.ron @@ -2282,4 +2282,13 @@ ], craft_sprite: Some(CraftingBench), ), + "shovel": ( + output: ("common.items.weapons.tool.shovel-0", 1), + inputs: [ + (Item("common.items.crafting_ing.twigs"), 5, false), + (Item("common.items.mineral.ingot.iron"), 2, false), + (Item("common.items.tool.craftsman_hammer"), 0, false), + ], + craft_sprite: Some(CraftingBench), + ), } diff --git a/assets/voxygen/audio/sfx.ron b/assets/voxygen/audio/sfx.ron index 043c7c638f..93dca1865d 100644 --- a/assets/voxygen/audio/sfx.ron +++ b/assets/voxygen/audio/sfx.ron @@ -1491,6 +1491,13 @@ threshold: 0.9, subtitle: "subtitle-attack-steam", ), + GroundDig: ( + files: [ + "voxygen.audio.sfx.abilities.shovel", + ], + threshold: 0.8, + subtitle: "subtitle-attack-shovel", + ), // Utterances (NPCs) diff --git a/assets/voxygen/audio/sfx/abilities/shovel.ogg b/assets/voxygen/audio/sfx/abilities/shovel.ogg new file mode 100644 index 0000000000..79c8c2be27 --- /dev/null +++ b/assets/voxygen/audio/sfx/abilities/shovel.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37a5cbb8c852adef7ef9049e076a16b5f575d18400194c642ecdcec599f71b61 +size 16357 diff --git a/assets/voxygen/element/weapons/dig.png b/assets/voxygen/element/weapons/dig.png new file mode 100644 index 0000000000..2d75ea6b71 --- /dev/null +++ b/assets/voxygen/element/weapons/dig.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e6a156a88c77ef82c3175df47c09e5293145b1c3c22e7157ab291fea16d5eef5 +size 359 diff --git a/assets/voxygen/i18n/en/common.ftl b/assets/voxygen/i18n/en/common.ftl index 337d9ca0d3..5a96cb845c 100644 --- a/assets/voxygen/i18n/en/common.ftl +++ b/assets/voxygen/i18n/en/common.ftl @@ -75,6 +75,7 @@ common-weapons-unique = Unique common-tool-debug = Debug common-tool-farming = Farming Tool common-tool-pick = Pickaxe +common-tool-shovel = Shovel common-tool-mining = Mining common-tool-instrument = Instrument common-kind-modular_component = Modular Component @@ -113,3 +114,5 @@ common-material-cloth = Cloth common-material-hide = Hide common-sprite-chest = Chest common-sprite-chair = Chair +common-sprite-mud = Mud +common-sprite-grave = Grave diff --git a/assets/voxygen/i18n/en/hud/misc.ftl b/assets/voxygen/i18n/en/hud/misc.ftl index f4919ca9bc..6b832607d8 100644 --- a/assets/voxygen/i18n/en/hud/misc.ftl +++ b/assets/voxygen/i18n/en/hud/misc.ftl @@ -47,7 +47,9 @@ hud-read = Read hud-unlock-requires = Open with { $item } hud-unlock-consumes = Use { $item } to open hud-mine = Mine +hud-dig = Dig hud-mine-needs_pickaxe = Needs Pickaxe +hud-mine-needs_shovel = Needs Shovel hud-mine-needs_unhandled_case = Needs ??? hud-talk = Talk hud-trade = Trade diff --git a/assets/voxygen/i18n/en/hud/subtitles.ftl b/assets/voxygen/i18n/en/hud/subtitles.ftl index a48cb4031e..c94df031e1 100644 --- a/assets/voxygen/i18n/en/hud/subtitles.ftl +++ b/assets/voxygen/i18n/en/hud/subtitles.ftl @@ -108,6 +108,7 @@ subtitle-attack-flash_freeze = Flash freeze subtitle-attack-icy_spikes = Icy spikes subtitle-attack-ice_crack = Ice crack subtitle-attack-steam = Steam +subtitle-attack-shovel = Shovel digging subtitle-consume_potion = Drinking potion subtitle-consume_apple = Eating apple diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron index 99ff67952c..e5b559cee5 100644 --- a/assets/voxygen/item_image_manifest.ron +++ b/assets/voxygen/item_image_manifest.ron @@ -1616,11 +1616,11 @@ ), Simple("common.items.weapons.tool.shovel-0"): VoxTrans( "voxel.weapon.tool.shovel_green", - (0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.2, + (0.0, 0.0, 0.0), (-45.0, -90.0, 0.0), 1.2, ), Simple("common.items.weapons.tool.shovel-1"): VoxTrans( "voxel.weapon.tool.shovel_gold", - (0.0, 0.0, 0.0), (-135.0, 90.0, 0.0), 1.2, + (0.0, 0.0, 0.0), (-45.0, -90.0, 0.0), 1.2, ), Simple("common.items.tool.instruments.lyre"): VoxTrans( "voxel.weapon.tool.wooden_lyre", diff --git a/assets/voxygen/voxel/weapon/tool/shovel_gold.vox b/assets/voxygen/voxel/weapon/tool/shovel_gold.vox index c575996d6b..9c612a3169 100644 --- a/assets/voxygen/voxel/weapon/tool/shovel_gold.vox +++ b/assets/voxygen/voxel/weapon/tool/shovel_gold.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7435a232b94c027a0bc56030a0ff5666b4ef1066a7cfb6f7fbf80c346fae8a8f -size 1376 +oid sha256:263548b13b5ed58428a11ca48b9a06ef983c9a6d8cc3e26a01acc0c6cedf0743 +size 25655 diff --git a/assets/voxygen/voxel/weapon/tool/shovel_green.vox b/assets/voxygen/voxel/weapon/tool/shovel_green.vox index c2847c6335..1644f1d905 100644 --- a/assets/voxygen/voxel/weapon/tool/shovel_green.vox +++ b/assets/voxygen/voxel/weapon/tool/shovel_green.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4d882629376ce7458bd30d224b9c11f2e9575a93eefb10e6316390660a5e08e1 -size 1300 +oid sha256:3381f8fd02edf9ca7d82ca028b6cb02fe4b21fe020e6a998fadec60b937b0bdd +size 25579 diff --git a/common/src/bin/csv_export/main.rs b/common/src/bin/csv_export/main.rs index fd3e53bfc7..2468aec2ec 100644 --- a/common/src/bin/csv_export/main.rs +++ b/common/src/bin/csv_export/main.rs @@ -180,6 +180,7 @@ fn get_tool_kind(kind: &ToolKind) -> String { ToolKind::Debug => "Debug".to_string(), ToolKind::Farming => "Farming".to_string(), ToolKind::Pick => "Pick".to_string(), + ToolKind::Shovel => "Shovel".to_string(), ToolKind::Instrument => "Instrument".to_string(), ToolKind::Natural => "Natural".to_string(), ToolKind::Empty => "Empty".to_string(), diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index 9aeadb7e6f..f70674708b 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -36,6 +36,7 @@ pub enum ToolKind { Debug, Farming, Pick, + Shovel, // npcs /// Intended for invisible weapons (e.g. a creature using its claws or /// biting) @@ -64,6 +65,7 @@ impl ToolKind { ToolKind::Debug => "debug", ToolKind::Farming => "farming", ToolKind::Pick => "pickaxe", + ToolKind::Shovel => "shovel", ToolKind::Instrument => "instrument", ToolKind::Empty => "empty", } diff --git a/common/src/outcome.rs b/common/src/outcome.rs index e7762bd955..4e0b0a9a46 100644 --- a/common/src/outcome.rs +++ b/common/src/outcome.rs @@ -137,6 +137,9 @@ pub enum Outcome { FireShockwave { pos: Vec3, }, + GroundDig { + pos: Vec3, + }, } impl Outcome { @@ -166,6 +169,7 @@ impl Outcome { | Outcome::CyclopsCharge { pos } | Outcome::FlamethrowerCharge { pos } | Outcome::LaserBeam { pos } + | Outcome::GroundDig { pos } | Outcome::Glider { pos, .. } => Some(*pos), Outcome::BreakBlock { pos, .. } | Outcome::SpriteUnlocked { pos } diff --git a/common/src/states/basic_melee.rs b/common/src/states/basic_melee.rs index cd91f40a28..5b0ec8fa85 100644 --- a/common/src/states/basic_melee.rs +++ b/common/src/states/basic_melee.rs @@ -3,6 +3,8 @@ use crate::{ character_state::OutputEvents, tool::ToolKind, CharacterState, MeleeConstructor, StateUpdate, }, + event::LocalEvent, + outcome::Outcome, states::{ behavior::{CharacterBehavior, JoinData}, utils::*, @@ -91,9 +93,17 @@ impl CharacterBehavior for Data { self.static_data.ability_info.tool, ) }) - .filter(|(_, tool)| tool == &Some(ToolKind::Pick)), + .filter(|(_, tool)| { + matches!(tool, Some(ToolKind::Pick | ToolKind::Shovel)) + }), ), ); + // Send local event used for frontend shenanigans + if self.static_data.ability_info.tool == Some(ToolKind::Shovel) { + output_events.emit_local(LocalEvent::CreateOutcome(Outcome::GroundDig { + pos: data.pos.0 + *data.ori.look_dir() * (data.body.max_radius()), + })); + } } else if self.timer < self.static_data.swing_duration { // Swings update.character = CharacterState::BasicMelee(Data { diff --git a/common/src/states/combo_melee.rs b/common/src/states/combo_melee.rs index f8c55d0103..f72ff9978e 100644 --- a/common/src/states/combo_melee.rs +++ b/common/src/states/combo_melee.rs @@ -282,7 +282,9 @@ impl CharacterBehavior for Data { self.static_data.ability_info.tool, ) }) - .filter(|(_, tool)| tool == &Some(ToolKind::Pick)), + .filter(|(_, tool)| { + matches!(tool, Some(ToolKind::Pick | ToolKind::Shovel)) + }), }); } else if self.timer < self.static_data.stage_data[stage_index].base_swing_duration { diff --git a/common/src/terrain/sprite.rs b/common/src/terrain/sprite.rs index c9333ebb77..373dd0cee4 100644 --- a/common/src/terrain/sprite.rs +++ b/common/src/terrain/sprite.rs @@ -627,6 +627,7 @@ impl SpriteKind { | SpriteKind::Silver | SpriteKind::Gold | SpriteKind::SapphireSmall => Some(ToolKind::Pick), + SpriteKind::Grave | SpriteKind::Mud => Some(ToolKind::Shovel), _ => None, } } diff --git a/server/agent/src/data.rs b/server/agent/src/data.rs index f81dd65389..a5537684e9 100644 --- a/server/agent/src/data.rs +++ b/server/agent/src/data.rs @@ -118,6 +118,7 @@ impl<'a> TargetData<'a> { | ToolKind::Spear | ToolKind::Farming | ToolKind::Pick + | ToolKind::Shovel | ToolKind::Natural | ToolKind::Empty, ) diff --git a/server/src/persistence/json_models.rs b/server/src/persistence/json_models.rs index f8c4e1d147..13370b29bd 100644 --- a/server/src/persistence/json_models.rs +++ b/server/src/persistence/json_models.rs @@ -86,7 +86,8 @@ pub fn skill_group_to_db_string(skill_group: comp::skillset::SkillGroupKind) -> | Weapon(ToolKind::Farming) | Weapon(ToolKind::Instrument) | Weapon(ToolKind::Empty) - | Weapon(ToolKind::Natural) => panic!( + | Weapon(ToolKind::Natural) + | Weapon(ToolKind::Shovel) => panic!( "Tried to add unsupported skill group to database: {:?}", skill_group ), @@ -200,6 +201,7 @@ fn tool_kind_to_string(tool: Option) -> String { Some(Spear) => "Spear", Some(Blowgun) => "Blowgun", Some(Pick) => "Pick", + Some(Shovel) => "Shovel", // Toolkinds that are not anticipated to have many active abilities (if any at all) Some(Farming) => "Farming", diff --git a/voxygen/anim/src/biped_small/alpha.rs b/voxygen/anim/src/biped_small/alpha.rs index 156edd5e3e..1e1147ca82 100644 --- a/voxygen/anim/src/biped_small/alpha.rs +++ b/voxygen/anim/src/biped_small/alpha.rs @@ -115,7 +115,7 @@ impl Animation for AlphaAnimation { next.tail.orientation = Quaternion::rotation_x(0.05 * fastalt * speednormcancel) * Quaternion::rotation_z(fast * 0.15 * speednormcancel); }, - Some(ToolKind::Axe | ToolKind::Hammer | ToolKind::Pick) => { + Some(ToolKind::Axe | ToolKind::Hammer | ToolKind::Pick | ToolKind::Shovel) => { next.head.orientation = Quaternion::rotation_z(move1abs * 0.3 + move2abs * -0.6); next.control_l.position = Vec3::new(2.0 - s_a.grip.0 * 2.0, 1.0, 3.0); next.control_r.position = Vec3::new( diff --git a/voxygen/anim/src/character/alpha.rs b/voxygen/anim/src/character/alpha.rs index 90a48ef1ee..2713c29d70 100644 --- a/voxygen/anim/src/character/alpha.rs +++ b/voxygen/anim/src/character/alpha.rs @@ -65,7 +65,7 @@ impl Animation for AlphaAnimation { next.head.orientation = Quaternion::rotation_z(move1 * -0.9 + move2 * 1.8); }, - Some(ToolKind::Hammer) | Some(ToolKind::Pick) => { + Some(ToolKind::Hammer | ToolKind::Pick | ToolKind::Shovel) => { let (move1, move2, move3) = match stage_section { Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0), Some(StageSection::Action) => (1.0, anim_time.powf(0.25), 0.0), @@ -96,7 +96,7 @@ impl Animation for AlphaAnimation { match hands { (Some(Hands::Two), _) | (None, Some(Hands::Two)) => { match ability_info.and_then(|a| a.tool) { - Some(ToolKind::Hammer) | Some(ToolKind::Pick) => { + Some(ToolKind::Hammer | ToolKind::Pick) => { let (move1, move2, move3) = match stage_section { Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0), Some(StageSection::Action) => (1.0, anim_time, 0.0), @@ -128,6 +128,30 @@ impl Animation for AlphaAnimation { ) * Quaternion::rotation_z(s_a.hc.5 + (moveret2 * -0.5)); }, + Some(ToolKind::Shovel) => { + let (move1, move2, move3) = match stage_section { + Some(StageSection::Buildup) => (anim_time.powf(0.25), 0.0, 0.0), + Some(StageSection::Action) => (1.0, anim_time, 0.0), + Some(StageSection::Recover) => (1.0, 1.0, anim_time.powi(4)), + _ => (0.0, 0.0, 0.0), + }; + let pullback = 1.0 - move3; + let moveret1 = move1 * pullback; + let moveret2 = move2 * pullback; + + next.hand_l.position = Vec3::new(8.0, 6.0, 3.0); + next.hand_l.orientation = Quaternion::rotation_x(PI / 2.0); + next.hand_r.position = Vec3::new(8.0, 6.0, 15.0); + next.hand_r.orientation = Quaternion::rotation_x(PI / 2.0); + next.main.position = Vec3::new(7.5, 7.5, 13.2); + next.main.orientation = Quaternion::rotation_y(PI); + + next.control.position = Vec3::new(-11.0 + moveret1 * 8.0, 1.8, 4.0); + next.control.orientation = + Quaternion::rotation_x(moveret1 * 0.3 + moveret2 * 0.2) + * Quaternion::rotation_y(0.8 - moveret1 * 0.7 + moveret2 * 0.7) + * Quaternion::rotation_z(moveret2 * 0.1 - moveret1 * 0.4); + }, _ => {}, } }, @@ -144,7 +168,7 @@ impl Animation for AlphaAnimation { next.hand_l.position = Vec3::new(0.0, -0.5, 0.0); next.hand_l.orientation = Quaternion::rotation_x(PI / 2.0) }, - Some(ToolKind::Hammer) | Some(ToolKind::Pick) => { + Some(ToolKind::Hammer | ToolKind::Pick | ToolKind::Shovel) => { next.control_l.position = Vec3::new( -7.0, 8.0 + move1 * -4.0 + move2 * 4.0, @@ -173,7 +197,7 @@ impl Animation for AlphaAnimation { next.hand_r.position = Vec3::new(0.0, -0.5, 0.0); next.hand_r.orientation = Quaternion::rotation_x(PI / 2.0) }, - Some(ToolKind::Hammer) | Some(ToolKind::Pick) => { + Some(ToolKind::Hammer | ToolKind::Pick | ToolKind::Shovel) => { next.control_r.position = Vec3::new( 7.0, 8.0 + move1 * -4.0 + move2h * 4.0, diff --git a/voxygen/anim/src/character/block.rs b/voxygen/anim/src/character/block.rs index 97d3a65e46..256661a7dd 100644 --- a/voxygen/anim/src/character/block.rs +++ b/voxygen/anim/src/character/block.rs @@ -139,7 +139,7 @@ impl Animation for BlockAnimation { * Quaternion::rotation_y(s_a.ac.4 + move1 * -1.8) * Quaternion::rotation_z(s_a.ac.5 + move1 * 4.0); }, - Some(ToolKind::Hammer) | Some(ToolKind::Pick) => { + Some(ToolKind::Hammer | ToolKind::Pick | ToolKind::Shovel) => { next.hand_l.position = Vec3::new( s_a.hhl.0, s_a.hhl.1 + move1 * 6.0, diff --git a/voxygen/anim/src/character/equip.rs b/voxygen/anim/src/character/equip.rs index fd9f8db51d..fcaaa2eea0 100644 --- a/voxygen/anim/src/character/equip.rs +++ b/voxygen/anim/src/character/equip.rs @@ -39,7 +39,7 @@ impl Animation for EquipAnimation { next.hand_l.position = Vec3::new(-7.0, -5.0, 17.0); next.hand_r.position = Vec3::new(-5.0, -4.5, 14.0); }, - Some(ToolKind::Hammer | ToolKind::Pick) => { + Some(ToolKind::Hammer | ToolKind::Pick | ToolKind::Shovel) => { next.hand_l.position = Vec3::new(-5.0, -5.0, 13.0); next.hand_r.position = Vec3::new(-3.0, -4.5, 10.0); }, diff --git a/voxygen/anim/src/character/leapmelee.rs b/voxygen/anim/src/character/leapmelee.rs index 9506e6d680..4e9b0b314a 100644 --- a/voxygen/anim/src/character/leapmelee.rs +++ b/voxygen/anim/src/character/leapmelee.rs @@ -121,7 +121,7 @@ impl Animation for LeapAnimation { match hands { (Some(Hands::One), _) => match ability_info.and_then(|a| a.tool) { - Some(ToolKind::Hammer) | Some(ToolKind::Pick) => { + Some(ToolKind::Hammer | ToolKind::Pick) => { next.control_l.position = Vec3::new( -7.0, 8.0 + move2 * -5.0 + move3 * 9.0, @@ -140,7 +140,7 @@ impl Animation for LeapAnimation { match hands { (None | Some(Hands::One), Some(Hands::One)) => { match ability_info.and_then(|a| a.tool) { - Some(ToolKind::Hammer) | Some(ToolKind::Pick) => { + Some(ToolKind::Hammer | ToolKind::Pick) => { next.control_r.position = Vec3::new( 7.0 + move2 * 3.0 + move3 * -3.0, 8.0 + move2 * -9.0 + move3 * 15.0, diff --git a/voxygen/anim/src/character/roll.rs b/voxygen/anim/src/character/roll.rs index 930490f4f2..aeae182ef7 100644 --- a/voxygen/anim/src/character/roll.rs +++ b/voxygen/anim/src/character/roll.rs @@ -103,7 +103,9 @@ impl Animation for RollAnimation { * Quaternion::rotation_y(s_a.ac.4) * Quaternion::rotation_z(s_a.ac.5); }, - Some(ToolKind::Hammer | ToolKind::Pick | ToolKind::Instrument) => { + Some( + ToolKind::Hammer | ToolKind::Pick | ToolKind::Shovel | ToolKind::Instrument, + ) => { next.hand_l.position = Vec3::new(s_a.hhl.0, s_a.hhl.1, s_a.hhl.2); next.hand_l.orientation = Quaternion::rotation_x(s_a.hhl.3) * Quaternion::rotation_y(s_a.hhl.4) diff --git a/voxygen/anim/src/character/sneakequip.rs b/voxygen/anim/src/character/sneakequip.rs index 2ea25a9c37..d16fde99d7 100644 --- a/voxygen/anim/src/character/sneakequip.rs +++ b/voxygen/anim/src/character/sneakequip.rs @@ -179,7 +179,7 @@ impl Animation for SneakEquipAnimation { next.hand_l.position = Vec3::new(-7.0, -5.0, 17.0); next.hand_r.position = Vec3::new(-5.0, -4.5, 14.0); }, - Some(ToolKind::Hammer | ToolKind::Pick) => { + Some(ToolKind::Hammer | ToolKind::Pick | ToolKind::Shovel) => { next.hand_l.position = Vec3::new(-5.0, -5.0, 13.0); next.hand_r.position = Vec3::new(-3.0, -4.5, 10.0); }, diff --git a/voxygen/anim/src/character/sneakwield.rs b/voxygen/anim/src/character/sneakwield.rs index b11aad0474..b319974d10 100644 --- a/voxygen/anim/src/character/sneakwield.rs +++ b/voxygen/anim/src/character/sneakwield.rs @@ -232,7 +232,7 @@ impl Animation for SneakWieldAnimation { * Quaternion::rotation_y(s_a.ac.4) * Quaternion::rotation_z(s_a.ac.5); }, - Some(ToolKind::Hammer) | Some(ToolKind::Pick) => { + Some(ToolKind::Hammer | ToolKind::Pick | ToolKind::Shovel) => { next.hand_l.position = Vec3::new(s_a.hhl.0, s_a.hhl.1, s_a.hhl.2); next.hand_l.orientation = Quaternion::rotation_x(s_a.hhl.3) * Quaternion::rotation_y(s_a.hhl.4) diff --git a/voxygen/anim/src/character/staggered.rs b/voxygen/anim/src/character/staggered.rs index 431e164007..f0c1e3e187 100644 --- a/voxygen/anim/src/character/staggered.rs +++ b/voxygen/anim/src/character/staggered.rs @@ -103,7 +103,7 @@ impl Animation for StaggeredAnimation { * Quaternion::rotation_y(s_a.ac.4) * Quaternion::rotation_z(s_a.ac.5); }, - Some(ToolKind::Hammer | ToolKind::Pick) => { + Some(ToolKind::Hammer | ToolKind::Pick | ToolKind::Shovel) => { next.hand_l.position = Vec3::new(s_a.hhl.0, s_a.hhl.1, s_a.hhl.2); next.hand_l.orientation = Quaternion::rotation_x(s_a.hhl.3) * Quaternion::rotation_y(s_a.hhl.4) diff --git a/voxygen/anim/src/character/stunned.rs b/voxygen/anim/src/character/stunned.rs index a08929e08a..966efa0e78 100644 --- a/voxygen/anim/src/character/stunned.rs +++ b/voxygen/anim/src/character/stunned.rs @@ -99,7 +99,7 @@ impl Animation for StunnedAnimation { * Quaternion::rotation_y(s_a.ac.4) * Quaternion::rotation_z(s_a.ac.5); }, - Some(ToolKind::Hammer | ToolKind::Pick) => { + Some(ToolKind::Hammer | ToolKind::Pick | ToolKind::Shovel) => { next.hand_l.position = Vec3::new(s_a.hhl.0, s_a.hhl.1, s_a.hhl.2); next.hand_l.orientation = Quaternion::rotation_x(s_a.hhl.3) * Quaternion::rotation_y(s_a.hhl.4) diff --git a/voxygen/anim/src/character/wield.rs b/voxygen/anim/src/character/wield.rs index 7863d3a424..f3b9a767e1 100644 --- a/voxygen/anim/src/character/wield.rs +++ b/voxygen/anim/src/character/wield.rs @@ -223,7 +223,7 @@ impl Animation for WieldAnimation { * Quaternion::rotation_y(s_a.ac.4) * Quaternion::rotation_z(s_a.ac.5); }, - Some(ToolKind::Hammer) | Some(ToolKind::Pick) => { + Some(ToolKind::Hammer | ToolKind::Pick) => { next.hand_l.position = Vec3::new(s_a.hhl.0, s_a.hhl.1, s_a.hhl.2); next.hand_l.orientation = Quaternion::rotation_x(s_a.hhl.3) * Quaternion::rotation_y(s_a.hhl.4) @@ -305,6 +305,19 @@ impl Animation for WieldAnimation { * Quaternion::rotation_y(0.6 + u_slow * 0.1) * Quaternion::rotation_z(u_slowalt * 0.1); }, + Some(ToolKind::Shovel) => { + next.hand_l.position = Vec3::new(8.0, 6.0, 3.0); + next.hand_l.orientation = Quaternion::rotation_x(PI / 2.0); + next.hand_r.position = Vec3::new(8.0, 6.0, 15.0); + next.hand_r.orientation = Quaternion::rotation_x(PI / 2.0); + next.main.position = Vec3::new(7.5, 7.5, 13.2); + next.main.orientation = Quaternion::rotation_y(PI); + + next.control.position = Vec3::new(-11.0 + slow * 0.02, 1.8, 4.0); + next.control.orientation = Quaternion::rotation_x(u_slow * 0.01) + * Quaternion::rotation_y(0.8 + u_slow * 0.01) + * Quaternion::rotation_z(u_slowalt * 0.01); + }, Some(ToolKind::Instrument) => { if let Some(AbilitySpec::Custom(spec)) = active_tool_spec { match spec.as_str() { diff --git a/voxygen/src/audio/sfx/mod.rs b/voxygen/src/audio/sfx/mod.rs index f219a652c2..1978e51968 100644 --- a/voxygen/src/audio/sfx/mod.rs +++ b/voxygen/src/audio/sfx/mod.rs @@ -182,6 +182,7 @@ pub enum SfxEvent { DeepLaugh, Whoosh, Swoosh, + GroundDig, } #[derive(Copy, Clone, Debug, PartialEq, Deserialize, Hash, Eq)] @@ -488,6 +489,10 @@ impl SfxMgr { }, } }, + Outcome::GroundDig { pos, .. } => { + let sfx_trigger_item = triggers.get_key_value(&SfxEvent::GroundDig); + audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); + }, Outcome::IceSpikes { pos, .. } => { let sfx_trigger_item = triggers.get_key_value(&SfxEvent::IceSpikes); audio.emit_sfx(sfx_trigger_item, *pos, Some(2.0), underwater); diff --git a/voxygen/src/hud/diary.rs b/voxygen/src/hud/diary.rs index 347cca0b96..ebe262af66 100644 --- a/voxygen/src/hud/diary.rs +++ b/voxygen/src/hud/diary.rs @@ -2937,6 +2937,7 @@ fn unlock_skill_strings(group: SkillGroupKind) -> SkillStrings<'static> { | ToolKind::Farming | ToolKind::Instrument | ToolKind::Pick + | ToolKind::Shovel | ToolKind::Natural | ToolKind::Empty, ) => { diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs index 9efa4d1424..1e7fedb214 100644 --- a/voxygen/src/hud/img_ids.rs +++ b/voxygen/src/hud/img_ids.rs @@ -92,6 +92,7 @@ image_ids! { bow: "voxygen.element.weapons.bow", staff: "voxygen.element.weapons.staff", mining: "voxygen.element.weapons.mining", + dig: "voxygen.element.weapons.dig", pickaxe: "voxygen.element.skills.pickaxe", pickaxe_ico: "voxygen.element.weapons.pickaxe", skilltree_ico: "voxygen.element.ui.diary.buttons.skilltree", diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 283ddac7e5..e6e3ff6e81 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -2065,11 +2065,11 @@ impl Hud { let pos = mat.mul_point(Vec3::broadcast(0.5)); let over_pos = pos + Vec3::unit_z() * 0.7; - let interaction_text = || match interaction { + let interaction_text = |collect_default| match interaction { BlockInteraction::Collect => { vec![( Some(GameInput::Interact), - i18n.get_msg("hud-collect").to_string(), + i18n.get_msg(collect_default).to_string(), )] }, BlockInteraction::Craft(_) => { @@ -2099,15 +2099,34 @@ impl Hud { }, BlockInteraction::Mine(mine_tool) => { if info.is_mining { - vec![( - Some(GameInput::Primary), - i18n.get_msg("hud-mine").to_string(), - )] + match mine_tool { + ToolKind::Pick => { + vec![( + Some(GameInput::Primary), + i18n.get_msg("hud-mine").to_string(), + )] + }, + ToolKind::Shovel => { + vec![( + Some(GameInput::Primary), + i18n.get_msg("hud-dig").to_string(), + )] + }, + _ => { + vec![( + None, + i18n.get_msg("hud-mine-needs_unhandled_case").to_string(), + )] + }, + } } else { match mine_tool { ToolKind::Pick => { vec![(None, i18n.get_msg("hud-mine-needs_pickaxe").to_string())] }, + ToolKind::Shovel => { + vec![(None, i18n.get_msg("hud-mine-needs_shovel").to_string())] + } // TODO: The required tool for mining something may not always be a // pickaxe! _ => { @@ -2148,10 +2167,7 @@ impl Hud { overitem_properties, self.pulse, &global_state.window.key_layout, - vec![( - Some(GameInput::Interact), - i18n.get_msg("hud-open").to_string(), - )], + interaction_text("hud-open"), ) .x_y(0.0, 100.0) .position_ingame(over_pos) @@ -2160,11 +2176,7 @@ impl Hud { // TODO: Handle this better. The items returned from `try_reclaim_from_block` // are based on rng. We probably want some function to get only gauranteed items // from `LootSpec`. - else if let Some((amount, mut item)) = Item::try_reclaim_from_block(*block) - .into_iter() - .flatten() - .next() - { + else if let Some((amount, mut item)) = Item::try_reclaim_from_block(*block).into_iter().flatten().next() { item.set_amount(amount.clamp(1, item.max_amount())) .expect("amount >= 1 and <= max_amount is always a valid amount"); make_overitem( @@ -2173,7 +2185,7 @@ impl Hud { pos.distance_squared(player_pos), overitem_properties, &self.fonts, - interaction_text(), + interaction_text("hud-collect"), ) .set(overitem_id, ui_widgets); } else if let Some(desc) = block.get_sprite().and_then(|s| get_sprite_desc(s, i18n)) @@ -2188,7 +2200,7 @@ impl Hud { overitem_properties, self.pulse, &global_state.window.key_layout, - interaction_text(), + interaction_text("hud-collect"), ) .x_y(0.0, 100.0) .position_ingame(over_pos) @@ -5242,6 +5254,8 @@ pub fn get_sprite_desc(sprite: SpriteKind, localized_strings: &Localization) -> | SpriteKind::DungeonChest3 | SpriteKind::DungeonChest4 | SpriteKind::DungeonChest5 => "common-sprite-chest", + SpriteKind::Mud => "common-sprite-mud", + SpriteKind::Grave => "common-sprite-grave", SpriteKind::ChairSingle | SpriteKind::ChairDouble => "common-sprite-chair", sprite => return Some(Cow::Owned(format!("{:?}", sprite))), }; diff --git a/voxygen/src/hud/util.rs b/voxygen/src/hud/util.rs index f4a69fddca..94e07b1eb7 100644 --- a/voxygen/src/hud/util.rs +++ b/voxygen/src/hud/util.rs @@ -320,6 +320,7 @@ fn tool_kind<'a>(tool: &Tool, i18n: &'a Localization) -> Cow<'a, str> { ToolKind::Farming => i18n.get_msg("common-tool-farming"), ToolKind::Instrument => i18n.get_msg("common-tool-instrument"), ToolKind::Pick => i18n.get_msg("common-tool-pick"), + ToolKind::Shovel => i18n.get_msg("common-tool-shovel"), ToolKind::Empty => i18n.get_msg("common-empty"), }; kind @@ -533,6 +534,8 @@ pub fn ability_image(imgs: &img_ids::Imgs, ability_id: &str) -> image::Id { "common.abilities.dagger.tempbasic" => imgs.onehdagger_m1, // Pickaxe "common.abilities.pick.swing" => imgs.mining, + // Shovel + "common.abilities.shovel.dig" => imgs.dig, // Instruments "common.abilities.music.bass" => imgs.instrument, "common.abilities.music.flute" => imgs.instrument, diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs index 1623f6e169..edf60557cc 100644 --- a/voxygen/src/scene/particle.rs +++ b/voxygen/src/scene/particle.rs @@ -386,6 +386,16 @@ impl ParticleMgr { ) }); }, + Outcome::GroundDig { pos, .. } => { + self.particles.resize_with(self.particles.len() + 12, || { + Particle::new( + Duration::from_millis(200), + time, + ParticleMode::BigShrapnel, + *pos, + ) + }); + }, Outcome::ProjectileShot { .. } | Outcome::Beam { .. } | Outcome::ExpChange { .. } diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index 3dcf7301d8..9ab05c2450 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -603,7 +603,9 @@ impl PlayState for SessionState { .get(player_entity) .and_then(|inv| inv.equipped(EquipSlot::ActiveMainhand)) .and_then(|item| item.tool_info()) - .map_or(false, |tool_kind| tool_kind == ToolKind::Pick) + .map_or(false, |tool_kind| { + matches!(tool_kind, ToolKind::Pick | ToolKind::Shovel) + }) && client.is_wielding() == Some(true); // Check to see whether we're aiming at anything