mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Mining skill tree.
This commit is contained in:
parent
830b6e802e
commit
0e394029de
@ -85,6 +85,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Meat drops from animals
|
- Meat drops from animals
|
||||||
- New ores, plants and hides to be looted from the world and processed into craft ingredients
|
- 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 more crafting stations, loom, spinning wheel, tanning rack, forge
|
||||||
|
- Added a skill tree for mining, which gains xp from mining ores and gems.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -76,4 +76,7 @@
|
|||||||
Climb(Cost): Some(2),
|
Climb(Cost): Some(2),
|
||||||
Climb(Speed): Some(2),
|
Climb(Speed): Some(2),
|
||||||
Swim(Speed): Some(2),
|
Swim(Speed): Some(2),
|
||||||
|
Pick(Speed): Some(3),
|
||||||
|
Pick(OreGain): Some(3),
|
||||||
|
Pick(GemGain): Some(3),
|
||||||
})
|
})
|
||||||
|
@ -109,4 +109,9 @@
|
|||||||
Sceptre(ARange),
|
Sceptre(ARange),
|
||||||
Sceptre(ACost),
|
Sceptre(ACost),
|
||||||
],
|
],
|
||||||
|
Weapon(Pick): [
|
||||||
|
Pick(Speed),
|
||||||
|
Pick(OreGain),
|
||||||
|
Pick(GemGain),
|
||||||
|
],
|
||||||
})
|
})
|
||||||
|
19
assets/server/manifests/resource_experience_manifest.ron
Normal file
19
assets/server/manifests/resource_experience_manifest.ron
Normal file
@ -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,
|
||||||
|
})
|
BIN
assets/voxygen/element/skills/pickaxe_gemgain.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/skills/pickaxe_gemgain.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/skills/pickaxe_oregain.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/skills/pickaxe_oregain.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/skills/pickaxe_speed.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/skills/pickaxe_speed.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/element/weapons/pickaxe.png
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/element/weapons/pickaxe.png
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -238,6 +238,15 @@
|
|||||||
"hud.skill.axe_leap_cost": "Decreases cost of leap by 25%{SP}",
|
"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_title": "Leap Distance",
|
||||||
"hud.skill.axe_leap_distance": "Increases distance of leap by 20%{SP}",
|
"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}",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,6 +65,10 @@
|
|||||||
"voxel.weapon.sceptre.wood-nature",
|
"voxel.weapon.sceptre.wood-nature",
|
||||||
(-1.0, 0.0, 0.0), (-90.0, 55.0, 0.0), 1.0,
|
(-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(
|
Tool("example_dagger"): VoxTrans(
|
||||||
"voxel.weapon.dagger.dagger_basic-0",
|
"voxel.weapon.dagger.dagger_basic-0",
|
||||||
(0.0, 0.0, 0.0), (90.0, 90.0, 0.0), 1.0,
|
(0.0, 0.0, 0.0), (90.0, 90.0, 0.0), 1.0,
|
||||||
|
@ -127,7 +127,7 @@ lazy_static! {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect();
|
.collect();
|
||||||
static ref SKILL_TREES: Vec<String> = vec!["general", "sword", "axe", "hammer", "bow", "staff", "sceptre"]
|
static ref SKILL_TREES: Vec<String> = vec!["general", "sword", "axe", "hammer", "bow", "staff", "sceptre", "pick"]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| s.to_string())
|
.map(|s| s.to_string())
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -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 => {
|
None => {
|
||||||
if let CharacterAbility::Roll {
|
if let CharacterAbility::Roll {
|
||||||
ref mut energy_cost,
|
ref mut energy_cost,
|
||||||
|
@ -50,6 +50,21 @@ impl ToolKind {
|
|||||||
ToolKind::Empty => "empty",
|
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)]
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||||
|
@ -107,6 +107,7 @@ pub enum Skill {
|
|||||||
Roll(RollSkill),
|
Roll(RollSkill),
|
||||||
Climb(ClimbSkill),
|
Climb(ClimbSkill),
|
||||||
Swim(SwimSkill),
|
Swim(SwimSkill),
|
||||||
|
Pick(PickSkill),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum SkillError {
|
pub enum SkillError {
|
||||||
@ -263,6 +264,13 @@ pub enum SwimSkill {
|
|||||||
Speed,
|
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)]
|
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum SkillGroupKind {
|
pub enum SkillGroupKind {
|
||||||
General,
|
General,
|
||||||
@ -344,7 +352,10 @@ impl Default for SkillSet {
|
|||||||
/// player
|
/// player
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
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(),
|
skills: HashMap::new(),
|
||||||
modify_health: false,
|
modify_health: false,
|
||||||
modify_energy: false,
|
modify_energy: false,
|
||||||
@ -365,7 +376,7 @@ impl SkillSet {
|
|||||||
/// let mut skillset = SkillSet::default();
|
/// let mut skillset = SkillSet::default();
|
||||||
/// skillset.unlock_skill_group(SkillGroupKind::Weapon(ToolKind::Sword));
|
/// 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) {
|
pub fn unlock_skill_group(&mut self, skill_group_kind: SkillGroupKind) {
|
||||||
if !self.contains_skill_group(skill_group_kind) {
|
if !self.contains_skill_group(skill_group_kind) {
|
||||||
@ -668,13 +679,13 @@ mod tests {
|
|||||||
skillset.add_skill_points(SkillGroupKind::Weapon(ToolKind::Axe), 1);
|
skillset.add_skill_points(SkillGroupKind::Weapon(ToolKind::Axe), 1);
|
||||||
skillset.unlock_skill(Skill::Axe(AxeSkill::UnlockLeap));
|
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_eq!(skillset.skills.len(), 1);
|
||||||
assert!(skillset.has_skill(Skill::Axe(AxeSkill::UnlockLeap)));
|
assert!(skillset.has_skill(Skill::Axe(AxeSkill::UnlockLeap)));
|
||||||
|
|
||||||
skillset.refund_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);
|
assert_eq!(skillset.skills.get(&Skill::Axe(AxeSkill::UnlockLeap)), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,9 +694,9 @@ mod tests {
|
|||||||
let mut skillset = SkillSet::default();
|
let mut skillset = SkillSet::default();
|
||||||
skillset.unlock_skill_group(SkillGroupKind::Weapon(ToolKind::Axe));
|
skillset.unlock_skill_group(SkillGroupKind::Weapon(ToolKind::Axe));
|
||||||
|
|
||||||
assert_eq!(skillset.skill_groups.len(), 2);
|
assert_eq!(skillset.skill_groups.len(), 3);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
skillset.skill_groups[1],
|
skillset.skill_groups[2],
|
||||||
SkillGroup::new(SkillGroupKind::Weapon(ToolKind::Axe))
|
SkillGroup::new(SkillGroupKind::Weapon(ToolKind::Axe))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -697,13 +708,13 @@ mod tests {
|
|||||||
skillset.unlock_skill_group(SkillGroupKind::Weapon(ToolKind::Axe));
|
skillset.unlock_skill_group(SkillGroupKind::Weapon(ToolKind::Axe));
|
||||||
skillset.add_skill_points(SkillGroupKind::Weapon(ToolKind::Axe), 1);
|
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);
|
assert_eq!(skillset.skills.len(), 0);
|
||||||
|
|
||||||
// Try unlocking a skill with enough skill points
|
// Try unlocking a skill with enough skill points
|
||||||
skillset.unlock_skill(Skill::Axe(AxeSkill::UnlockLeap));
|
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_eq!(skillset.skills.len(), 1);
|
||||||
assert!(skillset.has_skill(Skill::Axe(AxeSkill::UnlockLeap)));
|
assert!(skillset.has_skill(Skill::Axe(AxeSkill::UnlockLeap)));
|
||||||
|
|
||||||
@ -720,6 +731,6 @@ mod tests {
|
|||||||
skillset.unlock_skill_group(SkillGroupKind::Weapon(ToolKind::Axe));
|
skillset.unlock_skill_group(SkillGroupKind::Weapon(ToolKind::Axe));
|
||||||
skillset.add_skill_points(SkillGroupKind::Weapon(ToolKind::Axe), 1);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -164,6 +164,7 @@ pub enum ServerEvent {
|
|||||||
},
|
},
|
||||||
// Attempt to mine a block, turning it into an item
|
// Attempt to mine a block, turning it into an item
|
||||||
MineBlock {
|
MineBlock {
|
||||||
|
entity: EcsEntity,
|
||||||
pos: Vec3<i32>,
|
pos: Vec3<i32>,
|
||||||
tool: Option<comp::tool::ToolKind>,
|
tool: Option<comp::tool::ToolKind>,
|
||||||
},
|
},
|
||||||
|
@ -86,6 +86,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
< (rad + scale * melee_attack.range).powi(2)
|
< (rad + scale * melee_attack.range).powi(2)
|
||||||
{
|
{
|
||||||
server_emitter.emit(ServerEvent::MineBlock {
|
server_emitter.emit(ServerEvent::MineBlock {
|
||||||
|
entity: attacker,
|
||||||
pos: block_pos,
|
pos: block_pos,
|
||||||
tool,
|
tool,
|
||||||
});
|
});
|
||||||
|
@ -2610,6 +2610,7 @@ fn parse_skill_tree(skill_tree: &str) -> CmdResult<comp::skills::SkillGroupKind>
|
|||||||
"bow" => Ok(SkillGroupKind::Weapon(ToolKind::Bow)),
|
"bow" => Ok(SkillGroupKind::Weapon(ToolKind::Bow)),
|
||||||
"staff" => Ok(SkillGroupKind::Weapon(ToolKind::Staff)),
|
"staff" => Ok(SkillGroupKind::Weapon(ToolKind::Staff)),
|
||||||
"sceptre" => Ok(SkillGroupKind::Weapon(ToolKind::Sceptre)),
|
"sceptre" => Ok(SkillGroupKind::Weapon(ToolKind::Sceptre)),
|
||||||
|
"pick" => Ok(SkillGroupKind::Weapon(ToolKind::Pick)),
|
||||||
_ => Err(format!("{} is not a skill group!", skill_tree)),
|
_ => Err(format!("{} is not a skill group!", skill_tree)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -992,13 +992,12 @@ fn handle_exp_gain(
|
|||||||
// Closure to add xp pool corresponding to weapon type equipped in a particular
|
// Closure to add xp pool corresponding to weapon type equipped in a particular
|
||||||
// EquipSlot
|
// EquipSlot
|
||||||
let mut add_tool_from_slot = |equip_slot| {
|
let mut add_tool_from_slot = |equip_slot| {
|
||||||
let tool_kind = inventory.equipped(equip_slot).and_then(|i| {
|
let tool_kind = inventory
|
||||||
if let ItemKind::Tool(tool) = &i.kind() {
|
.equipped(equip_slot)
|
||||||
Some(tool.kind)
|
.and_then(|i| match &i.kind() {
|
||||||
} else {
|
ItemKind::Tool(tool) if tool.kind.gains_combat_xp() => Some(tool.kind),
|
||||||
None
|
_ => None,
|
||||||
}
|
});
|
||||||
});
|
|
||||||
if let Some(weapon) = tool_kind {
|
if let Some(weapon) = tool_kind {
|
||||||
// Only adds to xp pools if entity has that skill group available
|
// Only adds to xp pools if entity has that skill group available
|
||||||
if skill_set.contains_skill_group(SkillGroupKind::Weapon(weapon)) {
|
if skill_set.contains_skill_group(SkillGroupKind::Weapon(weapon)) {
|
||||||
|
@ -3,6 +3,7 @@ use tracing::error;
|
|||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
use common::{
|
use common::{
|
||||||
|
assets,
|
||||||
comp::{
|
comp::{
|
||||||
self,
|
self,
|
||||||
agent::{AgentEvent, Sound, MAX_LISTEN_DIST},
|
agent::{AgentEvent, Sound, MAX_LISTEN_DIST},
|
||||||
@ -11,7 +12,7 @@ use common::{
|
|||||||
item,
|
item,
|
||||||
slot::Slot,
|
slot::Slot,
|
||||||
tool::ToolKind,
|
tool::ToolKind,
|
||||||
Inventory, Pos,
|
Inventory, Pos, SkillGroupKind,
|
||||||
},
|
},
|
||||||
consts::{MAX_MOUNT_RANGE, SOUND_TRAVEL_DIST_PER_VOLUME},
|
consts::{MAX_MOUNT_RANGE, SOUND_TRAVEL_DIST_PER_VOLUME},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
@ -27,6 +28,10 @@ use crate::{
|
|||||||
Server,
|
Server,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
pub fn handle_lantern(server: &mut Server, entity: EcsEntity, enable: bool) {
|
pub fn handle_lantern(server: &mut Server, entity: EcsEntity, enable: bool) {
|
||||||
let ecs = server.state_mut().ecs();
|
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<i32>, tool: Option<ToolKind>) {
|
#[derive(Deserialize)]
|
||||||
|
struct ResourceExperienceManifest(HashMap<String, i32>);
|
||||||
|
|
||||||
|
impl assets::Asset for ResourceExperienceManifest {
|
||||||
|
type Loader = assets::RonLoader;
|
||||||
|
|
||||||
|
const EXTENSION: &'static str = "ron";
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref RESOURCE_EXPERIENCE_MANIFEST: assets::AssetHandle<ResourceExperienceManifest> =
|
||||||
|
assets::AssetExt::load_expect("server.manifests.resource_experience_manifest");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_mine_block(
|
||||||
|
server: &mut Server,
|
||||||
|
entity: EcsEntity,
|
||||||
|
pos: Vec3<i32>,
|
||||||
|
tool: Option<ToolKind>,
|
||||||
|
) {
|
||||||
let state = server.state_mut();
|
let state = server.state_mut();
|
||||||
if state.can_set_block(pos) {
|
if state.can_set_block(pos) {
|
||||||
let block = state.terrain().get(pos).ok().copied();
|
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)) {
|
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
|
// 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::<comp::SkillSet>()
|
||||||
|
.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::<Vec<Outcome>>()
|
||||||
|
.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
|
state
|
||||||
.create_object(Default::default(), comp::object::Body::Pouch)
|
.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)))
|
.with(comp::Pos(pos.map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0)))
|
||||||
|
@ -207,7 +207,9 @@ impl Server {
|
|||||||
handle_combo_change(&self, entity, change)
|
handle_combo_change(&self, entity, change)
|
||||||
},
|
},
|
||||||
ServerEvent::RequestSiteInfo { entity, id } => handle_site_info(&self, entity, id),
|
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 {
|
ServerEvent::TeleportTo {
|
||||||
entity,
|
entity,
|
||||||
target,
|
target,
|
||||||
|
7
server/src/migrations/V41__mining_tree.sql
Normal file
7
server/src/migrations/V41__mining_tree.sql
Normal file
@ -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;
|
@ -40,8 +40,8 @@ pub fn skill_to_db_string(skill: comp::skills::Skill) -> String {
|
|||||||
use comp::{
|
use comp::{
|
||||||
item::tool::ToolKind,
|
item::tool::ToolKind,
|
||||||
skills::{
|
skills::{
|
||||||
AxeSkill, BowSkill, ClimbSkill, GeneralSkill, HammerSkill, RollSkill, SceptreSkill,
|
AxeSkill, BowSkill, ClimbSkill, GeneralSkill, HammerSkill, PickSkill, RollSkill,
|
||||||
Skill::*, SkillGroupKind, StaffSkill, SwimSkill, SwordSkill,
|
SceptreSkill, Skill::*, SkillGroupKind, StaffSkill, SwimSkill, SwordSkill,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let skill_string = match skill {
|
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::Cost) => "Climb Cost",
|
||||||
Climb(ClimbSkill::Speed) => "Climb Speed",
|
Climb(ClimbSkill::Speed) => "Climb Speed",
|
||||||
Swim(SwimSkill::Speed) => "Swim 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::Sword)) => "Unlock Weapon Sword",
|
||||||
UnlockGroup(SkillGroupKind::Weapon(ToolKind::Axe)) => "Unlock Weapon Axe",
|
UnlockGroup(SkillGroupKind::Weapon(ToolKind::Axe)) => "Unlock Weapon Axe",
|
||||||
UnlockGroup(SkillGroupKind::Weapon(ToolKind::Hammer)) => "Unlock Weapon Hammer",
|
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::{
|
use comp::{
|
||||||
item::tool::ToolKind,
|
item::tool::ToolKind,
|
||||||
skills::{
|
skills::{
|
||||||
AxeSkill, BowSkill, ClimbSkill, GeneralSkill, HammerSkill, RollSkill, SceptreSkill,
|
AxeSkill, BowSkill, ClimbSkill, GeneralSkill, HammerSkill, PickSkill, RollSkill,
|
||||||
Skill::*, SkillGroupKind, StaffSkill, SwimSkill, SwordSkill,
|
SceptreSkill, Skill::*, SkillGroupKind, StaffSkill, SwimSkill, SwordSkill,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
match skill_string {
|
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 Cost" => Climb(ClimbSkill::Cost),
|
||||||
"Climb Speed" => Climb(ClimbSkill::Speed),
|
"Climb Speed" => Climb(ClimbSkill::Speed),
|
||||||
"Swim Speed" => Swim(SwimSkill::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 Sword" => UnlockGroup(SkillGroupKind::Weapon(ToolKind::Sword)),
|
||||||
"Unlock Weapon Axe" => UnlockGroup(SkillGroupKind::Weapon(ToolKind::Axe)),
|
"Unlock Weapon Axe" => UnlockGroup(SkillGroupKind::Weapon(ToolKind::Axe)),
|
||||||
"Unlock Weapon Hammer" => UnlockGroup(SkillGroupKind::Weapon(ToolKind::Hammer)),
|
"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::Bow) => "Weapon Bow",
|
||||||
Weapon(ToolKind::Staff) => "Weapon Staff",
|
Weapon(ToolKind::Staff) => "Weapon Staff",
|
||||||
Weapon(ToolKind::Sceptre) => "Weapon Sceptre",
|
Weapon(ToolKind::Sceptre) => "Weapon Sceptre",
|
||||||
|
Weapon(ToolKind::Pick) => "Weapon Pick",
|
||||||
Weapon(ToolKind::Dagger)
|
Weapon(ToolKind::Dagger)
|
||||||
| Weapon(ToolKind::Shield)
|
| Weapon(ToolKind::Shield)
|
||||||
| Weapon(ToolKind::Spear)
|
| Weapon(ToolKind::Spear)
|
||||||
| Weapon(ToolKind::Debug)
|
| Weapon(ToolKind::Debug)
|
||||||
| Weapon(ToolKind::Farming)
|
| Weapon(ToolKind::Farming)
|
||||||
| Weapon(ToolKind::Pick)
|
|
||||||
| Weapon(ToolKind::Empty)
|
| Weapon(ToolKind::Empty)
|
||||||
| Weapon(ToolKind::Natural) => panic!(
|
| Weapon(ToolKind::Natural) => panic!(
|
||||||
"Tried to add unsupported skill group to database: {:?}",
|
"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 Bow" => Weapon(ToolKind::Bow),
|
||||||
"Weapon Staff" => Weapon(ToolKind::Staff),
|
"Weapon Staff" => Weapon(ToolKind::Staff),
|
||||||
"Weapon Sceptre" => Weapon(ToolKind::Sceptre),
|
"Weapon Sceptre" => Weapon(ToolKind::Sceptre),
|
||||||
|
"Weapon Pick" => Weapon(ToolKind::Pick),
|
||||||
_ => panic!(
|
_ => panic!(
|
||||||
"Tried to convert an unsupported string from the database: {}",
|
"Tried to convert an unsupported string from the database: {}",
|
||||||
skill_group_string
|
skill_group_string
|
||||||
|
@ -149,6 +149,11 @@ widget_ids! {
|
|||||||
skill_sceptre_aura_2,
|
skill_sceptre_aura_2,
|
||||||
skill_sceptre_aura_3,
|
skill_sceptre_aura_3,
|
||||||
skill_sceptre_aura_4,
|
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_0,
|
||||||
general_combat_render_1,
|
general_combat_render_1,
|
||||||
skill_general_stat_0,
|
skill_general_stat_0,
|
||||||
@ -227,7 +232,7 @@ impl<'a> Diary<'a> {
|
|||||||
|
|
||||||
pub type SelectedSkillTree = skills::SkillGroupKind;
|
pub type SelectedSkillTree = skills::SkillGroupKind;
|
||||||
|
|
||||||
const TREES: [&str; 7] = [
|
const TREES: [&str; 8] = [
|
||||||
"General Combat",
|
"General Combat",
|
||||||
"Sword",
|
"Sword",
|
||||||
"Hammer",
|
"Hammer",
|
||||||
@ -235,6 +240,7 @@ const TREES: [&str; 7] = [
|
|||||||
"Sceptre",
|
"Sceptre",
|
||||||
"Bow",
|
"Bow",
|
||||||
"Fire Staff",
|
"Fire Staff",
|
||||||
|
"Pickaxe",
|
||||||
];
|
];
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
@ -353,6 +359,7 @@ impl<'a> Widget for Diary<'a> {
|
|||||||
"Sceptre" => self.imgs.sceptre,
|
"Sceptre" => self.imgs.sceptre,
|
||||||
"Bow" => self.imgs.bow,
|
"Bow" => self.imgs.bow,
|
||||||
"Fire Staff" => self.imgs.staff,
|
"Fire Staff" => self.imgs.staff,
|
||||||
|
"Pickaxe" => self.imgs.pickaxe,
|
||||||
_ => self.imgs.nothing,
|
_ => self.imgs.nothing,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -500,6 +507,9 @@ impl<'a> Widget for Diary<'a> {
|
|||||||
SelectedSkillTree::Weapon(ToolKind::Staff) => {
|
SelectedSkillTree::Weapon(ToolKind::Staff) => {
|
||||||
self.localized_strings.get("common.weapons.staff")
|
self.localized_strings.get("common.weapons.staff")
|
||||||
},
|
},
|
||||||
|
SelectedSkillTree::Weapon(ToolKind::Pick) => {
|
||||||
|
self.localized_strings.get("common.tool.pick")
|
||||||
|
},
|
||||||
_ => "Unknown",
|
_ => "Unknown",
|
||||||
};
|
};
|
||||||
self.create_new_text(&tree_title, state.content_align, 2.0, 34, TEXT_COLOR)
|
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::Bow) => 6,
|
||||||
SelectedSkillTree::Weapon(ToolKind::Staff) => 4,
|
SelectedSkillTree::Weapon(ToolKind::Staff) => 4,
|
||||||
SelectedSkillTree::Weapon(ToolKind::Sceptre) => 5,
|
SelectedSkillTree::Weapon(ToolKind::Sceptre) => 5,
|
||||||
|
SelectedSkillTree::Weapon(ToolKind::Pick) => 4,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
let skills_top_r = match sel_tab {
|
let skills_top_r = match sel_tab {
|
||||||
@ -1976,6 +1987,65 @@ impl<'a> Widget for Diary<'a> {
|
|||||||
&diary_tooltip,
|
&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<SelectedSkillTree> {
|
|||||||
"Sceptre" => Some(SelectedSkillTree::Weapon(ToolKind::Sceptre)),
|
"Sceptre" => Some(SelectedSkillTree::Weapon(ToolKind::Sceptre)),
|
||||||
"Bow" => Some(SelectedSkillTree::Weapon(ToolKind::Bow)),
|
"Bow" => Some(SelectedSkillTree::Weapon(ToolKind::Bow)),
|
||||||
"Fire Staff" => Some(SelectedSkillTree::Weapon(ToolKind::Staff)),
|
"Fire Staff" => Some(SelectedSkillTree::Weapon(ToolKind::Staff)),
|
||||||
|
"Pickaxe" => Some(SelectedSkillTree::Weapon(ToolKind::Pick)),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,7 @@ image_ids! {
|
|||||||
hammer: "voxygen.element.weapons.hammer",
|
hammer: "voxygen.element.weapons.hammer",
|
||||||
bow: "voxygen.element.weapons.bow",
|
bow: "voxygen.element.weapons.bow",
|
||||||
staff: "voxygen.element.weapons.staff",
|
staff: "voxygen.element.weapons.staff",
|
||||||
|
pickaxe: "voxygen.element.weapons.pickaxe",
|
||||||
lock: "voxygen.element.ui.diary.buttons.lock",
|
lock: "voxygen.element.ui.diary.buttons.lock",
|
||||||
wpn_icon_border_skills: "voxygen.element.ui.diary.buttons.border_skills",
|
wpn_icon_border_skills: "voxygen.element.ui.diary.buttons.border_skills",
|
||||||
wpn_icon_border: "voxygen.element.ui.generic.buttons.border",
|
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_speed_skill: "voxygen.element.skills.skilltree.utility_speed",
|
||||||
utility_duration_skill: "voxygen.element.skills.skilltree.utility_duration",
|
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
|
// Skillbar
|
||||||
level_up: "voxygen.element.ui.skillbar.level_up",
|
level_up: "voxygen.element.ui.skillbar.level_up",
|
||||||
bar_content: "voxygen.element.ui.skillbar.bar_content",
|
bar_content: "voxygen.element.ui.skillbar.bar_content",
|
||||||
|
@ -1353,6 +1353,7 @@ impl Hud {
|
|||||||
Weapon(ToolKind::Sceptre) => &i18n.get("common.weapons.sceptre"),
|
Weapon(ToolKind::Sceptre) => &i18n.get("common.weapons.sceptre"),
|
||||||
Weapon(ToolKind::Bow) => &i18n.get("common.weapons.bow"),
|
Weapon(ToolKind::Bow) => &i18n.get("common.weapons.bow"),
|
||||||
Weapon(ToolKind::Staff) => &i18n.get("common.weapons.staff"),
|
Weapon(ToolKind::Staff) => &i18n.get("common.weapons.staff"),
|
||||||
|
Weapon(ToolKind::Pick) => &i18n.get("common.tool.pick"),
|
||||||
_ => "Unknown",
|
_ => "Unknown",
|
||||||
};
|
};
|
||||||
Text::new(skill)
|
Text::new(skill)
|
||||||
|
Loading…
Reference in New Issue
Block a user