Better visuals for skill button labels, don't show "0 EXP" in the SCT

Made functions that were called every frame significantly cheaper.

Final UI fixes.
This commit is contained in:
Monty Marz 2021-01-18 20:08:13 +01:00 committed by Sam
parent eaa41c7dea
commit ac60bf5794
24 changed files with 394 additions and 421 deletions

BIN
assets/voxygen/element/buttons/border_skills.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -2,7 +2,7 @@ use super::PingMsg;
use common::{
character::CharacterId,
comp,
comp::{Skill, SkillGroupType},
comp::{Skill, SkillGroupKind},
terrain::block::Block,
};
use serde::{Deserialize, Serialize};
@ -75,7 +75,7 @@ pub enum ClientGeneral {
},
UnlockSkill(Skill),
RefundSkill(Skill),
UnlockSkillGroup(SkillGroupType),
UnlockSkillGroup(SkillGroupKind),
//Always possible
ChatMsg(String),
Terminate,

View File

@ -8,7 +8,7 @@ use crate::{
},
slot::EquipSlot,
},
skills::{SkillGroupType, SkillSet},
skills::{SkillGroupKind, SkillSet},
BuffKind, Health, HealthChange, HealthSource, Inventory, Stats,
},
uid::Uid,
@ -231,16 +231,16 @@ pub fn get_weapons(inv: &Inventory) -> (Option<ToolKind>, Option<ToolKind>) {
)
}
fn max_equipped_weapon_damage(inv: &Inventory, skillset: &SkillSet) -> f32 {
fn offensive_rating(inv: &Inventory, skillset: &SkillSet) -> f32 {
let active_damage = equipped_tool(inv, EquipSlot::Mainhand).map_or(0.0, |tool| {
tool.base_power()
* tool.base_speed()
* (1.0 + 0.05 * skillset.earned_sp(SkillGroupType::Weapon(tool.kind)) as f32)
* (1.0 + 0.05 * skillset.earned_sp(SkillGroupKind::Weapon(tool.kind)) as f32)
});
let second_damage = equipped_tool(inv, EquipSlot::Offhand).map_or(0.0, |tool| {
tool.base_power()
* tool.base_speed()
* (1.0 + 0.05 * skillset.earned_sp(SkillGroupType::Weapon(tool.kind)) as f32)
* (1.0 + 0.05 * skillset.earned_sp(SkillGroupKind::Weapon(tool.kind)) as f32)
});
active_damage.max(second_damage)
}
@ -251,8 +251,8 @@ pub fn combat_rating(inventory: &Inventory, health: &Health, stats: &Stats) -> f
let defensive_rating = health.maximum() as f32
/ (1.0 - Damage::compute_damage_reduction(inventory)).max(0.00001)
/ 100.0;
let offensive_rating = max_equipped_weapon_damage(inventory, &stats.skill_set).max(0.1)
+ 0.05 * stats.skill_set.earned_sp(SkillGroupType::General) as f32;
let offensive_rating = offensive_rating(inventory, &stats.skill_set).max(0.1)
+ 0.05 * stats.skill_set.earned_sp(SkillGroupKind::General) as f32;
let combined_rating = (offensive_rating * offensive_weighting
+ defensive_rating * defensive_weighting)
/ (offensive_weighting + defensive_weighting);

View File

@ -67,6 +67,6 @@ pub use phys::{
pub use player::Player;
pub use projectile::{Projectile, ProjectileConstructor};
pub use shockwave::{Shockwave, ShockwaveHitEntities};
pub use skills::{Skill, SkillGroup, SkillGroupType, SkillSet};
pub use skills::{Skill, SkillGroup, SkillGroupKind, SkillSet};
pub use stats::Stats;
pub use visual::{LightAnimation, LightEmitter};

View File

@ -9,7 +9,7 @@ use std::hash::Hash;
use tracing::{trace, warn};
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SkillTreeMap(HashMap<SkillGroupType, HashSet<Skill>>);
pub struct SkillTreeMap(HashMap<SkillGroupKind, HashSet<Skill>>);
impl Asset for SkillTreeMap {
type Loader = assets::RonLoader;
@ -17,6 +17,11 @@ impl Asset for SkillTreeMap {
const EXTENSION: &'static str = "ron";
}
pub struct SkillGroupDef {
pub skills: HashSet<Skill>,
pub total_skill_point_cost: u16,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SkillLevelMap(HashMap<Skill, Option<u16>>);
@ -39,10 +44,35 @@ lazy_static! {
// Determines the skills that comprise each skill group - this data is used to determine
// which of a player's skill groups a particular skill should be added to when a skill unlock
// is requested.
pub static ref SKILL_GROUP_DEFS: HashMap<SkillGroupType, HashSet<Skill>> = {
SkillTreeMap::load_expect_cloned(
pub static ref SKILL_GROUP_DEFS: HashMap<SkillGroupKind, SkillGroupDef> = {
let map = SkillTreeMap::load_expect_cloned(
"common.skill_trees.skills_skill-groups_manifest",
).0
).0;
map.iter().map(|(sgk, skills)|
(*sgk, SkillGroupDef { skills: skills.clone(),
total_skill_point_cost: skills
.iter()
.map(|skill| {
if let Some(max_level) = skill.max_level() {
(1..=max_level)
.into_iter()
.map(|level| skill.skill_cost(Some(level)))
.sum()
} else {
skill.skill_cost(None)
}
})
.sum()
})
)
.collect()
};
// Creates a hashmap for the reverse lookup of skill groups from a skill
pub static ref SKILL_GROUP_LOOKUP: HashMap<Skill, SkillGroupKind> = {
let map = SkillTreeMap::load_expect_cloned(
"common.skill_trees.skills_skill-groups_manifest",
).0;
map.iter().map(|(sgk, skills)| skills.into_iter().map(move |s| (*s, *sgk))).flatten().collect()
};
// Loads the maximum level that a skill can obtain
pub static ref SKILL_MAX_LEVEL: HashMap<Skill, Option<u16>> = {
@ -71,7 +101,7 @@ pub enum Skill {
Bow(BowSkill),
Staff(StaffSkill),
Sceptre(SceptreSkill),
UnlockGroup(SkillGroupType),
UnlockGroup(SkillGroupKind),
Roll(RollSkill),
}
@ -219,12 +249,12 @@ pub enum RollSkill {
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
pub enum SkillGroupType {
pub enum SkillGroupKind {
General,
Weapon(ToolKind),
}
impl SkillGroupType {
impl SkillGroupKind {
/// Gets the cost in experience of earning a skill point
#[allow(clippy::many_single_char_names)]
pub fn skill_point_cost(self, level: u16) -> u16 {
@ -243,21 +273,13 @@ impl SkillGroupType {
/// Gets the total amount of skill points that can be spent in a particular
/// skill group
pub fn max_skill_points(self) -> u16 {
if let Some(skill_list) = SKILL_GROUP_DEFS.get(&self) {
skill_list
.iter()
.map(|skill| {
if let Some(max_level) = skill.max_level() {
(1..=max_level)
.into_iter()
.map(|level| skill.skill_cost(Some(level)))
.sum()
} else {
skill.skill_cost(None)
}
})
.sum()
pub fn total_skill_point_cost(self) -> u16 {
if let Some(SkillGroupDef {
total_skill_point_cost,
..
}) = SKILL_GROUP_DEFS.get(&self)
{
*total_skill_point_cost
} else {
0
}
@ -269,16 +291,16 @@ impl SkillGroupType {
/// skill group.
#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub struct SkillGroup {
pub skill_group_type: SkillGroupType,
pub skill_group_kind: SkillGroupKind,
pub exp: u16,
pub available_sp: u16,
pub earned_sp: u16,
}
impl SkillGroup {
fn new(skill_group_type: SkillGroupType) -> SkillGroup {
fn new(skill_group_kind: SkillGroupKind) -> SkillGroup {
SkillGroup {
skill_group_type,
skill_group_kind,
exp: 0,
available_sp: 0,
earned_sp: 0,
@ -303,7 +325,7 @@ impl Default for SkillSet {
/// player
fn default() -> Self {
Self {
skill_groups: vec![SkillGroup::new(SkillGroupType::General)],
skill_groups: vec![SkillGroup::new(SkillGroupKind::General)],
skills: HashMap::new(),
modify_health: false,
modify_energy: false,
@ -312,25 +334,23 @@ impl Default for SkillSet {
}
impl SkillSet {
// TODO: Game design to determine how skill groups are unlocked
/// Unlocks a skill group for a player. It starts with 0 exp and 0 skill
/// points.
///
/// ```
/// use veloren_common::comp::skills::{SkillGroupType, SkillSet};
/// use veloren_common::comp::{
/// item::tool::ToolKind,
/// skills::{SkillGroupKind, SkillSet},
/// };
///
/// let mut skillset = SkillSet::new();
/// skillset.unlock_skill_group(SkillGroupType::Axes);
/// let mut skillset = SkillSet::default();
/// skillset.unlock_skill_group(SkillGroupKind::Weapon(ToolKind::Sword));
///
/// assert_eq!(skillset.skill_groups.len(), 1);
/// assert_eq!(skillset.skill_groups.len(), 2);
/// ```
pub fn unlock_skill_group(&mut self, skill_group_type: SkillGroupType) {
if !self
.skill_groups
.iter()
.any(|x| x.skill_group_type == skill_group_type)
{
self.skill_groups.push(SkillGroup::new(skill_group_type));
pub fn unlock_skill_group(&mut self, skill_group_kind: SkillGroupKind) {
if !self.contains_skill_group(skill_group_kind) {
self.skill_groups.push(SkillGroup::new(skill_group_kind));
} else {
warn!("Tried to unlock already known skill group");
}
@ -340,26 +360,21 @@ impl SkillSet {
/// group unlocked and available SP in that skill group.
///
/// ```
/// use veloren_common::comp::skills::{Skill, SkillGroupType, SkillSet};
/// use veloren_common::comp::skills::{GeneralSkill, Skill, SkillGroupKind, SkillSet};
///
/// let mut skillset = SkillSet::new();
/// skillset.unlock_skill_group(SkillGroupType::Axes);
/// skillset.add_skill_points(SkillGroupType::Axes, 1);
/// let mut skillset = SkillSet::default();
/// skillset.add_skill_points(SkillGroupKind::General, 1);
///
/// skillset.unlock_skill(Skill::TestAxeSkill2);
/// skillset.unlock_skill(Skill::General(GeneralSkill::HealthIncrease));
///
/// assert_eq!(skillset.skills.len(), 1);
/// ```
pub fn unlock_skill(&mut self, skill: Skill) {
if let Some(skill_group_type) = skill.skill_group_type() {
if let Some(skill_group_kind) = skill.skill_group_kind() {
let next_level = self.next_skill_level(skill);
let prerequisites_met = self.prerequisites_met(skill);
if !matches!(self.skills.get(&skill), Some(level) if *level == skill.max_level()) {
if let Some(mut skill_group) = self
.skill_groups
.iter_mut()
.find(|x| x.skill_group_type == skill_group_type)
{
if let Some(mut skill_group) = self.skill_group_mut(skill_group_kind) {
if prerequisites_met {
if skill_group.available_sp >= skill.skill_cost(next_level) {
skill_group.available_sp -= skill.skill_cost(next_level);
@ -397,33 +412,25 @@ impl SkillSet {
/// skill group.
///
/// ```
/// use veloren_common::comp::skills::{Skill, SkillGroupType, SkillSet};
/// use veloren_common::comp::skills::{GeneralSkill, Skill, SkillGroupKind, SkillSet};
///
/// let mut skillset = SkillSet::new();
/// skillset.unlock_skill_group(SkillGroupType::Axes);
/// skillset.add_skill_points(SkillGroupType::Axes, 1);
/// skillset.unlock_skill(Skill::TestAxeSkill2);
/// let mut skillset = SkillSet::default();
/// skillset.add_skill_points(SkillGroupKind::General, 1);
/// skillset.unlock_skill(Skill::General(GeneralSkill::HealthIncrease));
///
/// skillset.refund_skill(Skill::TestAxeSkill2);
/// skillset.refund_skill(Skill::General(GeneralSkill::HealthIncrease));
///
/// assert_eq!(skillset.skills.len(), 0);
/// ```
pub fn refund_skill(&mut self, skill: Skill) {
if self.has_skill(skill) {
if let Some(skill_group_type) = skill.skill_group_type() {
if let Some(mut skill_group) = self
.skill_groups
.iter_mut()
.find(|x| x.skill_group_type == skill_group_type)
{
let level = self.skills.get(&skill).copied();
if let Some(level) = level {
skill_group.available_sp += skill.skill_cost(level);
if level.map_or(false, |l| l > 1) {
self.skills.insert(skill, level.map(|l| l - 1));
} else {
self.skills.remove(&skill);
}
if let Ok(level) = self.skill_level(skill) {
if let Some(skill_group_kind) = skill.skill_group_kind() {
if let Some(mut skill_group) = self.skill_group_mut(skill_group_kind) {
skill_group.available_sp += skill.skill_cost(level);
if level.map_or(false, |l| l > 1) {
self.skills.insert(skill, level.map(|l| l - 1));
} else {
self.skills.remove(&skill);
}
} else {
warn!("Tried to refund skill for a skill group that player does not have");
@ -443,24 +450,19 @@ impl SkillSet {
/// group type.
///
/// ```
/// use veloren_common::comp::skills::{SkillGroupType, SkillSet};
/// use veloren_common::comp::skills::{SkillGroupKind, SkillSet};
///
/// let mut skillset = SkillSet::new();
/// skillset.unlock_skill_group(SkillGroupType::Axes);
/// skillset.add_skill_points(SkillGroupType::Axes, 1);
/// let mut skillset = SkillSet::default();
/// skillset.add_skill_points(SkillGroupKind::General, 1);
///
/// assert_eq!(skillset.skill_groups[0].available_sp, 1);
/// ```
pub fn add_skill_points(
&mut self,
skill_group_type: SkillGroupType,
skill_group_kind: SkillGroupKind,
number_of_skill_points: u16,
) {
if let Some(mut skill_group) = self
.skill_groups
.iter_mut()
.find(|x| x.skill_group_type == skill_group_type)
{
if let Some(mut skill_group) = self.skill_group_mut(skill_group_kind) {
skill_group.available_sp = skill_group
.available_sp
.saturating_add(number_of_skill_points);
@ -471,13 +473,9 @@ impl SkillSet {
}
/// Adds a skill point while subtracting the necessary amount of experience
pub fn earn_skill_point(&mut self, skill_group_type: SkillGroupType) {
let sp_cost = self.skill_point_cost(skill_group_type);
if let Some(mut skill_group) = self
.skill_groups
.iter_mut()
.find(|x| x.skill_group_type == skill_group_type)
{
pub fn earn_skill_point(&mut self, skill_group_kind: SkillGroupKind) {
let sp_cost = self.skill_point_cost(skill_group_kind);
if let Some(mut skill_group) = self.skill_group_mut(skill_group_kind) {
skill_group.exp = skill_group.exp.saturating_sub(sp_cost);
skill_group.available_sp = skill_group.available_sp.saturating_add(1);
skill_group.earned_sp = skill_group.earned_sp.saturating_add(1);
@ -486,20 +484,16 @@ impl SkillSet {
/// Checks if the skill set of an entity contains a particular skill group
/// type
pub fn contains_skill_group(&self, skill_group_type: SkillGroupType) -> bool {
pub fn contains_skill_group(&self, skill_group_kind: SkillGroupKind) -> bool {
self.skill_groups
.iter()
.any(|x| x.skill_group_type == skill_group_type)
.any(|x| x.skill_group_kind == skill_group_kind)
}
/// Adds/subtracts experience to the skill group within an entity's skill
/// set
pub fn change_experience(&mut self, skill_group_type: SkillGroupType, amount: i32) {
if let Some(mut skill_group) = self
.skill_groups
.iter_mut()
.find(|x| x.skill_group_type == skill_group_type)
{
pub fn change_experience(&mut self, skill_group_kind: SkillGroupKind, amount: i32) {
if let Some(mut skill_group) = self.skill_group_mut(skill_group_kind) {
skill_group.exp = (skill_group.exp as i32 + amount) as u16;
} else {
warn!("Tried to add experience to a skill group that player does not have");
@ -509,36 +503,39 @@ impl SkillSet {
/// Checks that the skill set contains all prerequisite skills for a
/// particular skill
pub fn prerequisites_met(&self, skill: Skill) -> bool {
let next_level = self.next_skill_level(skill);
skill.prerequisite_skills(next_level).iter().all(|(s, l)| {
self.skill_level(*s).map_or(false, |l_b| l_b >= *l)
/* self.has_skill(*s) && self.skills.get(s).map_or(false, |l_b|
* l_b >= l) */
})
skill
.prerequisite_skills()
.all(|(s, l)| self.skill_level(s).map_or(false, |l_b| l_b >= l))
}
/// Returns a reference to a particular skill group in a skillset
fn skill_group(&self, skill_group: SkillGroupKind) -> Option<&SkillGroup> {
self.skill_groups
.iter()
.find(|s_g| s_g.skill_group_kind == skill_group)
}
/// Returns a reference to a particular skill group in a skillset
fn skill_group_mut(&mut self, skill_group: SkillGroupKind) -> Option<&mut SkillGroup> {
self.skill_groups
.iter_mut()
.find(|s_g| s_g.skill_group_kind == skill_group)
}
/// Gets the available points for a particular skill group
pub fn available_sp(&self, skill_group: SkillGroupType) -> u16 {
self.skill_groups
.iter()
.find(|s_g| s_g.skill_group_type == skill_group)
pub fn available_sp(&self, skill_group: SkillGroupKind) -> u16 {
self.skill_group(skill_group)
.map_or(0, |s_g| s_g.available_sp)
}
/// Gets the total earned points for a particular skill group
pub fn earned_sp(&self, skill_group: SkillGroupType) -> u16 {
self.skill_groups
.iter()
.find(|s_g| s_g.skill_group_type == skill_group)
.map_or(0, |s_g| s_g.earned_sp)
pub fn earned_sp(&self, skill_group: SkillGroupKind) -> u16 {
self.skill_group(skill_group).map_or(0, |s_g| s_g.earned_sp)
}
/// Gets the available experience for a particular skill group
pub fn experience(&self, skill_group: SkillGroupType) -> u16 {
self.skill_groups
.iter()
.find(|s_g| s_g.skill_group_type == skill_group)
.map_or(0, |s_g| s_g.exp)
pub fn experience(&self, skill_group: SkillGroupKind) -> u16 {
self.skill_group(skill_group).map_or(0, |s_g| s_g.exp)
}
/// Gets skill point cost to purchase skill of next level
@ -549,11 +546,11 @@ impl SkillSet {
/// Checks if player has sufficient skill points to purchase a skill
pub fn sufficient_skill_points(&self, skill: Skill) -> bool {
if let Some(skill_group_type) = skill.skill_group_type() {
if let Some(skill_group_kind) = skill.skill_group_kind() {
if let Some(skill_group) = self
.skill_groups
.iter()
.find(|x| x.skill_group_type == skill_group_type)
.find(|x| x.skill_group_kind == skill_group_kind)
{
let needed_sp = self.skill_cost(skill);
skill_group.available_sp >= needed_sp
@ -569,18 +566,13 @@ impl SkillSet {
pub fn has_available_sp(&self) -> bool {
self.skill_groups.iter().any(|sg| {
sg.available_sp > 0
&& (sg.earned_sp - sg.available_sp) < sg.skill_group_type.max_skill_points()
&& (sg.earned_sp - sg.available_sp) < sg.skill_group_kind.total_skill_point_cost()
})
}
/// Checks how much experience is needed for the next skill point in a tree
pub fn 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)
{
pub fn skill_point_cost(&self, skill_group: SkillGroupKind) -> u16 {
if let Some(level) = self.skill_group(skill_group).map(|sg| sg.earned_sp) {
skill_group.skill_point_cost(level)
} else {
skill_group.skill_point_cost(0)
@ -621,36 +613,28 @@ impl SkillSet {
impl Skill {
/// Returns a vec of prerequisite skills (it should only be necessary to
/// note direct prerequisites)
pub fn prerequisite_skills(self, level: Option<u16>) -> HashMap<Skill, Option<u16>> {
let mut prerequisites = HashMap::new();
if let Some(level) = level {
if level > 1 {
// For skills above level 1, sets prerequisite of skill of lower level
prerequisites.insert(self, Some(level - 1));
}
}
if let Some(skills) = SKILL_PREREQUISITES.get(&self) {
prerequisites.extend(skills);
}
prerequisites
pub fn prerequisite_skills(&self) -> impl Iterator<Item = (Skill, Option<u16>)> {
SKILL_PREREQUISITES
.get(&self)
.into_iter()
.flatten()
.map(|(skill, level)| (*skill, *level))
}
/// Returns the cost in skill points of unlocking a particular skill
pub fn skill_cost(self, level: Option<u16>) -> u16 {
pub fn skill_cost(&self, level: Option<u16>) -> u16 {
// TODO: Better balance the costs later
level.unwrap_or(1)
}
/// Returns the maximum level a skill can reach, returns None if the skill
/// doesn't level
pub fn max_level(self) -> Option<u16> { SKILL_MAX_LEVEL.get(&self).copied().flatten() }
pub fn max_level(&self) -> Option<u16> { SKILL_MAX_LEVEL.get(&self).copied().flatten() }
/// Returns the skill group type for a skill from the static skill group
/// definitions.
pub fn skill_group_type(self) -> Option<SkillGroupType> {
SKILL_GROUP_DEFS
.iter()
.find_map(|(key, val)| val.contains(&self).then_some(*key))
pub fn skill_group_kind(&self) -> Option<SkillGroupKind> {
SKILL_GROUP_LOOKUP.get(&self).copied()
}
}
@ -661,8 +645,8 @@ mod tests {
#[test]
fn test_refund_skill() {
let mut skillset = SkillSet::default();
skillset.unlock_skill_group(SkillGroupType::Weapon(ToolKind::Axe));
skillset.add_skill_points(SkillGroupType::Weapon(ToolKind::Axe), 1);
skillset.unlock_skill_group(SkillGroupKind::Weapon(ToolKind::Axe));
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);
@ -678,12 +662,12 @@ mod tests {
#[test]
fn test_unlock_skillgroup() {
let mut skillset = SkillSet::default();
skillset.unlock_skill_group(SkillGroupType::Weapon(ToolKind::Axe));
skillset.unlock_skill_group(SkillGroupKind::Weapon(ToolKind::Axe));
assert_eq!(skillset.skill_groups.len(), 2);
assert_eq!(
skillset.skill_groups[1],
SkillGroup::new(SkillGroupType::Weapon(ToolKind::Axe))
SkillGroup::new(SkillGroupKind::Weapon(ToolKind::Axe))
);
}
@ -691,8 +675,8 @@ mod tests {
fn test_unlock_skill() {
let mut skillset = SkillSet::default();
skillset.unlock_skill_group(SkillGroupType::Weapon(ToolKind::Axe));
skillset.add_skill_points(SkillGroupType::Weapon(ToolKind::Axe), 1);
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.skills.len(), 0);
@ -714,8 +698,8 @@ mod tests {
#[test]
fn test_add_skill_points() {
let mut skillset = SkillSet::default();
skillset.unlock_skill_group(SkillGroupType::Weapon(ToolKind::Axe));
skillset.add_skill_points(SkillGroupType::Weapon(ToolKind::Axe), 1);
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);
}

View File

@ -32,7 +32,7 @@ pub enum Outcome {
},
SkillPointGain {
uid: Uid,
skill_tree: comp::skills::SkillGroupType,
skill_tree: comp::skills::SkillGroupKind,
total_points: u16,
// TODO: Access ECS to get position from Uid to conserve bandwidth
pos: Vec3<f32>,

View File

@ -1,7 +1,7 @@
use crate::comp::{
item::{tool::ToolKind, Item, ItemKind},
skills::{
AxeSkill, BowSkill, HammerSkill, Skill, SkillGroupType, SkillSet, StaffSkill, SwordSkill,
AxeSkill, BowSkill, HammerSkill, Skill, SkillGroupKind, SkillSet, StaffSkill, SwordSkill,
},
};
use tracing::warn;
@ -41,7 +41,7 @@ impl SkillSetBuilder {
if let Some(ToolKind::Sword) = active_item {
// Sword
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Sword))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Sword))
.with_skill(Skill::Sword(SwordSkill::TsCombo))
.with_skill(Skill::Sword(SwordSkill::TsDamage))
.with_skill(Skill::Sword(SwordSkill::TsRegen))
@ -66,7 +66,7 @@ impl SkillSetBuilder {
Some(ToolKind::Sword) => {
// Sword
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Sword))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Sword))
.with_skill(Skill::Sword(SwordSkill::TsCombo))
.with_skill(Skill::Sword(SwordSkill::DDamage))
.with_skill(Skill::Sword(SwordSkill::DCost))
@ -74,7 +74,7 @@ impl SkillSetBuilder {
Some(ToolKind::Axe) => {
// Axe
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Axe))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Axe))
.with_skill(Skill::Axe(AxeSkill::DsCombo))
.with_skill(Skill::Axe(AxeSkill::SInfinite))
.with_skill(Skill::Axe(AxeSkill::SSpeed))
@ -83,7 +83,7 @@ impl SkillSetBuilder {
Some(ToolKind::Hammer) => {
// Hammer
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Hammer))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Hammer))
.with_skill(Skill::Hammer(HammerSkill::SsKnockback))
.with_skill(Skill::Hammer(HammerSkill::SsSpeed))
.with_skill(Skill::Hammer(HammerSkill::CKnockback))
@ -92,7 +92,7 @@ impl SkillSetBuilder {
Some(ToolKind::Bow) => {
// Bow
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Bow))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Bow))
.with_skill(Skill::Bow(BowSkill::BDamage))
.with_skill(Skill::Bow(BowSkill::ProjSpeed))
.with_skill(Skill::Bow(BowSkill::CDamage))
@ -102,7 +102,7 @@ impl SkillSetBuilder {
Some(ToolKind::Staff) => {
// Staff
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Staff))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Staff))
.with_skill(Skill::Staff(StaffSkill::FDamage))
.with_skill(Skill::Staff(StaffSkill::FDrain))
.with_skill(Skill::Staff(StaffSkill::FVelocity))
@ -115,7 +115,7 @@ impl SkillSetBuilder {
Some(ToolKind::Sword) => {
// Sword
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Sword))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Sword))
.with_skill(Skill::Sword(SwordSkill::TsCombo))
.with_skill(Skill::Sword(SwordSkill::TsDamage))
.with_skill(Skill::Sword(SwordSkill::DDamage))
@ -126,7 +126,7 @@ impl SkillSetBuilder {
Some(ToolKind::Axe) => {
// Axe
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Axe))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Axe))
.with_skill(Skill::Axe(AxeSkill::DsCombo))
.with_skill(Skill::Axe(AxeSkill::DsDamage))
.with_skill(Skill::Axe(AxeSkill::SInfinite))
@ -138,7 +138,7 @@ impl SkillSetBuilder {
Some(ToolKind::Hammer) => {
// Hammer
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Hammer))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Hammer))
.with_skill(Skill::Hammer(HammerSkill::SsKnockback))
.with_skill(Skill::Hammer(HammerSkill::SsDamage))
.with_skill(Skill::Hammer(HammerSkill::SsSpeed))
@ -150,7 +150,7 @@ impl SkillSetBuilder {
Some(ToolKind::Bow) => {
// Bow
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Bow))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Bow))
.with_skill(Skill::Bow(BowSkill::BDamage))
.with_skill(Skill::Bow(BowSkill::CDamage))
.with_skill(Skill::Bow(BowSkill::CKnockback))
@ -162,7 +162,7 @@ impl SkillSetBuilder {
Some(ToolKind::Staff) => {
// Staff
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Staff))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Staff))
.with_skill(Skill::Staff(StaffSkill::BExplosion))
.with_skill(Skill::Staff(StaffSkill::BRegen))
.with_skill(Skill::Staff(StaffSkill::BRadius))
@ -179,7 +179,7 @@ impl SkillSetBuilder {
Some(ToolKind::Sword) => {
// Sword
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Sword))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Sword))
.with_skill(Skill::Sword(SwordSkill::TsCombo))
.with_skill(Skill::Sword(SwordSkill::TsDamage))
.with_skill(Skill::Sword(SwordSkill::DDamage))
@ -192,7 +192,7 @@ impl SkillSetBuilder {
Some(ToolKind::Axe) => {
// Axe
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Axe))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Axe))
.with_skill(Skill::Axe(AxeSkill::DsCombo))
.with_skill(Skill::Axe(AxeSkill::DsSpeed))
.with_skill(Skill::Axe(AxeSkill::DsRegen))
@ -206,7 +206,7 @@ impl SkillSetBuilder {
Some(ToolKind::Hammer) => {
// Hammer
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Hammer))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Hammer))
.with_skill(Skill::Hammer(HammerSkill::SsKnockback))
.with_skill(Skill::Hammer(HammerSkill::SsDamage))
.with_skill(Skill::Hammer(HammerSkill::SsRegen))
@ -220,7 +220,7 @@ impl SkillSetBuilder {
Some(ToolKind::Bow) => {
// Bow
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Bow))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Bow))
.with_skill(Skill::Bow(BowSkill::BDamage))
.with_skill(Skill::Bow(BowSkill::ProjSpeed))
.with_skill(Skill::Bow(BowSkill::BRegen))
@ -234,7 +234,7 @@ impl SkillSetBuilder {
Some(ToolKind::Staff) => {
// Staff
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Staff))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Staff))
.with_skill(Skill::Staff(StaffSkill::BExplosion))
.with_skill(Skill::Staff(StaffSkill::FDamage))
.with_skill(Skill::Staff(StaffSkill::FRange))
@ -251,7 +251,7 @@ impl SkillSetBuilder {
Some(ToolKind::Sword) => {
// Sword
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Sword))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Sword))
.with_skill(Skill::Sword(SwordSkill::TsCombo))
.with_skill(Skill::Sword(SwordSkill::TsRegen))
.with_skill(Skill::Sword(SwordSkill::TsSpeed))
@ -267,7 +267,7 @@ impl SkillSetBuilder {
Some(ToolKind::Axe) => {
// Axe
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Axe))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Axe))
.with_skill(Skill::Axe(AxeSkill::DsCombo))
.with_skill(Skill::Axe(AxeSkill::SInfinite))
.with_skill(Skill::Axe(AxeSkill::SHelicopter))
@ -279,7 +279,7 @@ impl SkillSetBuilder {
Some(ToolKind::Hammer) => {
// Hammer
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Hammer))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Hammer))
.with_skill(Skill::Hammer(HammerSkill::SsKnockback))
.with_skill(Skill::Hammer(HammerSkill::SsSpeed))
.with_skill(Skill::Hammer(HammerSkill::SsRegen))
@ -294,7 +294,7 @@ impl SkillSetBuilder {
Some(ToolKind::Bow) => {
// Bow
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Bow))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Bow))
.with_skill(Skill::Bow(BowSkill::BDamage))
.with_skill(Skill::Bow(BowSkill::ProjSpeed))
.with_skill(Skill::Bow(BowSkill::CDamage))
@ -309,7 +309,7 @@ impl SkillSetBuilder {
Some(ToolKind::Staff) => {
// Staff
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Staff))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Staff))
.with_skill(Skill::Staff(StaffSkill::BExplosion))
.with_skill(Skill::Staff(StaffSkill::BDamage))
.with_skill(Skill::Staff(StaffSkill::BRadius))
@ -329,7 +329,7 @@ impl SkillSetBuilder {
Some(ToolKind::Sword) => {
// Sword
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Sword))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Sword))
.with_skill(Skill::Sword(SwordSkill::TsCombo))
.with_skill(Skill::Sword(SwordSkill::TsDamage))
.with_skill(Skill::Sword(SwordSkill::TsSpeed))
@ -343,7 +343,7 @@ impl SkillSetBuilder {
Some(ToolKind::Axe) => {
// Axe
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Axe))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Axe))
.with_skill(Skill::Axe(AxeSkill::DsCombo))
.with_skill(Skill::Axe(AxeSkill::DsDamage))
.with_skill(Skill::Axe(AxeSkill::SInfinite))
@ -358,7 +358,7 @@ impl SkillSetBuilder {
Some(ToolKind::Hammer) => {
// Hammer
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Hammer))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Hammer))
.with_skill(Skill::Hammer(HammerSkill::SsKnockback))
.with_skill(Skill::Hammer(HammerSkill::SsDamage))
.with_skill(Skill::Hammer(HammerSkill::SsRegen))
@ -372,7 +372,7 @@ impl SkillSetBuilder {
Some(ToolKind::Bow) => {
// Bow
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Bow))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Bow))
.with_skill(Skill::Bow(BowSkill::BDamage))
.with_skill(Skill::Bow(BowSkill::CDamage))
.with_skill(Skill::Bow(BowSkill::CKnockback))
@ -387,7 +387,7 @@ impl SkillSetBuilder {
Some(ToolKind::Staff) => {
// Staff
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Staff))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Staff))
.with_skill(Skill::Staff(StaffSkill::BExplosion))
.with_skill(Skill::Staff(StaffSkill::BDamage))
.with_skill(Skill::Staff(StaffSkill::BRadius))
@ -407,7 +407,7 @@ impl SkillSetBuilder {
Some(ToolKind::Sword) => {
// Sword
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Sword))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Sword))
.with_skill(Skill::Sword(SwordSkill::TsCombo))
.with_skill(Skill::Sword(SwordSkill::TsDamage))
.with_skill(Skill::Sword(SwordSkill::TsRegen))
@ -423,7 +423,7 @@ impl SkillSetBuilder {
Some(ToolKind::Axe) => {
// Axe
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Axe))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Axe))
.with_skill(Skill::Axe(AxeSkill::DsCombo))
.with_skill(Skill::Axe(AxeSkill::DsDamage))
.with_skill(Skill::Axe(AxeSkill::DsSpeed))
@ -440,7 +440,7 @@ impl SkillSetBuilder {
Some(ToolKind::Hammer) => {
// Hammer
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Hammer))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Hammer))
.with_skill(Skill::Hammer(HammerSkill::SsKnockback))
.with_skill(Skill::Hammer(HammerSkill::SsDamage))
.with_skill(Skill::Hammer(HammerSkill::SsSpeed))
@ -457,7 +457,7 @@ impl SkillSetBuilder {
Some(ToolKind::Bow) => {
// Bow
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Bow))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Bow))
.with_skill(Skill::Bow(BowSkill::BDamage))
.with_skill(Skill::Bow(BowSkill::BRegen))
.with_skill(Skill::Bow(BowSkill::CDamage))
@ -474,7 +474,7 @@ impl SkillSetBuilder {
Some(ToolKind::Staff) => {
// Staff
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Staff))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Staff))
.with_skill(Skill::Staff(StaffSkill::BExplosion))
.with_skill(Skill::Staff(StaffSkill::BDamage))
.with_skill(Skill::Staff(StaffSkill::BRegen))
@ -495,7 +495,7 @@ impl SkillSetBuilder {
Some(ToolKind::Sword) => {
// Sword
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Sword))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Sword))
.with_skill(Skill::Sword(SwordSkill::TsCombo))
.with_skill(Skill::Sword(SwordSkill::TsDamage))
.with_skill(Skill::Sword(SwordSkill::TsRegen))
@ -515,7 +515,7 @@ impl SkillSetBuilder {
Some(ToolKind::Axe) => {
// Axe
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Axe))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Axe))
.with_skill(Skill::Axe(AxeSkill::DsCombo))
.with_skill(Skill::Axe(AxeSkill::DsDamage))
.with_skill(Skill::Axe(AxeSkill::DsSpeed))
@ -534,7 +534,7 @@ impl SkillSetBuilder {
Some(ToolKind::Hammer) => {
// Hammer
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Hammer))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Hammer))
.with_skill(Skill::Hammer(HammerSkill::SsKnockback))
.with_skill(Skill::Hammer(HammerSkill::SsDamage))
.with_skill(Skill::Hammer(HammerSkill::SsSpeed))
@ -553,7 +553,7 @@ impl SkillSetBuilder {
Some(ToolKind::Bow) => {
// Bow
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Bow))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Bow))
.with_skill(Skill::Bow(BowSkill::BDamage))
.with_skill(Skill::Bow(BowSkill::ProjSpeed))
.with_skill(Skill::Bow(BowSkill::BRegen))
@ -572,7 +572,7 @@ impl SkillSetBuilder {
Some(ToolKind::Staff) => {
// Staff
Self::default()
.with_skill_group(SkillGroupType::Weapon(ToolKind::Staff))
.with_skill_group(SkillGroupKind::Weapon(ToolKind::Staff))
.with_skill(Skill::Staff(StaffSkill::BExplosion))
.with_skill(Skill::Staff(StaffSkill::BDamage))
.with_skill(Skill::Staff(StaffSkill::BRegen))
@ -595,7 +595,7 @@ impl SkillSetBuilder {
}
pub fn with_skill(mut self, skill: Skill) -> Self {
if let Some(skill_group) = skill.skill_group_type() {
if let Some(skill_group) = skill.skill_group_kind() {
self.0
.add_skill_points(skill_group, self.0.skill_cost(skill));
self.0.unlock_skill(skill);
@ -615,7 +615,7 @@ impl SkillSetBuilder {
self
}
pub fn with_skill_group(mut self, skill_group: SkillGroupType) -> Self {
pub fn with_skill_group(mut self, skill_group: SkillGroupKind) -> Self {
self.0.unlock_skill_group(skill_group);
self
}

View File

@ -91,8 +91,8 @@ impl<'a> System<'a> for Sys {
.skill_groups
.iter()
.filter_map(|s_g| {
(s_g.exp >= stat.skill_set.skill_point_cost(s_g.skill_group_type))
.then(|| s_g.skill_group_type)
(s_g.exp >= stat.skill_set.skill_point_cost(s_g.skill_group_kind))
.then(|| s_g.skill_group_kind)
})
.collect::<HashSet<_>>();

View File

@ -2053,16 +2053,16 @@ fn handle_skill_point(
}
}
fn parse_skill_tree(skill_tree: &str) -> Option<comp::skills::SkillGroupType> {
use comp::{item::tool::ToolKind, skills::SkillGroupType};
fn parse_skill_tree(skill_tree: &str) -> Option<comp::skills::SkillGroupKind> {
use comp::{item::tool::ToolKind, skills::SkillGroupKind};
match skill_tree {
"general" => Some(SkillGroupType::General),
"sword" => Some(SkillGroupType::Weapon(ToolKind::Sword)),
"axe" => Some(SkillGroupType::Weapon(ToolKind::Axe)),
"hammer" => Some(SkillGroupType::Weapon(ToolKind::Hammer)),
"bow" => Some(SkillGroupType::Weapon(ToolKind::Bow)),
"staff" => Some(SkillGroupType::Weapon(ToolKind::Staff)),
"sceptre" => Some(SkillGroupType::Weapon(ToolKind::Sceptre)),
"general" => Some(SkillGroupKind::General),
"sword" => Some(SkillGroupKind::Weapon(ToolKind::Sword)),
"axe" => Some(SkillGroupKind::Weapon(ToolKind::Axe)),
"hammer" => Some(SkillGroupKind::Weapon(ToolKind::Hammer)),
"bow" => Some(SkillGroupKind::Weapon(ToolKind::Bow)),
"staff" => Some(SkillGroupKind::Weapon(ToolKind::Staff)),
"sceptre" => Some(SkillGroupKind::Weapon(ToolKind::Sceptre)),
_ => None,
}
}

View File

@ -1,7 +1,7 @@
use crate::{
client::Client,
comp::{
biped_large, quadruped_low, quadruped_medium, quadruped_small, skills::SkillGroupType,
biped_large, quadruped_low, quadruped_medium, quadruped_small, skills::SkillGroupKind,
theropod, PhysicsState,
},
rtsim::RtSim,
@ -234,7 +234,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
(entity, uid)
})
.collect::<Vec<_>>();
// Devides exp reward by square root of number of people in group
// Divides exp reward by square root of number of people in group
exp_reward /= (non_pet_group_members_in_range as f32).sqrt();
members_in_range.into_iter().for_each(|(e, uid)| {
if let (Some(inventory), Some(mut stats)) = (inventories.get(e), stats.get_mut(e)) {
@ -796,22 +796,22 @@ fn handle_exp_gain(
outcomes: &mut Vec<Outcome>,
) {
let (main_tool_kind, second_tool_kind) = combat::get_weapons(inventory);
let mut xp_pools = HashSet::<SkillGroupType>::new();
xp_pools.insert(SkillGroupType::General);
let mut xp_pools = HashSet::<SkillGroupKind>::new();
xp_pools.insert(SkillGroupKind::General);
if let Some(w) = main_tool_kind {
if stats
.skill_set
.contains_skill_group(SkillGroupType::Weapon(w))
.contains_skill_group(SkillGroupKind::Weapon(w))
{
xp_pools.insert(SkillGroupType::Weapon(w));
xp_pools.insert(SkillGroupKind::Weapon(w));
}
}
if let Some(w) = second_tool_kind {
if stats
.skill_set
.contains_skill_group(SkillGroupType::Weapon(w))
.contains_skill_group(SkillGroupKind::Weapon(w))
{
xp_pools.insert(SkillGroupType::Weapon(w));
xp_pools.insert(SkillGroupKind::Weapon(w));
}
}
let num_pools = xp_pools.len() as f32;

View File

@ -34,12 +34,12 @@ DROP TABLE stats;
-- Creates new table for skill groups
CREATE TABLE skill_group (
entity_id INTEGER NOT NULL,
skill_group_type TEXT NOT NULL,
skill_group_kind TEXT NOT NULL,
exp INTEGER NOT NULL,
available_sp INTEGER NOT NULL,
earned_sp INTEGER NOT NULL,
FOREIGN KEY(entity_id) REFERENCES entity(entity_id),
PRIMARY KEY(entity_id,skill_group_type)
PRIMARY KEY(entity_id,skill_group_kind)
);
-- Creates new table for skills

View File

@ -367,9 +367,9 @@ fn get_item_from_asset(item_definition_id: &str) -> Result<common::comp::Item, E
fn convert_skill_groups_from_database(skill_groups: &[SkillGroup]) -> Vec<skills::SkillGroup> {
let mut new_skill_groups = Vec::new();
for skill_group in skill_groups.iter() {
let skill_group_type = json_models::db_string_to_skill_group(&skill_group.skill_group_type);
let skill_group_kind = json_models::db_string_to_skill_group(&skill_group.skill_group_kind);
let new_skill_group = skills::SkillGroup {
skill_group_type,
skill_group_kind,
exp: skill_group.exp as u16,
available_sp: skill_group.available_sp as u16,
earned_sp: skill_group.earned_sp as u16,
@ -396,7 +396,7 @@ pub fn convert_skill_groups_to_database(
.into_iter()
.map(|sg| SkillGroup {
entity_id,
skill_group_type: json_models::skill_group_to_db_string(sg.skill_group_type),
skill_group_kind: json_models::skill_group_to_db_string(sg.skill_group_kind),
exp: sg.exp as i32,
available_sp: sg.available_sp as i32,
earned_sp: sg.earned_sp as i32,

View File

@ -41,7 +41,7 @@ pub fn skill_to_db_string(skill: comp::skills::Skill) -> String {
item::tool::ToolKind,
skills::{
AxeSkill, BowSkill, GeneralSkill, HammerSkill, RollSkill, SceptreSkill, Skill::*,
SkillGroupType, StaffSkill, SwordSkill,
SkillGroupKind, StaffSkill, SwordSkill,
},
};
let skill_string = match skill {
@ -133,19 +133,19 @@ pub fn skill_to_db_string(skill: comp::skills::Skill) -> String {
Roll(RollSkill::Cost) => "Roll Cost",
Roll(RollSkill::Strength) => "Roll Strength",
Roll(RollSkill::Duration) => "Roll Duration",
UnlockGroup(SkillGroupType::Weapon(ToolKind::Sword)) => "Unlock Weapon Sword",
UnlockGroup(SkillGroupType::Weapon(ToolKind::Axe)) => "Unlock Weapon Axe",
UnlockGroup(SkillGroupType::Weapon(ToolKind::Hammer)) => "Unlock Weapon Hammer",
UnlockGroup(SkillGroupType::Weapon(ToolKind::Bow)) => "Unlock Weapon Bow",
UnlockGroup(SkillGroupType::Weapon(ToolKind::Staff)) => "Unlock Weapon Staff",
UnlockGroup(SkillGroupType::Weapon(ToolKind::Sceptre)) => "Unlock Weapon Sceptre",
UnlockGroup(SkillGroupType::Weapon(ToolKind::Dagger))
| UnlockGroup(SkillGroupType::Weapon(ToolKind::Shield))
| UnlockGroup(SkillGroupType::Weapon(ToolKind::Debug))
| UnlockGroup(SkillGroupType::Weapon(ToolKind::Farming))
| UnlockGroup(SkillGroupType::Weapon(ToolKind::Empty))
| UnlockGroup(SkillGroupType::Weapon(ToolKind::Unique(_)))
| UnlockGroup(SkillGroupType::General) => {
UnlockGroup(SkillGroupKind::Weapon(ToolKind::Sword)) => "Unlock Weapon Sword",
UnlockGroup(SkillGroupKind::Weapon(ToolKind::Axe)) => "Unlock Weapon Axe",
UnlockGroup(SkillGroupKind::Weapon(ToolKind::Hammer)) => "Unlock Weapon Hammer",
UnlockGroup(SkillGroupKind::Weapon(ToolKind::Bow)) => "Unlock Weapon Bow",
UnlockGroup(SkillGroupKind::Weapon(ToolKind::Staff)) => "Unlock Weapon Staff",
UnlockGroup(SkillGroupKind::Weapon(ToolKind::Sceptre)) => "Unlock Weapon Sceptre",
UnlockGroup(SkillGroupKind::Weapon(ToolKind::Dagger))
| UnlockGroup(SkillGroupKind::Weapon(ToolKind::Shield))
| UnlockGroup(SkillGroupKind::Weapon(ToolKind::Debug))
| UnlockGroup(SkillGroupKind::Weapon(ToolKind::Farming))
| UnlockGroup(SkillGroupKind::Weapon(ToolKind::Empty))
| UnlockGroup(SkillGroupKind::Weapon(ToolKind::Unique(_)))
| UnlockGroup(SkillGroupKind::General) => {
panic!("Tried to add unsupported skill to database: {:?}", skill)
},
};
@ -157,7 +157,7 @@ pub fn db_string_to_skill(skill_string: &str) -> comp::skills::Skill {
item::tool::ToolKind,
skills::{
AxeSkill, BowSkill, GeneralSkill, HammerSkill, RollSkill, SceptreSkill, Skill::*,
SkillGroupType, StaffSkill, SwordSkill,
SkillGroupKind, StaffSkill, SwordSkill,
},
};
match skill_string {
@ -249,12 +249,12 @@ pub fn db_string_to_skill(skill_string: &str) -> comp::skills::Skill {
"Roll Cost" => Roll(RollSkill::Cost),
"Roll Strength" => Roll(RollSkill::Strength),
"Roll Duration" => Roll(RollSkill::Duration),
"Unlock Weapon Sword" => UnlockGroup(SkillGroupType::Weapon(ToolKind::Sword)),
"Unlock Weapon Axe" => UnlockGroup(SkillGroupType::Weapon(ToolKind::Axe)),
"Unlock Weapon Hammer" => UnlockGroup(SkillGroupType::Weapon(ToolKind::Hammer)),
"Unlock Weapon Bow" => UnlockGroup(SkillGroupType::Weapon(ToolKind::Bow)),
"Unlock Weapon Staff" => UnlockGroup(SkillGroupType::Weapon(ToolKind::Staff)),
"Unlock Weapon Sceptre" => UnlockGroup(SkillGroupType::Weapon(ToolKind::Sceptre)),
"Unlock Weapon Sword" => UnlockGroup(SkillGroupKind::Weapon(ToolKind::Sword)),
"Unlock Weapon Axe" => UnlockGroup(SkillGroupKind::Weapon(ToolKind::Axe)),
"Unlock Weapon Hammer" => UnlockGroup(SkillGroupKind::Weapon(ToolKind::Hammer)),
"Unlock Weapon Bow" => UnlockGroup(SkillGroupKind::Weapon(ToolKind::Bow)),
"Unlock Weapon Staff" => UnlockGroup(SkillGroupKind::Weapon(ToolKind::Staff)),
"Unlock Weapon Sceptre" => UnlockGroup(SkillGroupKind::Weapon(ToolKind::Sceptre)),
_ => {
panic!(
"Tried to convert an unsupported string from the database: {}",
@ -264,8 +264,8 @@ pub fn db_string_to_skill(skill_string: &str) -> comp::skills::Skill {
}
}
pub fn skill_group_to_db_string(skill_group: comp::skills::SkillGroupType) -> String {
use comp::{item::tool::ToolKind, skills::SkillGroupType::*};
pub fn skill_group_to_db_string(skill_group: comp::skills::SkillGroupKind) -> String {
use comp::{item::tool::ToolKind, skills::SkillGroupKind::*};
let skill_group_string = match skill_group {
General => "General",
Weapon(ToolKind::Sword) => "Weapon Sword",
@ -287,8 +287,8 @@ pub fn skill_group_to_db_string(skill_group: comp::skills::SkillGroupType) -> St
skill_group_string.to_string()
}
pub fn db_string_to_skill_group(skill_group_string: &str) -> comp::skills::SkillGroupType {
use comp::{item::tool::ToolKind, skills::SkillGroupType::*};
pub fn db_string_to_skill_group(skill_group_string: &str) -> comp::skills::SkillGroupKind {
use comp::{item::tool::ToolKind, skills::SkillGroupKind::*};
match skill_group_string {
"General" => General,
"Weapon Sword" => Weapon(ToolKind::Sword),

View File

@ -57,11 +57,11 @@ pub struct Skill {
}
#[derive(Associations, Identifiable, Insertable, Queryable, Debug)]
#[primary_key(entity_id, skill_group_type)]
#[primary_key(entity_id, skill_group_kind)]
#[table_name = "skill_group"]
pub struct SkillGroup {
pub entity_id: i64,
pub skill_group_type: String,
pub skill_group_kind: String,
pub exp: i32,
pub available_sp: i32,
pub earned_sp: i32,

View File

@ -41,9 +41,9 @@ table! {
}
table! {
skill_group (entity_id, skill_group_type) {
skill_group (entity_id, skill_group_kind) {
entity_id -> BigInt,
skill_group_type -> Text,
skill_group_kind -> Text,
exp -> Integer,
available_sp -> Integer,
earned_sp -> Integer,

View File

@ -153,10 +153,10 @@ impl Sys {
.get_mut(entity)
.map(|mut s| s.skill_set.refund_skill(skill));
},
ClientGeneral::UnlockSkillGroup(skill_group_type) => {
ClientGeneral::UnlockSkillGroup(skill_group_kind) => {
stats
.get_mut(entity)
.map(|mut s| s.skill_set.unlock_skill_group(skill_group_type));
.map(|mut s| s.skill_set.unlock_skill_group(skill_group_kind));
},
_ => unreachable!("not a client_in_game msg"),
}

View File

@ -1,11 +1,10 @@
use super::{
cr_color,
img_ids::{Imgs, ImgsRot},
item_imgs::ItemImgs,
slots::{ArmorSlot, EquipSlot, InventorySlot, SlotManager},
util::loadout_slot_text,
Show, CRITICAL_HP_COLOR, LOW_HP_COLOR, QUALITY_ARTIFACT, QUALITY_COMMON, QUALITY_DEBUG,
QUALITY_EPIC, QUALITY_HIGH, QUALITY_LEGENDARY, QUALITY_LOW, QUALITY_MODERATE, TEXT_COLOR,
UI_HIGHLIGHT_0, UI_MAIN, XP_COLOR,
Show, CRITICAL_HP_COLOR, LOW_HP_COLOR, QUALITY_COMMON, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
};
use crate::{
hud::get_quality_col,
@ -428,27 +427,9 @@ impl<'a> Widget for Bag<'a> {
.stat_txts
.resize(STATS.len(), &mut ui.widget_id_generator())
});
// Thresholds (lower)
let common = 4.3;
let moderate = 6.0;
let high = 8.0;
let epic = 10.0;
let legendary = 79.0;
let artifact = 122.0;
let debug = 200.0;
// Stats
let combat_rating = combat_rating(inventory, self.health, self.stats).min(999.9);
let indicator_col = match combat_rating {
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,
};
let indicator_col = cr_color(combat_rating);
for i in STATS.iter().copied().enumerate() {
let btn = Button::image(match i.1 {
"Health" => self.imgs.health_ico,

View File

@ -219,7 +219,7 @@ impl<'a> Diary<'a> {
Achievements,
}*/
pub type SelectedSkillTree = skills::SkillGroupType;
pub type SelectedSkillTree = skills::SkillGroupKind;
const TREES: [&str; 7] = [
"General Combat",
@ -379,7 +379,7 @@ impl<'a> Widget for Diary<'a> {
)
})
.map_or(false, |(st, a_pts, e_pts)| {
a_pts > 0 && (e_pts - a_pts) < st.max_skill_points()
a_pts > 0 && (e_pts - a_pts) < st.total_skill_point_cost()
});
if Button::image(
if skill_tree_from_str(i.1).map_or(false, |st| st == *sel_tab || available_pts) {
@ -576,18 +576,26 @@ impl<'a> Widget for Diary<'a> {
//
//
// TOP-LEFT Skills
let offset_0 = 22.0;
let offset_1 = -122.0;
let offset_2 = offset_1 - -20.0;
while self.created_btns_top_l < skills_top_l {
let mut img = Button::image(self.imgs.wpn_icon_border).w_h(80.0, 80.0);
let mut img = Button::image(self.imgs.wpn_icon_border_skills).w_h(80.0, 100.0);
match self.created_btns_top_l {
0 => img = img.middle_of(state.skills_top_l_align), // Central Skill
1 => img = img.up_from(state.skills_top_l[0], 4.0), // 12:00
2 => img = img.down_from(state.skills_top_l[0], 4.0), // 6:00
3 => img = img.left_from(state.skills_top_l[0], 4.0), // 3:00
4 => img = img.right_from(state.skills_top_l[0], 4.0), // 9:00
5 => img = img.top_left_with_margins_on(state.skills_top_l[0], -84.0, -84.0), /* 10:30 */
6 => img = img.top_right_with_margins_on(state.skills_top_l[0], -84.0, -84.0), /* 1:30 */
7 => img = img.bottom_left_with_margins_on(state.skills_top_l[0], -84.0, -84.0), /* 4:30 */
8 => img = img.bottom_right_with_margins_on(state.skills_top_l[0], -84.0, -84.0), /* 7:30 */
1 => img = img.up_from(state.skills_top_l[0], offset_0), // 12:00
2 => img = img.down_from(state.skills_top_l[0], offset_0), // 6:00
3 => img = img.left_from(state.skills_top_l[0], offset_0), // 3:00
4 => img = img.right_from(state.skills_top_l[0], offset_0), // 9:00
5 => img = img.top_left_with_margins_on(state.skills_top_l[0], offset_1, offset_2), /* 10:30 */
6 => img = img.top_right_with_margins_on(state.skills_top_l[0], offset_1, offset_2), /* 1:30 */
7 => {
img = img.bottom_left_with_margins_on(state.skills_top_l[0], offset_1, offset_2)
}, /* 4:30 */
8 => {
img =
img.bottom_right_with_margins_on(state.skills_top_l[0], offset_1, offset_2)
}, /* 7:30 */
_ => {},
}
img.set(state.skills_top_l[self.created_btns_top_l], ui);
@ -595,17 +603,22 @@ impl<'a> Widget for Diary<'a> {
}
// TOP-RIGHT Skills
while self.created_btns_top_r < skills_top_r {
let mut img = Button::image(self.imgs.wpn_icon_border).w_h(80.0, 80.0);
let mut img = Button::image(self.imgs.wpn_icon_border_skills).w_h(80.0, 100.0);
match self.created_btns_top_r {
0 => img = img.middle_of(state.skills_top_r_align), // Central Skill
1 => img = img.up_from(state.skills_top_r[0], 4.0), // 12:00
2 => img = img.down_from(state.skills_top_r[0], 4.0), // 6:00
3 => img = img.left_from(state.skills_top_r[0], 4.0), // 3:00
4 => img = img.right_from(state.skills_top_r[0], 4.0), // 9:00
5 => img = img.top_left_with_margins_on(state.skills_top_r[0], -84.0, -84.0), /* 10:30 */
6 => img = img.top_right_with_margins_on(state.skills_top_r[0], -84.0, -84.0), /* 1:30 */
7 => img = img.bottom_left_with_margins_on(state.skills_top_r[0], -84.0, -84.0), /* 4:30 */
8 => img = img.bottom_right_with_margins_on(state.skills_top_r[0], -84.0, -84.0), /* 7:30 */
1 => img = img.up_from(state.skills_top_r[0], offset_0), // 12:00
2 => img = img.down_from(state.skills_top_r[0], offset_0), // 6:00
3 => img = img.left_from(state.skills_top_r[0], offset_0), // 3:00
4 => img = img.right_from(state.skills_top_r[0], offset_0), // 9:00
5 => img = img.top_left_with_margins_on(state.skills_top_r[0], offset_1, offset_2), /* 10:30 */
6 => img = img.top_right_with_margins_on(state.skills_top_r[0], offset_1, offset_2), /* 1:30 */
7 => {
img = img.bottom_left_with_margins_on(state.skills_top_r[0], offset_1, offset_2)
}, /* 4:30 */
8 => {
img =
img.bottom_right_with_margins_on(state.skills_top_r[0], offset_1, offset_2)
}, /* 7:30 */
_ => {},
}
img.set(state.skills_top_r[self.created_btns_top_r], ui);
@ -613,17 +626,22 @@ impl<'a> Widget for Diary<'a> {
}
// BOTTOM-LEFT Skills
while self.created_btns_bot_l < skills_bot_l {
let mut img = Button::image(self.imgs.wpn_icon_border).w_h(80.0, 80.0);
let mut img = Button::image(self.imgs.wpn_icon_border_skills).w_h(80.0, 100.0);
match self.created_btns_bot_l {
0 => img = img.middle_of(state.skills_bot_l_align), // Central Skill
1 => img = img.up_from(state.skills_bot_l[0], 4.0), // 12:00
2 => img = img.down_from(state.skills_bot_l[0], 4.0), // 6:00
3 => img = img.left_from(state.skills_bot_l[0], 4.0), // 3:00
4 => img = img.right_from(state.skills_bot_l[0], 4.0), // 9:00
5 => img = img.top_left_with_margins_on(state.skills_bot_l[0], -84.0, -84.0), /* 10:30 */
6 => img = img.top_right_with_margins_on(state.skills_bot_l[0], -84.0, -84.0), /* 1:30 */
7 => img = img.bottom_left_with_margins_on(state.skills_bot_l[0], -84.0, -84.0), /* 4:30 */
8 => img = img.bottom_right_with_margins_on(state.skills_bot_l[0], -84.0, -84.0), /* 7:30 */
1 => img = img.up_from(state.skills_bot_l[0], offset_0), // 12:00
2 => img = img.down_from(state.skills_bot_l[0], offset_0), // 6:00
3 => img = img.left_from(state.skills_bot_l[0], offset_0), // 3:00
4 => img = img.right_from(state.skills_bot_l[0], offset_0), // 9:00
5 => img = img.top_left_with_margins_on(state.skills_bot_l[0], offset_1, offset_2), /* 10:30 */
6 => img = img.top_right_with_margins_on(state.skills_bot_l[0], offset_1, offset_2), /* 1:30 */
7 => {
img = img.bottom_left_with_margins_on(state.skills_bot_l[0], offset_1, offset_2)
}, /* 4:30 */
8 => {
img =
img.bottom_right_with_margins_on(state.skills_bot_l[0], offset_1, offset_2)
}, /* 7:30 */
_ => {},
}
img.set(state.skills_bot_l[self.created_btns_bot_l], ui);
@ -631,20 +649,25 @@ impl<'a> Widget for Diary<'a> {
}
// BOTTOM-RIGHT Skills
while self.created_btns_bot_r < skills_bot_r {
let mut btn = Image::new(self.imgs.wpn_icon_border).w_h(80.0, 80.0);
let mut img = Image::new(self.imgs.wpn_icon_border_skills).w_h(80.0, 100.0);
match self.created_btns_bot_r {
0 => btn = btn.middle_of(state.skills_bot_r_align), // Central Skill
1 => btn = btn.up_from(state.skills_bot_r[0], 4.0), // 12:00
2 => btn = btn.down_from(state.skills_bot_r[0], 4.0), // 6:00
3 => btn = btn.left_from(state.skills_bot_r[0], 4.0), // 3:00
4 => btn = btn.right_from(state.skills_bot_r[0], 4.0), // 9:00
5 => btn = btn.top_left_with_margins_on(state.skills_bot_r[0], -84.0, -84.0), /* 10:30 */
6 => btn = btn.top_right_with_margins_on(state.skills_bot_r[0], -84.0, -84.0), /* 1:30 */
7 => btn = btn.bottom_left_with_margins_on(state.skills_bot_r[0], -84.0, -84.0), /* 4:30 */
8 => btn = btn.bottom_right_with_margins_on(state.skills_bot_r[0], -84.0, -84.0), /* 7:30 */
0 => img = img.middle_of(state.skills_bot_r_align), // Central Skill
1 => img = img.up_from(state.skills_bot_r[0], offset_0), // 12:00
2 => img = img.down_from(state.skills_bot_r[0], offset_0), // 6:00
3 => img = img.left_from(state.skills_bot_r[0], offset_0), // 3:00
4 => img = img.right_from(state.skills_bot_r[0], offset_0), // 9:00
5 => img = img.top_left_with_margins_on(state.skills_bot_r[0], offset_1, offset_2), /* 10:30 */
6 => img = img.top_right_with_margins_on(state.skills_bot_r[0], offset_1, offset_2), /* 1:30 */
7 => {
img = img.bottom_left_with_margins_on(state.skills_bot_r[0], offset_1, offset_2)
}, /* 4:30 */
8 => {
img =
img.bottom_right_with_margins_on(state.skills_bot_r[0], offset_1, offset_2)
}, /* 7:30 */
_ => {},
}
btn.set(state.skills_bot_r[self.created_btns_bot_r], ui);
img.set(state.skills_bot_r[self.created_btns_bot_r], ui);
self.created_btns_bot_r += 1;
}
// Skill-Icons and Functionality
@ -652,7 +675,7 @@ impl<'a> Widget for Diary<'a> {
let art_size = [320.0, 320.0];
match sel_tab {
SelectedSkillTree::General => {
use skills::{GeneralSkill::*, RollSkill::*, SkillGroupType::*};
use skills::{GeneralSkill::*, RollSkill::*, SkillGroupKind::*};
use ToolKind::*;
// General Combat
Image::new(
@ -3395,10 +3418,10 @@ fn create_skill_button<'a>(
) -> Button<'a, button::Image> {
Button::image(image)
.w_h(74.0, 74.0)
.middle_of(state)
.mid_top_with_margin_on(state, 3.0)
.label(label)
.label_y(conrod_core::position::Relative::Scalar(-28.0))
.label_x(conrod_core::position::Relative::Scalar(32.0))
.label_y(conrod_core::position::Relative::Scalar(-47.0))
.label_x(conrod_core::position::Relative::Scalar(0.0))
.label_color(if skill_set.is_at_max_level(skill) {
TEXT_COLOR
} else if skill_set.sufficient_skill_points(skill) {
@ -3406,7 +3429,7 @@ fn create_skill_button<'a>(
} else {
CRITICAL_HP_COLOR
})
.label_font_size(fonts.cyri.scale(16))
.label_font_size(fonts.cyri.scale(15))
.label_font_id(fonts.cyri.conrod_id)
.image_color(if skill_set.prerequisites_met(skill) {
TEXT_COLOR
@ -3447,7 +3470,7 @@ fn add_sp_cost_tooltip<'a>(
localized_strings: &'a Localization,
) -> String {
match skill_set.skill_level(skill) {
Ok(level) if level == skill.max_level() => tooltip.replace("{}", ""),
Ok(level) if level == skill.max_level() => tooltip.replace("{SP}", ""),
_ => tooltip.replace(
"{SP}",
&localized_strings

View File

@ -1,9 +1,8 @@
use super::{
cr_color,
img_ids::{Imgs, ImgsRot},
Show, BLACK, BUFF_COLOR, DEBUFF_COLOR, ERROR_COLOR, GROUP_COLOR, HP_COLOR, KILL_COLOR,
LOW_HP_COLOR, QUALITY_ARTIFACT, QUALITY_COMMON, QUALITY_DEBUG, QUALITY_EPIC, QUALITY_HIGH,
QUALITY_LEGENDARY, QUALITY_LOW, QUALITY_MODERATE, STAMINA_COLOR, TEXT_COLOR, TEXT_COLOR_GREY,
UI_HIGHLIGHT_0, UI_MAIN, XP_COLOR,
LOW_HP_COLOR, STAMINA_COLOR, TEXT_COLOR, TEXT_COLOR_GREY, UI_HIGHLIGHT_0, UI_MAIN,
};
use crate::{
@ -29,8 +28,6 @@ use conrod_core::{
};
use specs::{saveload::MarkerAllocator, WorldExt};
use inline_tweak::*;
widget_ids! {
pub struct Ids {
group_button,
@ -436,38 +433,16 @@ impl<'a> Widget for Group<'a> {
.middle_of(state.ids.member_panels_bg[i])
.color(Some(UI_HIGHLIGHT_0))
.set(state.ids.member_panels_frame[i], ui);
// Thresholds (lower)
let common = 4.3;
let moderate = 6.0;
let high = 8.0;
let epic = 10.0;
let legendary = 79.0;
let artifact = 122.0;
let debug = 200.0;
let indicator_col = match combat_rating {
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,
};
let indicator_col = cr_color(combat_rating);
Image::new(self.imgs.combat_rating_ico_shadow)
.w_h(tweak!(18.0), tweak!(18.0))
.top_left_with_margins_on(
state.ids.member_panels_frame[i],
tweak!(-20.0),
tweak!(2.0),
)
.w_h(18.0, 18.0)
.top_left_with_margins_on(state.ids.member_panels_frame[i], 20.0, 2.0)
.color(Some(indicator_col))
.set(state.ids.combat_rating_indicators[i], ui);
// Panel Text
Text::new(&char_name)
.top_left_with_margins_on(state.ids.member_panels_frame[i], tweak!(-22.0), tweak!(22.0))
.top_left_with_margins_on(state.ids.member_panels_frame[i], -22.0, 22.0)
.font_size(20)
.font_id(self.fonts.cyri.conrod_id)
.color(BLACK)

View File

@ -78,6 +78,7 @@ image_ids! {
bow: "voxygen.element.icons.bow",
staff: "voxygen.element.icons.staff",
lock: "voxygen.element.icons.lock",
wpn_icon_border_skills: "voxygen.element.buttons.border_skills",
wpn_icon_border: "voxygen.element.buttons.border",
wpn_icon_border_mo: "voxygen.element.buttons.border_mo",
wpn_icon_border_press: "voxygen.element.buttons.border_press",

View File

@ -62,7 +62,7 @@ use common::{
comp::{
self,
item::{tool::ToolKind, ItemDesc, Quality},
skills::{Skill, SkillGroupType},
skills::{Skill, SkillGroupKind},
BuffKind,
},
outcome::Outcome,
@ -304,7 +304,7 @@ pub struct ExpFloater {
pub struct SkillPointGain {
pub owner: Uid,
pub skill_tree: SkillGroupType,
pub skill_tree: SkillGroupKind,
pub total_points: u16,
pub timer: f32,
}
@ -1112,24 +1112,29 @@ impl Hud {
} else {
1.0
};
Text::new(&format!("{} Exp", floater.exp_change))
.font_size(font_size_xp)
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(0.0, 0.0, 0.0, fade))
.x_y(
ui_widgets.win_w * (0.5 * floater.rand_offset.0 as f64 - 0.25),
ui_widgets.win_h * (0.15 * floater.rand_offset.1 as f64) + y - 3.0,
)
.set(player_sct_bg_id, ui_widgets);
Text::new(&format!("{} Exp", floater.exp_change))
.font_size(font_size_xp)
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(0.59, 0.41, 0.67, fade))
.x_y(
ui_widgets.win_w * (0.5 * floater.rand_offset.0 as f64 - 0.25),
ui_widgets.win_h * (0.15 * floater.rand_offset.1 as f64) + y,
)
.set(player_sct_id, ui_widgets);
if floater.exp_change > 0 {
// Don't show 0 Exp
Text::new(&format!("{} Exp", floater.exp_change.max(1)))
.font_size(font_size_xp)
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(0.0, 0.0, 0.0, fade))
.x_y(
ui_widgets.win_w * (0.5 * floater.rand_offset.0 as f64 - 0.25),
ui_widgets.win_h * (0.15 * floater.rand_offset.1 as f64) + y
- 3.0,
)
.set(player_sct_bg_id, ui_widgets);
Text::new(&format!("{} Exp", floater.exp_change.max(1)))
.font_size(font_size_xp)
.font_id(self.fonts.cyri.conrod_id)
.color(Color::Rgba(0.59, 0.41, 0.67, fade))
.x_y(
ui_widgets.win_w * (0.5 * floater.rand_offset.0 as f64 - 0.25),
ui_widgets.win_h * (0.15 * floater.rand_offset.1 as f64) + y,
)
.set(player_sct_id, ui_widgets);
}
floater.timer -= dt.as_secs_f32();
}
}
@ -1205,7 +1210,7 @@ impl Hud {
.bottom_left_with_margins_on(self.ids.player_rank_up_txt_1_bg, 2.0, 2.0)
.set(self.ids.player_rank_up_txt_1, ui_widgets);
// Variable skilltree icon
use crate::hud::SkillGroupType::{General, Weapon};
use crate::hud::SkillGroupKind::{General, Weapon};
Image::new(match display.skill_tree {
General => self.imgs.swords_crossed,
Weapon(ToolKind::Hammer) => self.imgs.hammer,
@ -2953,3 +2958,25 @@ fn try_hotbar_slot_from_input(input: GameInput) -> Option<hotbar::Slot> {
_ => return None,
})
}
pub fn cr_color(combat_rating: f32) -> Color {
let common = 4.3;
let moderate = 6.0;
let high = 8.0;
let epic = 10.0;
let legendary = 79.0;
let artifact = 122.0;
let debug = 200.0;
match combat_rating {
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,
}
}

View File

@ -1,8 +1,7 @@
use super::{
img_ids::Imgs, DEFAULT_NPC, ENEMY_HP_COLOR, FACTION_COLOR, GROUP_COLOR, GROUP_MEMBER, HP_COLOR,
LOW_HP_COLOR, QUALITY_ARTIFACT, QUALITY_COMMON, QUALITY_DEBUG, QUALITY_EPIC, QUALITY_HIGH,
QUALITY_LEGENDARY, QUALITY_LOW, QUALITY_MODERATE, REGION_COLOR, SAY_COLOR, STAMINA_COLOR,
TELL_COLOR, TEXT_BG, TEXT_COLOR, XP_COLOR,
cr_color, img_ids::Imgs, DEFAULT_NPC, ENEMY_HP_COLOR, FACTION_COLOR, GROUP_COLOR, GROUP_MEMBER,
HP_COLOR, LOW_HP_COLOR, REGION_COLOR, SAY_COLOR, STAMINA_COLOR, TELL_COLOR, TEXT_BG,
TEXT_COLOR,
};
use crate::{
hud::get_buff_info,
@ -18,7 +17,6 @@ use conrod_core::{
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
};
const MAX_BUBBLE_WIDTH: f64 = 250.0;
use inline_tweak::*;
widget_ids! {
struct Ids {
// Speech bubble
@ -321,19 +319,19 @@ impl<'a> Widget for Overhead<'a> {
// % HP Filling
let size_factor = (hp_percentage / 100.0) * BARSIZE;
let w = if self.in_group {
tweak!(82.0) * size_factor
82.0 * size_factor
} else {
73.0 * size_factor
};
let h = 6.0 * BARSIZE;
let x = if self.in_group {
(tweak!(0.0) + (hp_percentage / 100.0 * tweak!(41.0) - tweak!(41.0))) * BARSIZE
(0.0 + (hp_percentage / 100.0 * 41.0 - 41.0)) * BARSIZE
} else {
(4.5 + (hp_percentage / 100.0 * 36.45 - 36.45)) * BARSIZE
};
Image::new(self.imgs.enemy_bar)
.w_h(w, h)
.x_y(x, MANA_BAR_Y + tweak!(8.0))
.x_y(x, MANA_BAR_Y + 8.0)
.color(if self.in_group {
// Different HP bar colors only for group members
Some(match hp_percentage {
@ -363,12 +361,12 @@ impl<'a> Widget for Overhead<'a> {
let energy_factor = energy.current() as f64 / energy.maximum() as f64;
let size_factor = energy_factor * BARSIZE;
let w = if self.in_group {
tweak!(80.0) * size_factor
80.0 * size_factor
} else {
72.0 * size_factor
};
let x = if self.in_group {
((tweak!(0.0) + (energy_factor * tweak!(40.0))) - tweak!(40.0)) * BARSIZE
((0.0 + (energy_factor * 40.0)) - 40.0) * BARSIZE
} else {
((3.5 + (energy_factor * 36.5)) - 36.45) * BARSIZE
};
@ -388,28 +386,10 @@ impl<'a> Widget for Overhead<'a> {
.parent(id)
.set(state.ids.health_bar_fg, ui);
// Thresholds (lower)
let common = 4.3;
let moderate = 6.0;
let high = 8.0;
let epic = 10.0;
let legendary = 79.0;
let artifact = 122.0;
let debug = 200.0;
let indicator_col = cr_color(combat_rating);
let artifact_diffculty = 122.0;
let indicator_col = match combat_rating {
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,
};
if combat_rating > artifact && !self.in_group {
if combat_rating > artifact_diffculty && !self.in_group {
let skull_ani = ((self.pulse * 0.7/* speed factor */).cos() * 0.5 + 0.5) * 10.0; //Animation timer
Image::new(if skull_ani as i32 == 1 && rand::random::<f32>() < 0.9 {
self.imgs.skull_2
@ -427,8 +407,8 @@ impl<'a> Widget for Overhead<'a> {
} else {
self.imgs.combat_rating_ico
})
.w_h(tweak!(7.0) * BARSIZE, tweak!(7.0) * BARSIZE)
.x_y(tweak!(-37.0) * BARSIZE, MANA_BAR_Y + tweak!(6.0))
.w_h(7.0 * BARSIZE, 7.0 * BARSIZE)
.x_y(-37.0 * BARSIZE, MANA_BAR_Y + 6.0)
.color(Some(indicator_col))
.parent(id)
.set(state.ids.level, ui);

View File

@ -575,7 +575,7 @@ impl<'a> Widget for Skillbar<'a> {
Image::new(self.imgs.skillbar_slot)
.w_h(40.0, 40.0)
.right_from(state.ids.m1_slot_bg, slot_offset)
.set(state.ids.m2_slot, ui);
.set(state.ids.m2_slot_bg, ui);
fn get_tool(inventory: &Inventory, equip_slot: EquipSlot) -> Option<&Tool> {
match inventory.equipped(equip_slot).map(|i| i.kind()) {
@ -596,10 +596,6 @@ impl<'a> Widget for Skillbar<'a> {
(_, _) => None,
};
Image::new(self.imgs.skillbar_slot)
.w_h(40.0, 40.0)
.middle_of(state.ids.m2_slot)
.set(state.ids.m2_slot_bg, ui);
Button::image(match tool.map(|t| t.kind) {
Some(ToolKind::Sword) => self.imgs.twohsword_m2,
Some(ToolKind::Dagger) => self.imgs.onehdagger_m2,
@ -626,7 +622,10 @@ impl<'a> Widget for Skillbar<'a> {
Color::Rgba(0.3, 0.3, 0.3, 0.8)
}
} else {
Color::Rgba(1.0, 1.0, 1.0, 1.0)
match tool.map(|t| t.kind) {
None => Color::Rgba(1.0, 1.0, 1.0, 0.0),
_ => Color::Rgba(1.0, 1.0, 1.0, 1.0),
}
})
.set(state.ids.m2_content, ui);
// Slot 6-10

View File

@ -382,9 +382,13 @@ impl<'a> Widget for Social<'a> {
players.filter(|(uid, _)| Some(**uid) != my_uid).enumerate()
{
let hide_username = true;
let zone = "Wilderness"; // TODO Add real zone
let zone = ""; // TODO Add real zone
let selected = state.selected_uid.map_or(false, |u| u.0 == uid);
let alias = &player_info.player_alias;
let zone_name = match &player_info.character {
None => self.localized_strings.get("hud.group.in_menu").to_string(), /* character select or spectating */
_ => format!("{} ", &zone),
};
let name_text = match &player_info.character {
Some(character) => {
if Some(uid) == my_uid {
@ -394,17 +398,13 @@ impl<'a> Widget for Social<'a> {
&character.name
)
} else if hide_username {
character.name.clone()
format!("{} [{}]", &character.name, zone_name)
} else {
format!("[{}] {}", alias, &character.name)
format!("[{}] {} [{}]", alias, &character.name, zone_name)
}
},
None => alias.clone(), // character select or spectating
};
let zone_name = match &player_info.character {
None => self.localized_strings.get("hud.group.in_menu").to_string(), /* character select or spectating */
_ => format!("{} ", &zone),
};
// Player name widgets
let button = Button::image(if !selected {
self.imgs.nothing