mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Resolve Issue #978 - Extract SkillSet Into Its Own Component
This commit is contained in:
parent
6f9f28af18
commit
568a8d9666
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,6 +5,7 @@ target
|
|||||||
|
|
||||||
**/*.vi
|
**/*.vi
|
||||||
**/*.swp
|
**/*.swp
|
||||||
|
**/*tags
|
||||||
|
|
||||||
# IntelliJ
|
# IntelliJ
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ sum_type! {
|
|||||||
Player(comp::Player),
|
Player(comp::Player),
|
||||||
CanBuild(comp::CanBuild),
|
CanBuild(comp::CanBuild),
|
||||||
Stats(comp::Stats),
|
Stats(comp::Stats),
|
||||||
|
SkillSet(comp::SkillSet),
|
||||||
Buffs(comp::Buffs),
|
Buffs(comp::Buffs),
|
||||||
Auras(comp::Auras),
|
Auras(comp::Auras),
|
||||||
Energy(comp::Energy),
|
Energy(comp::Energy),
|
||||||
@ -48,6 +49,7 @@ sum_type! {
|
|||||||
Player(PhantomData<comp::Player>),
|
Player(PhantomData<comp::Player>),
|
||||||
CanBuild(PhantomData<comp::CanBuild>),
|
CanBuild(PhantomData<comp::CanBuild>),
|
||||||
Stats(PhantomData<comp::Stats>),
|
Stats(PhantomData<comp::Stats>),
|
||||||
|
SkillSet(PhantomData<comp::SkillSet>),
|
||||||
Buffs(PhantomData<comp::Buffs>),
|
Buffs(PhantomData<comp::Buffs>),
|
||||||
Auras(PhantomData<comp::Auras>),
|
Auras(PhantomData<comp::Auras>),
|
||||||
Energy(PhantomData<comp::Energy>),
|
Energy(PhantomData<comp::Energy>),
|
||||||
@ -82,6 +84,7 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
EcsCompPacket::Player(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Player(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::CanBuild(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::CanBuild(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Stats(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Stats(comp) => sync::handle_insert(comp, entity, world),
|
||||||
|
EcsCompPacket::SkillSet(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Buffs(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Buffs(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Auras(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Auras(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Energy(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Energy(comp) => sync::handle_insert(comp, entity, world),
|
||||||
@ -120,6 +123,7 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
EcsCompPacket::Player(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Player(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::CanBuild(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::CanBuild(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Stats(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Stats(comp) => sync::handle_modify(comp, entity, world),
|
||||||
|
EcsCompPacket::SkillSet(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Buffs(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Buffs(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Auras(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Auras(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Energy(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Energy(comp) => sync::handle_modify(comp, entity, world),
|
||||||
@ -158,6 +162,7 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
EcsCompPhantom::Player(_) => sync::handle_remove::<comp::Player>(entity, world),
|
EcsCompPhantom::Player(_) => sync::handle_remove::<comp::Player>(entity, world),
|
||||||
EcsCompPhantom::CanBuild(_) => sync::handle_remove::<comp::CanBuild>(entity, world),
|
EcsCompPhantom::CanBuild(_) => sync::handle_remove::<comp::CanBuild>(entity, world),
|
||||||
EcsCompPhantom::Stats(_) => sync::handle_remove::<comp::Stats>(entity, world),
|
EcsCompPhantom::Stats(_) => sync::handle_remove::<comp::Stats>(entity, world),
|
||||||
|
EcsCompPhantom::SkillSet(_) => sync::handle_remove::<comp::SkillSet>(entity, world),
|
||||||
EcsCompPhantom::Buffs(_) => sync::handle_remove::<comp::Buffs>(entity, world),
|
EcsCompPhantom::Buffs(_) => sync::handle_remove::<comp::Buffs>(entity, world),
|
||||||
EcsCompPhantom::Auras(_) => sync::handle_remove::<comp::Auras>(entity, world),
|
EcsCompPhantom::Auras(_) => sync::handle_remove::<comp::Auras>(entity, world),
|
||||||
EcsCompPhantom::Energy(_) => sync::handle_remove::<comp::Energy>(entity, world),
|
EcsCompPhantom::Energy(_) => sync::handle_remove::<comp::Energy>(entity, world),
|
||||||
|
@ -13,7 +13,7 @@ use crate::{
|
|||||||
poise::PoiseChange,
|
poise::PoiseChange,
|
||||||
skills::SkillGroupKind,
|
skills::SkillGroupKind,
|
||||||
Body, Combo, Energy, EnergyChange, EnergySource, Health, HealthChange, HealthSource,
|
Body, Combo, Energy, EnergyChange, EnergySource, Health, HealthChange, HealthSource,
|
||||||
Inventory, Stats,
|
Inventory, SkillSet, Stats,
|
||||||
},
|
},
|
||||||
event::ServerEvent,
|
event::ServerEvent,
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
@ -742,15 +742,15 @@ pub fn weapon_rating<T: ItemDesc>(item: &T, msm: &MaterialStatManifest) -> f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn weapon_skills(inventory: &Inventory, stats: &Stats) -> f32 {
|
fn weapon_skills(inventory: &Inventory, skill_set: &SkillSet) -> f32 {
|
||||||
let (mainhand, offhand) = get_weapons(inventory);
|
let (mainhand, offhand) = get_weapons(inventory);
|
||||||
let mainhand_skills = if let Some(tool) = mainhand {
|
let mainhand_skills = if let Some(tool) = mainhand {
|
||||||
stats.skill_set.earned_sp(SkillGroupKind::Weapon(tool)) as f32
|
skill_set.earned_sp(SkillGroupKind::Weapon(tool)) as f32
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
};
|
};
|
||||||
let offhand_skills = if let Some(tool) = offhand {
|
let offhand_skills = if let Some(tool) = offhand {
|
||||||
stats.skill_set.earned_sp(SkillGroupKind::Weapon(tool)) as f32
|
skill_set.earned_sp(SkillGroupKind::Weapon(tool)) as f32
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
};
|
};
|
||||||
@ -779,7 +779,7 @@ fn get_weapon_rating(inventory: &Inventory, msm: &MaterialStatManifest) -> f32 {
|
|||||||
pub fn combat_rating(
|
pub fn combat_rating(
|
||||||
inventory: &Inventory,
|
inventory: &Inventory,
|
||||||
health: &Health,
|
health: &Health,
|
||||||
stats: &Stats,
|
skill_set: &SkillSet,
|
||||||
body: Body,
|
body: Body,
|
||||||
msm: &MaterialStatManifest,
|
msm: &MaterialStatManifest,
|
||||||
) -> f32 {
|
) -> f32 {
|
||||||
@ -793,8 +793,8 @@ pub fn combat_rating(
|
|||||||
|
|
||||||
// Assumes a standard person has earned 20 skill points in the general skill
|
// Assumes a standard person has earned 20 skill points in the general skill
|
||||||
// tree and 10 skill points for the weapon skill tree
|
// tree and 10 skill points for the weapon skill tree
|
||||||
let skills_rating = (stats.skill_set.earned_sp(SkillGroupKind::General) as f32 / 20.0
|
let skills_rating = (skill_set.earned_sp(SkillGroupKind::General) as f32 / 20.0
|
||||||
+ weapon_skills(inventory, stats) / 10.0)
|
+ weapon_skills(inventory, skill_set) / 10.0)
|
||||||
/ 2.0;
|
/ 2.0;
|
||||||
|
|
||||||
let weapon_rating = get_weapon_rating(inventory, msm);
|
let weapon_rating = get_weapon_rating(inventory, msm);
|
||||||
|
@ -5,6 +5,8 @@ use crate::{
|
|||||||
use hashbrown::{HashMap, HashSet};
|
use hashbrown::{HashMap, HashSet};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use specs::{Component, DerefFlaggedStorage};
|
||||||
|
use specs_idvs::IdvStorage;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use tracing::{trace, warn};
|
use tracing::{trace, warn};
|
||||||
|
|
||||||
@ -334,6 +336,10 @@ pub struct SkillSet {
|
|||||||
pub modify_energy: bool,
|
pub modify_energy: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Component for SkillSet {
|
||||||
|
type Storage = DerefFlaggedStorage<Self, IdvStorage<Self>>;
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for SkillSet {
|
impl Default for SkillSet {
|
||||||
/// Instantiate a new skill set with the default skill groups with no
|
/// Instantiate a new skill set with the default skill groups with no
|
||||||
/// unlocked skills in them - used when adding a skill set to a new
|
/// unlocked skills in them - used when adding a skill set to a new
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use crate::comp::skills::SkillSet;
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{Component, DerefFlaggedStorage};
|
use specs::{Component, DerefFlaggedStorage};
|
||||||
use specs_idvs::IdvStorage;
|
use specs_idvs::IdvStorage;
|
||||||
@ -24,9 +23,6 @@ impl Error for StatChangeError {}
|
|||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct Stats {
|
pub struct Stats {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
// TODO: Make skillset a separate component, probably too heavy for something that will
|
|
||||||
// potentially be updated every tick (especially as more buffs are added)
|
|
||||||
pub skill_set: SkillSet,
|
|
||||||
pub damage_reduction: f32,
|
pub damage_reduction: f32,
|
||||||
pub max_health_modifier: f32,
|
pub max_health_modifier: f32,
|
||||||
}
|
}
|
||||||
@ -35,7 +31,6 @@ impl Stats {
|
|||||||
pub fn new(name: String) -> Self {
|
pub fn new(name: String) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
skill_set: SkillSet::default(),
|
|
||||||
damage_reduction: 0.0,
|
damage_reduction: 0.0,
|
||||||
max_health_modifier: 1.0,
|
max_health_modifier: 1.0,
|
||||||
}
|
}
|
||||||
@ -46,7 +41,6 @@ impl Stats {
|
|||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: "".to_owned(),
|
name: "".to_owned(),
|
||||||
skill_set: SkillSet::default(),
|
|
||||||
damage_reduction: 0.0,
|
damage_reduction: 0.0,
|
||||||
max_health_modifier: 1.0,
|
max_health_modifier: 1.0,
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,7 @@ pub enum ServerEvent {
|
|||||||
components: (
|
components: (
|
||||||
comp::Body,
|
comp::Body,
|
||||||
comp::Stats,
|
comp::Stats,
|
||||||
|
comp::SkillSet,
|
||||||
comp::Inventory,
|
comp::Inventory,
|
||||||
Option<comp::Waypoint>,
|
Option<comp::Waypoint>,
|
||||||
),
|
),
|
||||||
@ -115,6 +116,7 @@ pub enum ServerEvent {
|
|||||||
CreateNpc {
|
CreateNpc {
|
||||||
pos: comp::Pos,
|
pos: comp::Pos,
|
||||||
stats: comp::Stats,
|
stats: comp::Stats,
|
||||||
|
skill_set: comp::SkillSet,
|
||||||
health: comp::Health,
|
health: comp::Health,
|
||||||
poise: comp::Poise,
|
poise: comp::Poise,
|
||||||
loadout: comp::inventory::loadout::Loadout,
|
loadout: comp::inventory::loadout::Loadout,
|
||||||
|
@ -86,8 +86,8 @@ impl CharacterBehavior for Data {
|
|||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
let mut stats = comp::Stats::new("Summon".to_string());
|
let stats = comp::Stats::new("Summon".to_string());
|
||||||
stats.skill_set = SkillSetBuilder::build_skillset(
|
let skill_set = SkillSetBuilder::build_skillset(
|
||||||
&None,
|
&None,
|
||||||
self.static_data.summon_info.skillset_config,
|
self.static_data.summon_info.skillset_config,
|
||||||
)
|
)
|
||||||
@ -97,6 +97,7 @@ impl CharacterBehavior for Data {
|
|||||||
update.server_events.push_front(ServerEvent::CreateNpc {
|
update.server_events.push_front(ServerEvent::CreateNpc {
|
||||||
pos: *data.pos,
|
pos: *data.pos,
|
||||||
stats,
|
stats,
|
||||||
|
skill_set,
|
||||||
health: comp::Health::new(
|
health: comp::Health::new(
|
||||||
body,
|
body,
|
||||||
self.static_data.summon_info.health_scaling,
|
self.static_data.summon_info.health_scaling,
|
||||||
|
@ -2,7 +2,7 @@ use crate::{
|
|||||||
comp::{
|
comp::{
|
||||||
self, item::MaterialStatManifest, Beam, Body, CharacterState, Combo, ControlAction,
|
self, item::MaterialStatManifest, Beam, Body, CharacterState, Combo, ControlAction,
|
||||||
Controller, ControllerInputs, Energy, Health, InputAttr, InputKind, Inventory,
|
Controller, ControllerInputs, Energy, Health, InputAttr, InputKind, Inventory,
|
||||||
InventoryAction, Melee, Ori, PhysicsState, Pos, StateUpdate, Stats, Vel,
|
InventoryAction, Melee, Ori, PhysicsState, Pos, SkillSet, StateUpdate, Stats, Vel,
|
||||||
},
|
},
|
||||||
resources::DeltaTime,
|
resources::DeltaTime,
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
@ -91,6 +91,7 @@ pub struct JoinData<'a> {
|
|||||||
pub melee_attack: Option<&'a Melee>,
|
pub melee_attack: Option<&'a Melee>,
|
||||||
pub updater: &'a LazyUpdate,
|
pub updater: &'a LazyUpdate,
|
||||||
pub stats: &'a Stats,
|
pub stats: &'a Stats,
|
||||||
|
pub skill_set: &'a SkillSet,
|
||||||
pub msm: &'a MaterialStatManifest,
|
pub msm: &'a MaterialStatManifest,
|
||||||
pub combo: &'a Combo,
|
pub combo: &'a Combo,
|
||||||
pub alignment: Option<&'a comp::Alignment>,
|
pub alignment: Option<&'a comp::Alignment>,
|
||||||
@ -121,6 +122,7 @@ pub struct JoinStruct<'a> {
|
|||||||
pub melee_attack: Option<&'a Melee>,
|
pub melee_attack: Option<&'a Melee>,
|
||||||
pub beam: Option<&'a Beam>,
|
pub beam: Option<&'a Beam>,
|
||||||
pub stat: &'a Stats,
|
pub stat: &'a Stats,
|
||||||
|
pub skill_set: &'a SkillSet,
|
||||||
pub combo: &'a Combo,
|
pub combo: &'a Combo,
|
||||||
pub alignment: Option<&'a comp::Alignment>,
|
pub alignment: Option<&'a comp::Alignment>,
|
||||||
}
|
}
|
||||||
@ -148,6 +150,7 @@ impl<'a> JoinData<'a> {
|
|||||||
physics: j.physics,
|
physics: j.physics,
|
||||||
melee_attack: j.melee_attack,
|
melee_attack: j.melee_attack,
|
||||||
stats: j.stat,
|
stats: j.stat,
|
||||||
|
skill_set: j.skill_set,
|
||||||
updater,
|
updater,
|
||||||
dt,
|
dt,
|
||||||
msm,
|
msm,
|
||||||
|
@ -31,10 +31,10 @@ pub struct Data {
|
|||||||
impl Data {
|
impl Data {
|
||||||
pub fn create_adjusted_by_skills(join_data: &JoinData) -> Self {
|
pub fn create_adjusted_by_skills(join_data: &JoinData) -> Self {
|
||||||
let mut data = Data::default();
|
let mut data = Data::default();
|
||||||
if let Ok(Some(level)) = join_data.stats.skill_set.skill_level(Skill::Climb(Cost)) {
|
if let Ok(Some(level)) = join_data.skill_set.skill_level(Skill::Climb(Cost)) {
|
||||||
data.static_data.energy_cost *= 0.8_f32.powi(level.into());
|
data.static_data.energy_cost *= 0.8_f32.powi(level.into());
|
||||||
}
|
}
|
||||||
if let Ok(Some(level)) = join_data.stats.skill_set.skill_level(Skill::Climb(Speed)) {
|
if let Ok(Some(level)) = join_data.skill_set.skill_level(Skill::Climb(Speed)) {
|
||||||
data.static_data.movement_speed *= 1.2_f32.powi(level.into());
|
data.static_data.movement_speed *= 1.2_f32.powi(level.into());
|
||||||
}
|
}
|
||||||
data
|
data
|
||||||
|
@ -302,11 +302,7 @@ pub fn handle_orientation(data: &JoinData, update: &mut StateUpdate, rate: f32)
|
|||||||
fn swim_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32, depth: f32) {
|
fn swim_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32, depth: f32) {
|
||||||
let mut water_accel = BASE_HUMANOID_WATER_ACCEL;
|
let mut water_accel = BASE_HUMANOID_WATER_ACCEL;
|
||||||
let mut water_speed = BASE_HUMANOID_WATER_SPEED;
|
let mut water_speed = BASE_HUMANOID_WATER_SPEED;
|
||||||
if let Ok(Some(level)) = data
|
if let Ok(Some(level)) = data.skill_set.skill_level(Skill::Swim(SwimSkill::Speed)) {
|
||||||
.stats
|
|
||||||
.skill_set
|
|
||||||
.skill_level(Skill::Swim(SwimSkill::Speed))
|
|
||||||
{
|
|
||||||
water_speed *= 1.4_f32.powi(level.into());
|
water_speed *= 1.4_f32.powi(level.into());
|
||||||
water_accel *= 1.4_f32.powi(level.into());
|
water_accel *= 1.4_f32.powi(level.into());
|
||||||
}
|
}
|
||||||
@ -501,8 +497,7 @@ fn handle_ability(data: &JoinData, update: &mut StateUpdate, input: InputKind) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let unlocked = |(s, a): (Option<Skill>, CharacterAbility)| {
|
let unlocked = |(s, a): (Option<Skill>, CharacterAbility)| {
|
||||||
s.map_or(true, |s| data.stats.skill_set.has_skill(s))
|
s.map_or(true, |s| data.skill_set.has_skill(s)).then_some(a)
|
||||||
.then_some(a)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(equip_slot) = equip_slot {
|
if let Some(equip_slot) = equip_slot {
|
||||||
@ -523,7 +518,7 @@ fn handle_ability(data: &JoinData, update: &mut StateUpdate, input: InputKind) {
|
|||||||
})
|
})
|
||||||
.map(|a| {
|
.map(|a| {
|
||||||
let tool = unwrap_tool_data(data, equip_slot).map(|t| t.kind);
|
let tool = unwrap_tool_data(data, equip_slot).map(|t| t.kind);
|
||||||
a.adjusted_by_skills(&data.stats.skill_set, tool)
|
a.adjusted_by_skills(&data.skill_set, tool)
|
||||||
})
|
})
|
||||||
.filter(|ability| ability.requirements_paid(data, update))
|
.filter(|ability| ability.requirements_paid(data, update))
|
||||||
{
|
{
|
||||||
@ -570,8 +565,7 @@ pub fn attempt_input(data: &JoinData, update: &mut StateUpdate) {
|
|||||||
/// attempts to perform their dodge ability
|
/// attempts to perform their dodge ability
|
||||||
pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
|
pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
|
||||||
if input_is_pressed(data, InputKind::Roll) && data.body.is_humanoid() {
|
if input_is_pressed(data, InputKind::Roll) && data.body.is_humanoid() {
|
||||||
let ability =
|
let ability = CharacterAbility::default_roll().adjusted_by_skills(&data.skill_set, None);
|
||||||
CharacterAbility::default_roll().adjusted_by_skills(&data.stats.skill_set, None);
|
|
||||||
if ability.requirements_paid(data, update) {
|
if ability.requirements_paid(data, update) {
|
||||||
update.character = CharacterState::from((
|
update.character = CharacterState::from((
|
||||||
&ability,
|
&ability,
|
||||||
|
@ -11,7 +11,7 @@ use common::{
|
|||||||
slot::{EquipSlot, Slot},
|
slot::{EquipSlot, Slot},
|
||||||
},
|
},
|
||||||
Beam, Body, CharacterState, Combo, Controller, Energy, Health, Inventory, Melee, Mounting,
|
Beam, Body, CharacterState, Combo, Controller, Energy, Health, Inventory, Melee, Mounting,
|
||||||
Ori, PhysicsState, Poise, PoiseState, Pos, StateUpdate, Stats, Vel,
|
Ori, PhysicsState, Poise, PoiseState, Pos, SkillSet, StateUpdate, Stats, Vel,
|
||||||
},
|
},
|
||||||
event::{EventBus, LocalEvent, ServerEvent},
|
event::{EventBus, LocalEvent, ServerEvent},
|
||||||
resources::DeltaTime,
|
resources::DeltaTime,
|
||||||
@ -73,6 +73,7 @@ pub struct ReadData<'a> {
|
|||||||
uids: ReadStorage<'a, Uid>,
|
uids: ReadStorage<'a, Uid>,
|
||||||
mountings: ReadStorage<'a, Mounting>,
|
mountings: ReadStorage<'a, Mounting>,
|
||||||
stats: ReadStorage<'a, Stats>,
|
stats: ReadStorage<'a, Stats>,
|
||||||
|
skill_sets: ReadStorage<'a, SkillSet>,
|
||||||
msm: Read<'a, MaterialStatManifest>,
|
msm: Read<'a, MaterialStatManifest>,
|
||||||
combos: ReadStorage<'a, Combo>,
|
combos: ReadStorage<'a, Combo>,
|
||||||
alignments: ReadStorage<'a, comp::Alignment>,
|
alignments: ReadStorage<'a, comp::Alignment>,
|
||||||
@ -134,6 +135,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
body,
|
body,
|
||||||
physics,
|
physics,
|
||||||
stat,
|
stat,
|
||||||
|
skill_set,
|
||||||
combo,
|
combo,
|
||||||
) in (
|
) in (
|
||||||
&read_data.entities,
|
&read_data.entities,
|
||||||
@ -149,6 +151,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
&read_data.bodies,
|
&read_data.bodies,
|
||||||
&read_data.physics_states,
|
&read_data.physics_states,
|
||||||
&read_data.stats,
|
&read_data.stats,
|
||||||
|
&read_data.skill_sets,
|
||||||
&read_data.combos,
|
&read_data.combos,
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
@ -259,6 +262,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
melee_attack: read_data.melee_attacks.get(entity),
|
melee_attack: read_data.melee_attacks.get(entity),
|
||||||
beam: read_data.beams.get(entity),
|
beam: read_data.beams.get(entity),
|
||||||
stat: &stat,
|
stat: &stat,
|
||||||
|
skill_set: &skill_set,
|
||||||
combo: &combo,
|
combo: &combo,
|
||||||
alignment: read_data.alignments.get(entity),
|
alignment: read_data.alignments.get(entity),
|
||||||
};
|
};
|
||||||
|
@ -183,6 +183,7 @@ impl State {
|
|||||||
ecs.register::<comp::Body>();
|
ecs.register::<comp::Body>();
|
||||||
ecs.register::<comp::Player>();
|
ecs.register::<comp::Player>();
|
||||||
ecs.register::<comp::Stats>();
|
ecs.register::<comp::Stats>();
|
||||||
|
ecs.register::<comp::SkillSet>();
|
||||||
ecs.register::<comp::Buffs>();
|
ecs.register::<comp::Buffs>();
|
||||||
ecs.register::<comp::Auras>();
|
ecs.register::<comp::Auras>();
|
||||||
ecs.register::<comp::Energy>();
|
ecs.register::<comp::Energy>();
|
||||||
|
@ -3,7 +3,7 @@ use common::{
|
|||||||
self,
|
self,
|
||||||
skills::{GeneralSkill, Skill},
|
skills::{GeneralSkill, Skill},
|
||||||
Body, CharacterState, Combo, Energy, EnergyChange, EnergySource, Health, Poise,
|
Body, CharacterState, Combo, Energy, EnergyChange, EnergySource, Health, Poise,
|
||||||
PoiseChange, PoiseSource, Pos, Stats,
|
PoiseChange, PoiseSource, Pos, SkillSet, Stats,
|
||||||
},
|
},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
@ -40,6 +40,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
type SystemData = (
|
type SystemData = (
|
||||||
ReadData<'a>,
|
ReadData<'a>,
|
||||||
WriteStorage<'a, Stats>,
|
WriteStorage<'a, Stats>,
|
||||||
|
WriteStorage<'a, SkillSet>,
|
||||||
WriteStorage<'a, Health>,
|
WriteStorage<'a, Health>,
|
||||||
WriteStorage<'a, Poise>,
|
WriteStorage<'a, Poise>,
|
||||||
WriteStorage<'a, Energy>,
|
WriteStorage<'a, Energy>,
|
||||||
@ -55,7 +56,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
_job: &mut Job<Self>,
|
_job: &mut Job<Self>,
|
||||||
(
|
(
|
||||||
read_data,
|
read_data,
|
||||||
mut stats,
|
stats,
|
||||||
|
mut skill_sets,
|
||||||
mut healths,
|
mut healths,
|
||||||
mut poises,
|
mut poises,
|
||||||
mut energies,
|
mut energies,
|
||||||
@ -79,10 +81,11 @@ impl<'a> System<'a> for Sys {
|
|||||||
poises.set_event_emission(true);
|
poises.set_event_emission(true);
|
||||||
|
|
||||||
// Update stats
|
// Update stats
|
||||||
for (entity, uid, mut stats, mut health, pos) in (
|
for (entity, uid, stats, mut skill_set, mut health, pos) in (
|
||||||
&read_data.entities,
|
&read_data.entities,
|
||||||
&read_data.uids,
|
&read_data.uids,
|
||||||
&mut stats.restrict_mut(),
|
&stats,
|
||||||
|
&mut skill_sets.restrict_mut(),
|
||||||
&mut healths.restrict_mut(),
|
&mut healths.restrict_mut(),
|
||||||
&read_data.positions,
|
&read_data.positions,
|
||||||
)
|
)
|
||||||
@ -102,8 +105,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
|
|
||||||
health.is_dead = true;
|
health.is_dead = true;
|
||||||
}
|
}
|
||||||
|
let stat = stats;
|
||||||
let stat = stats.get_unchecked();
|
|
||||||
|
|
||||||
let update_max_hp = {
|
let update_max_hp = {
|
||||||
let health = health.get_unchecked();
|
let health = health.get_unchecked();
|
||||||
@ -116,24 +118,24 @@ impl<'a> System<'a> for Sys {
|
|||||||
health.scale_maximum(stat.max_health_modifier);
|
health.scale_maximum(stat.max_health_modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
let skills_to_level = stat
|
let skillset = skill_set.get_unchecked();
|
||||||
.skill_set
|
let skills_to_level = skillset
|
||||||
.skill_groups
|
.skill_groups
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|s_g| {
|
.filter_map(|s_g| {
|
||||||
(s_g.exp >= stat.skill_set.skill_point_cost(s_g.skill_group_kind))
|
(s_g.exp >= skillset.skill_point_cost(s_g.skill_group_kind))
|
||||||
.then(|| s_g.skill_group_kind)
|
.then(|| s_g.skill_group_kind)
|
||||||
})
|
})
|
||||||
.collect::<HashSet<_>>();
|
.collect::<HashSet<_>>();
|
||||||
|
|
||||||
if !skills_to_level.is_empty() {
|
if !skills_to_level.is_empty() {
|
||||||
let mut stat = stats.get_mut_unchecked();
|
let mut skill_set = skill_set.get_mut_unchecked();
|
||||||
for skill_group in skills_to_level {
|
for skill_group in skills_to_level {
|
||||||
stat.skill_set.earn_skill_point(skill_group);
|
skill_set.earn_skill_point(skill_group);
|
||||||
outcomes.push(Outcome::SkillPointGain {
|
outcomes.push(Outcome::SkillPointGain {
|
||||||
uid: *uid,
|
uid: *uid,
|
||||||
skill_tree: skill_group,
|
skill_tree: skill_group,
|
||||||
total_points: stat.skill_set.earned_sp(skill_group),
|
total_points: skill_set.earned_sp(skill_group),
|
||||||
pos: pos.0,
|
pos: pos.0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -141,37 +143,35 @@ impl<'a> System<'a> for Sys {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Apply effects from leveling skills
|
// Apply effects from leveling skills
|
||||||
for (mut stats, mut health, mut energy, body) in (
|
for (mut skill_set, mut health, mut energy, body) in (
|
||||||
&mut stats.restrict_mut(),
|
&mut skill_sets.restrict_mut(),
|
||||||
&mut healths.restrict_mut(),
|
&mut healths.restrict_mut(),
|
||||||
&mut energies.restrict_mut(),
|
&mut energies.restrict_mut(),
|
||||||
&read_data.bodies,
|
&read_data.bodies,
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
{
|
{
|
||||||
let stat = stats.get_unchecked();
|
let skillset = skill_set.get_unchecked();
|
||||||
if stat.skill_set.modify_health {
|
if skillset.modify_health {
|
||||||
let mut health = health.get_mut_unchecked();
|
let mut health = health.get_mut_unchecked();
|
||||||
let health_level = stat
|
let health_level = skillset
|
||||||
.skill_set
|
|
||||||
.skill_level(Skill::General(GeneralSkill::HealthIncrease))
|
.skill_level(Skill::General(GeneralSkill::HealthIncrease))
|
||||||
.unwrap_or(None)
|
.unwrap_or(None)
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
health.update_max_hp(Some(*body), health_level);
|
health.update_max_hp(Some(*body), health_level);
|
||||||
let mut stat = stats.get_mut_unchecked();
|
let mut skillset = skill_set.get_mut_unchecked();
|
||||||
stat.skill_set.modify_health = false;
|
skillset.modify_health = false;
|
||||||
}
|
}
|
||||||
let stat = stats.get_unchecked();
|
let skillset = skill_set.get_unchecked();
|
||||||
if stat.skill_set.modify_energy {
|
if skillset.modify_energy {
|
||||||
let mut energy = energy.get_mut_unchecked();
|
let mut energy = energy.get_mut_unchecked();
|
||||||
let energy_level = stat
|
let energy_level = skillset
|
||||||
.skill_set
|
|
||||||
.skill_level(Skill::General(GeneralSkill::EnergyIncrease))
|
.skill_level(Skill::General(GeneralSkill::EnergyIncrease))
|
||||||
.unwrap_or(None)
|
.unwrap_or(None)
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
energy.update_max_energy(Some(*body), energy_level);
|
energy.update_max_energy(Some(*body), energy_level);
|
||||||
let mut stat = stats.get_mut_unchecked();
|
let mut skill_set = skill_set.get_mut_unchecked();
|
||||||
stat.skill_set.modify_energy = false;
|
skill_set.modify_energy = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use crate::persistence::character_loader::CharacterLoader;
|
use crate::persistence::character_loader::CharacterLoader;
|
||||||
use common::comp::{inventory::loadout_builder::LoadoutBuilder, Body, Inventory, Item, Stats};
|
use common::comp::{
|
||||||
|
inventory::loadout_builder::LoadoutBuilder, Body, Inventory, Item, SkillSet, Stats,
|
||||||
|
};
|
||||||
use specs::{Entity, ReadExpect};
|
use specs::{Entity, ReadExpect};
|
||||||
|
|
||||||
const VALID_STARTER_ITEMS: [&str; 6] = [
|
const VALID_STARTER_ITEMS: [&str; 6] = [
|
||||||
@ -32,6 +34,7 @@ pub fn create_character(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let stats = Stats::new(character_alias.to_string());
|
let stats = Stats::new(character_alias.to_string());
|
||||||
|
let skill_set = SkillSet::default();
|
||||||
|
|
||||||
let loadout = LoadoutBuilder::new()
|
let loadout = LoadoutBuilder::new()
|
||||||
.defaults()
|
.defaults()
|
||||||
@ -56,6 +59,6 @@ pub fn create_character(
|
|||||||
entity,
|
entity,
|
||||||
player_uuid,
|
player_uuid,
|
||||||
character_alias,
|
character_alias,
|
||||||
(body, stats, inventory, waypoint),
|
(body, stats, skill_set, inventory, waypoint),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -849,9 +849,7 @@ fn handle_spawn(
|
|||||||
);
|
);
|
||||||
|
|
||||||
let body = body();
|
let body = body();
|
||||||
|
|
||||||
let loadout = LoadoutBuilder::build_loadout(body, None, None, None).build();
|
let loadout = LoadoutBuilder::build_loadout(body, None, None, None).build();
|
||||||
|
|
||||||
let inventory = Inventory::new_with_loadout(loadout);
|
let inventory = Inventory::new_with_loadout(loadout);
|
||||||
|
|
||||||
let mut entity_base = server
|
let mut entity_base = server
|
||||||
@ -859,6 +857,7 @@ fn handle_spawn(
|
|||||||
.create_npc(
|
.create_npc(
|
||||||
pos,
|
pos,
|
||||||
comp::Stats::new(get_npc_name(id, npc::BodyType::from_body(body))),
|
comp::Stats::new(get_npc_name(id, npc::BodyType::from_body(body))),
|
||||||
|
comp::SkillSet::default(),
|
||||||
comp::Health::new(body, 1),
|
comp::Health::new(body, 1),
|
||||||
comp::Poise::new(body),
|
comp::Poise::new(body),
|
||||||
inventory,
|
inventory,
|
||||||
@ -951,13 +950,21 @@ fn handle_spawn_training_dummy(
|
|||||||
let body = comp::Body::Object(comp::object::Body::TrainingDummy);
|
let body = comp::Body::Object(comp::object::Body::TrainingDummy);
|
||||||
|
|
||||||
let stats = comp::Stats::new("Training Dummy".to_string());
|
let stats = comp::Stats::new("Training Dummy".to_string());
|
||||||
|
let skill_set = comp::SkillSet::default();
|
||||||
let health = comp::Health::new(body, 0);
|
let health = comp::Health::new(body, 0);
|
||||||
let poise = comp::Poise::new(body);
|
let poise = comp::Poise::new(body);
|
||||||
|
|
||||||
server
|
server
|
||||||
.state
|
.state
|
||||||
.create_npc(pos, stats, health, poise, Inventory::new_empty(), body)
|
.create_npc(
|
||||||
|
pos,
|
||||||
|
stats,
|
||||||
|
skill_set,
|
||||||
|
health,
|
||||||
|
poise,
|
||||||
|
Inventory::new_empty(),
|
||||||
|
body,
|
||||||
|
)
|
||||||
.with(comp::Vel(vel))
|
.with(comp::Vel(vel))
|
||||||
.with(comp::MountState::Unmounted)
|
.with(comp::MountState::Unmounted)
|
||||||
.build();
|
.build();
|
||||||
@ -2174,13 +2181,13 @@ fn handle_skill_point(
|
|||||||
.map(|alias| find_alias(server.state.ecs(), &alias).map(|(target, _)| target))
|
.map(|alias| find_alias(server.state.ecs(), &alias).map(|(target, _)| target))
|
||||||
.unwrap_or(Ok(target))?;
|
.unwrap_or(Ok(target))?;
|
||||||
|
|
||||||
if let Some(mut stats) = server
|
if let Some(mut skill_set) = server
|
||||||
.state
|
.state
|
||||||
.ecs_mut()
|
.ecs_mut()
|
||||||
.write_storage::<comp::Stats>()
|
.write_storage::<comp::SkillSet>()
|
||||||
.get_mut(player)
|
.get_mut(player)
|
||||||
{
|
{
|
||||||
stats.skill_set.add_skill_points(skill_tree, sp);
|
skill_set.add_skill_points(skill_tree, sp);
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err("Player has no stats!".into())
|
Err("Player has no stats!".into())
|
||||||
|
@ -8,7 +8,8 @@ use common::{
|
|||||||
buff::{BuffCategory, BuffData, BuffKind, BuffSource},
|
buff::{BuffCategory, BuffData, BuffKind, BuffSource},
|
||||||
inventory::loadout::Loadout,
|
inventory::loadout::Loadout,
|
||||||
shockwave, Agent, Alignment, Body, Gravity, Health, HomeChunk, Inventory, Item, ItemDrop,
|
shockwave, Agent, Alignment, Body, Gravity, Health, HomeChunk, Inventory, Item, ItemDrop,
|
||||||
LightEmitter, Object, Ori, Poise, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
|
LightEmitter, Object, Ori, Poise, Pos, Projectile, Scale, SkillSet, Stats, Vel,
|
||||||
|
WaypointArea,
|
||||||
},
|
},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
rtsim::RtSimEntity,
|
rtsim::RtSimEntity,
|
||||||
@ -34,6 +35,7 @@ pub fn handle_loaded_character_data(
|
|||||||
loaded_components: (
|
loaded_components: (
|
||||||
comp::Body,
|
comp::Body,
|
||||||
comp::Stats,
|
comp::Stats,
|
||||||
|
comp::SkillSet,
|
||||||
comp::Inventory,
|
comp::Inventory,
|
||||||
Option<comp::Waypoint>,
|
Option<comp::Waypoint>,
|
||||||
),
|
),
|
||||||
@ -49,6 +51,7 @@ pub fn handle_create_npc(
|
|||||||
server: &mut Server,
|
server: &mut Server,
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
stats: Stats,
|
stats: Stats,
|
||||||
|
skill_set: SkillSet,
|
||||||
health: Health,
|
health: Health,
|
||||||
poise: Poise,
|
poise: Poise,
|
||||||
loadout: Loadout,
|
loadout: Loadout,
|
||||||
@ -64,7 +67,7 @@ pub fn handle_create_npc(
|
|||||||
|
|
||||||
let entity = server
|
let entity = server
|
||||||
.state
|
.state
|
||||||
.create_npc(pos, stats, health, poise, inventory, body)
|
.create_npc(pos, stats, skill_set, health, poise, inventory, body)
|
||||||
.with(scale)
|
.with(scale)
|
||||||
.with(alignment);
|
.with(alignment);
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ use common::{
|
|||||||
chat::{KillSource, KillType},
|
chat::{KillSource, KillType},
|
||||||
inventory::item::MaterialStatManifest,
|
inventory::item::MaterialStatManifest,
|
||||||
object, Alignment, Body, CharacterState, Energy, EnergyChange, Group, Health, HealthChange,
|
object, Alignment, Body, CharacterState, Energy, EnergyChange, Group, Health, HealthChange,
|
||||||
HealthSource, Inventory, Player, Poise, PoiseChange, PoiseSource, Pos, Stats,
|
HealthSource, Inventory, Player, Poise, PoiseChange, PoiseSource, Pos, SkillSet, Stats,
|
||||||
},
|
},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
lottery::{LootSpec, Lottery},
|
lottery::{LootSpec, Lottery},
|
||||||
@ -178,7 +178,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
|||||||
|
|
||||||
// Give EXP to the killer if entity had stats
|
// Give EXP to the killer if entity had stats
|
||||||
(|| {
|
(|| {
|
||||||
let mut stats = state.ecs().write_storage::<Stats>();
|
let mut skill_set = state.ecs().write_storage::<SkillSet>();
|
||||||
let healths = state.ecs().read_storage::<Health>();
|
let healths = state.ecs().read_storage::<Health>();
|
||||||
let inventories = state.ecs().read_storage::<Inventory>();
|
let inventories = state.ecs().read_storage::<Inventory>();
|
||||||
let players = state.ecs().read_storage::<Player>();
|
let players = state.ecs().read_storage::<Player>();
|
||||||
@ -193,18 +193,23 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
|||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let (entity_stats, entity_health, entity_inventory, entity_body) = if let (
|
let (entity_skill_set, entity_health, entity_inventory, entity_body) = if let (
|
||||||
Some(entity_stats),
|
Some(entity_skill_set),
|
||||||
Some(entity_health),
|
Some(entity_health),
|
||||||
Some(entity_inventory),
|
Some(entity_inventory),
|
||||||
Some(entity_body),
|
Some(entity_body),
|
||||||
) = (
|
) = (
|
||||||
stats.get(entity),
|
skill_set.get(entity),
|
||||||
healths.get(entity),
|
healths.get(entity),
|
||||||
inventories.get(entity),
|
inventories.get(entity),
|
||||||
bodies.get(entity),
|
bodies.get(entity),
|
||||||
) {
|
) {
|
||||||
(entity_stats, entity_health, entity_inventory, entity_body)
|
(
|
||||||
|
entity_skill_set,
|
||||||
|
entity_health,
|
||||||
|
entity_inventory,
|
||||||
|
entity_body,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@ -228,7 +233,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
|||||||
let mut exp_reward = combat::combat_rating(
|
let mut exp_reward = combat::combat_rating(
|
||||||
entity_inventory,
|
entity_inventory,
|
||||||
entity_health,
|
entity_health,
|
||||||
entity_stats,
|
entity_skill_set,
|
||||||
*entity_body,
|
*entity_body,
|
||||||
&msm,
|
&msm,
|
||||||
) * 2.5;
|
) * 2.5;
|
||||||
@ -268,24 +273,24 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
|||||||
// Divides 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();
|
exp_reward /= (non_pet_group_members_in_range as f32).sqrt();
|
||||||
members_in_range.into_iter().for_each(|(e, uid)| {
|
members_in_range.into_iter().for_each(|(e, uid)| {
|
||||||
if let (Some(inventory), Some(mut stats)) = (inventories.get(e), stats.get_mut(e)) {
|
if let (Some(inventory), Some(mut skill_set)) =
|
||||||
handle_exp_gain(exp_reward, inventory, &mut stats, uid, &mut outcomes);
|
(inventories.get(e), skill_set.get_mut(e))
|
||||||
|
{
|
||||||
|
handle_exp_gain(exp_reward, inventory, &mut skill_set, uid, &mut outcomes);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if let (Some(mut attacker_stats), Some(attacker_uid), Some(attacker_inventory)) = (
|
if let (Some(mut attacker_skill_set), Some(attacker_uid), Some(attacker_inventory)) = (
|
||||||
stats.get_mut(attacker),
|
skill_set.get_mut(attacker),
|
||||||
uids.get(attacker),
|
uids.get(attacker),
|
||||||
inventories.get(attacker),
|
inventories.get(attacker),
|
||||||
) {
|
) {
|
||||||
// TODO: Discuss whether we should give EXP by Player
|
// TODO: Discuss whether we should give EXP by Player Killing or not.
|
||||||
// Killing or not.
|
|
||||||
// attacker_stats.exp.change_by(exp_reward.ceil() as i64);
|
|
||||||
handle_exp_gain(
|
handle_exp_gain(
|
||||||
exp_reward,
|
exp_reward,
|
||||||
attacker_inventory,
|
attacker_inventory,
|
||||||
&mut attacker_stats,
|
&mut attacker_skill_set,
|
||||||
attacker_uid,
|
attacker_uid,
|
||||||
&mut outcomes,
|
&mut outcomes,
|
||||||
);
|
);
|
||||||
@ -856,7 +861,7 @@ pub fn handle_energy_change(server: &Server, entity: EcsEntity, change: EnergyCh
|
|||||||
fn handle_exp_gain(
|
fn handle_exp_gain(
|
||||||
exp_reward: f32,
|
exp_reward: f32,
|
||||||
inventory: &Inventory,
|
inventory: &Inventory,
|
||||||
stats: &mut Stats,
|
skill_set: &mut SkillSet,
|
||||||
uid: &Uid,
|
uid: &Uid,
|
||||||
outcomes: &mut Vec<Outcome>,
|
outcomes: &mut Vec<Outcome>,
|
||||||
) {
|
) {
|
||||||
@ -864,26 +869,18 @@ fn handle_exp_gain(
|
|||||||
let mut xp_pools = HashSet::<SkillGroupKind>::new();
|
let mut xp_pools = HashSet::<SkillGroupKind>::new();
|
||||||
xp_pools.insert(SkillGroupKind::General);
|
xp_pools.insert(SkillGroupKind::General);
|
||||||
if let Some(w) = main_tool_kind {
|
if let Some(w) = main_tool_kind {
|
||||||
if stats
|
if skill_set.contains_skill_group(SkillGroupKind::Weapon(w)) {
|
||||||
.skill_set
|
|
||||||
.contains_skill_group(SkillGroupKind::Weapon(w))
|
|
||||||
{
|
|
||||||
xp_pools.insert(SkillGroupKind::Weapon(w));
|
xp_pools.insert(SkillGroupKind::Weapon(w));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(w) = second_tool_kind {
|
if let Some(w) = second_tool_kind {
|
||||||
if stats
|
if skill_set.contains_skill_group(SkillGroupKind::Weapon(w)) {
|
||||||
.skill_set
|
|
||||||
.contains_skill_group(SkillGroupKind::Weapon(w))
|
|
||||||
{
|
|
||||||
xp_pools.insert(SkillGroupKind::Weapon(w));
|
xp_pools.insert(SkillGroupKind::Weapon(w));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let num_pools = xp_pools.len() as f32;
|
let num_pools = xp_pools.len() as f32;
|
||||||
for pool in xp_pools {
|
for pool in xp_pools {
|
||||||
stats
|
skill_set.change_experience(pool, (exp_reward / num_pools).ceil() as i32);
|
||||||
.skill_set
|
|
||||||
.change_experience(pool, (exp_reward / num_pools).ceil() as i32);
|
|
||||||
}
|
}
|
||||||
outcomes.push(Outcome::ExpChange {
|
outcomes.push(Outcome::ExpChange {
|
||||||
uid: *uid,
|
uid: *uid,
|
||||||
|
@ -140,6 +140,7 @@ impl Server {
|
|||||||
ServerEvent::CreateNpc {
|
ServerEvent::CreateNpc {
|
||||||
pos,
|
pos,
|
||||||
stats,
|
stats,
|
||||||
|
skill_set,
|
||||||
health,
|
health,
|
||||||
poise,
|
poise,
|
||||||
loadout,
|
loadout,
|
||||||
@ -154,6 +155,7 @@ impl Server {
|
|||||||
self,
|
self,
|
||||||
pos,
|
pos,
|
||||||
stats,
|
stats,
|
||||||
|
skill_set,
|
||||||
health,
|
health,
|
||||||
poise,
|
poise,
|
||||||
loadout,
|
loadout,
|
||||||
|
@ -175,9 +175,9 @@ pub fn handle_client_disconnect(
|
|||||||
// the race condition of their login fetching their old data
|
// the race condition of their login fetching their old data
|
||||||
// and overwriting the data saved here.
|
// and overwriting the data saved here.
|
||||||
fn persist_entity(state: &mut State, entity: EcsEntity) -> EcsEntity {
|
fn persist_entity(state: &mut State, entity: EcsEntity) -> EcsEntity {
|
||||||
if let (Some(presence), Some(stats), Some(inventory), mut character_updater) = (
|
if let (Some(presence), Some(skill_set), Some(inventory), mut character_updater) = (
|
||||||
state.read_storage::<Presence>().get(entity),
|
state.read_storage::<Presence>().get(entity),
|
||||||
state.read_storage::<comp::Stats>().get(entity),
|
state.read_storage::<comp::SkillSet>().get(entity),
|
||||||
state.read_storage::<comp::Inventory>().get(entity),
|
state.read_storage::<comp::Inventory>().get(entity),
|
||||||
state.ecs().fetch_mut::<CharacterUpdater>(),
|
state.ecs().fetch_mut::<CharacterUpdater>(),
|
||||||
) {
|
) {
|
||||||
@ -191,7 +191,7 @@ fn persist_entity(state: &mut State, entity: EcsEntity) -> EcsEntity {
|
|||||||
|
|
||||||
character_updater.add_pending_logout_update(
|
character_updater.add_pending_logout_update(
|
||||||
char_id,
|
char_id,
|
||||||
(stats.clone(), inventory.clone(), waypoint),
|
(skill_set.clone(), inventory.clone(), waypoint),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
PresenceKind::Spectator => { /* Do nothing, spectators do not need persisting */ },
|
PresenceKind::Spectator => { /* Do nothing, spectators do not need persisting */ },
|
||||||
|
@ -15,9 +15,9 @@ use crate::{
|
|||||||
convert_body_from_database, convert_body_to_database_json,
|
convert_body_from_database, convert_body_to_database_json,
|
||||||
convert_character_from_database, convert_inventory_from_database_items,
|
convert_character_from_database, convert_inventory_from_database_items,
|
||||||
convert_items_to_database_items, convert_loadout_from_database_items,
|
convert_items_to_database_items, convert_loadout_from_database_items,
|
||||||
convert_skill_groups_to_database, convert_skills_to_database,
|
convert_skill_groups_to_database, convert_skill_set_from_database,
|
||||||
convert_stats_from_database, convert_waypoint_from_database_json,
|
convert_skills_to_database, convert_stats_from_database,
|
||||||
convert_waypoint_to_database_json,
|
convert_waypoint_from_database_json, convert_waypoint_to_database_json,
|
||||||
},
|
},
|
||||||
character_loader::{CharacterCreationResult, CharacterDataResult, CharacterListResult},
|
character_loader::{CharacterCreationResult, CharacterDataResult, CharacterListResult},
|
||||||
error::PersistenceError::DatabaseError,
|
error::PersistenceError::DatabaseError,
|
||||||
@ -198,7 +198,8 @@ pub fn load_character_data(
|
|||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
convert_body_from_database(&body_data)?,
|
convert_body_from_database(&body_data)?,
|
||||||
convert_stats_from_database(character_data.alias, &skill_data, &skill_group_data),
|
convert_stats_from_database(character_data.alias),
|
||||||
|
convert_skill_set_from_database(&skill_data, &skill_group_data),
|
||||||
convert_inventory_from_database_items(
|
convert_inventory_from_database_items(
|
||||||
character_containers.inventory_container_id,
|
character_containers.inventory_container_id,
|
||||||
&inventory_items,
|
&inventory_items,
|
||||||
@ -301,7 +302,7 @@ pub fn create_character(
|
|||||||
) -> CharacterCreationResult {
|
) -> CharacterCreationResult {
|
||||||
check_character_limit(uuid, connection)?;
|
check_character_limit(uuid, connection)?;
|
||||||
|
|
||||||
let (body, stats, inventory, waypoint) = persisted_components;
|
let (body, _stats, skill_set, inventory, waypoint) = persisted_components;
|
||||||
|
|
||||||
// Fetch new entity IDs for character, inventory and loadout
|
// Fetch new entity IDs for character, inventory and loadout
|
||||||
let mut new_entity_ids = get_new_entity_ids(connection, |next_id| next_id + 3)?;
|
let mut new_entity_ids = get_new_entity_ids(connection, |next_id| next_id + 3)?;
|
||||||
@ -387,8 +388,6 @@ pub fn create_character(
|
|||||||
])?;
|
])?;
|
||||||
drop(stmt);
|
drop(stmt);
|
||||||
|
|
||||||
let skill_set = stats.skill_set;
|
|
||||||
|
|
||||||
let db_skill_groups = convert_skill_groups_to_database(character_id, skill_set.skill_groups);
|
let db_skill_groups = convert_skill_groups_to_database(character_id, skill_set.skill_groups);
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
@ -682,7 +681,7 @@ fn get_pseudo_container_id(
|
|||||||
|
|
||||||
pub fn update(
|
pub fn update(
|
||||||
char_id: CharacterId,
|
char_id: CharacterId,
|
||||||
char_stats: comp::Stats,
|
char_skill_set: comp::SkillSet,
|
||||||
inventory: comp::Inventory,
|
inventory: comp::Inventory,
|
||||||
char_waypoint: Option<comp::Waypoint>,
|
char_waypoint: Option<comp::Waypoint>,
|
||||||
connection: &mut Transaction,
|
connection: &mut Transaction,
|
||||||
@ -781,8 +780,6 @@ pub fn update(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let char_skill_set = char_stats.skill_set;
|
|
||||||
|
|
||||||
let db_skill_groups = convert_skill_groups_to_database(char_id, char_skill_set.skill_groups);
|
let db_skill_groups = convert_skill_groups_to_database(char_id, char_skill_set.skill_groups);
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
@ -428,26 +428,22 @@ pub fn convert_character_from_database(character: &Character) -> common::charact
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert_stats_from_database(
|
pub fn convert_stats_from_database(alias: String) -> common::comp::Stats {
|
||||||
alias: String,
|
|
||||||
skills: &[Skill],
|
|
||||||
skill_groups: &[SkillGroup],
|
|
||||||
) -> common::comp::Stats {
|
|
||||||
let mut new_stats = common::comp::Stats::empty();
|
let mut new_stats = common::comp::Stats::empty();
|
||||||
new_stats.name = alias;
|
new_stats.name = alias;
|
||||||
/*new_stats.update_max_hp(new_stats.body_type);
|
new_stats
|
||||||
new_stats.health.set_to(
|
}
|
||||||
new_stats.health.maximum(),
|
|
||||||
common::comp::HealthSource::Revive,
|
pub fn convert_skill_set_from_database(
|
||||||
);*/
|
skills: &[Skill],
|
||||||
new_stats.skill_set = skills::SkillSet {
|
skill_groups: &[SkillGroup],
|
||||||
|
) -> common::comp::SkillSet {
|
||||||
|
skills::SkillSet {
|
||||||
skill_groups: convert_skill_groups_from_database(skill_groups),
|
skill_groups: convert_skill_groups_from_database(skill_groups),
|
||||||
skills: convert_skills_from_database(skills),
|
skills: convert_skills_from_database(skills),
|
||||||
modify_health: true,
|
modify_health: true,
|
||||||
modify_energy: true,
|
modify_energy: true,
|
||||||
};
|
}
|
||||||
|
|
||||||
new_stats
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_item_from_asset(item_definition_id: &str) -> Result<common::comp::Item, PersistenceError> {
|
fn get_item_from_asset(item_definition_id: &str) -> Result<common::comp::Item, PersistenceError> {
|
||||||
|
@ -14,7 +14,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
use tracing::{debug, error, info, trace, warn};
|
use tracing::{debug, error, info, trace, warn};
|
||||||
|
|
||||||
pub type CharacterUpdateData = (comp::Stats, comp::Inventory, Option<comp::Waypoint>);
|
pub type CharacterUpdateData = (comp::SkillSet, comp::Inventory, Option<comp::Waypoint>);
|
||||||
|
|
||||||
pub enum CharacterUpdaterEvent {
|
pub enum CharacterUpdaterEvent {
|
||||||
BatchUpdate(Vec<(CharacterId, CharacterUpdateData)>),
|
BatchUpdate(Vec<(CharacterId, CharacterUpdateData)>),
|
||||||
@ -131,17 +131,17 @@ impl CharacterUpdater {
|
|||||||
updates: impl Iterator<
|
updates: impl Iterator<
|
||||||
Item = (
|
Item = (
|
||||||
CharacterId,
|
CharacterId,
|
||||||
&'a comp::Stats,
|
&'a comp::SkillSet,
|
||||||
&'a comp::Inventory,
|
&'a comp::Inventory,
|
||||||
Option<&'a comp::Waypoint>,
|
Option<&'a comp::Waypoint>,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
) {
|
) {
|
||||||
let updates = updates
|
let updates = updates
|
||||||
.map(|(character_id, stats, inventory, waypoint)| {
|
.map(|(character_id, skill_set, inventory, waypoint)| {
|
||||||
(
|
(
|
||||||
character_id,
|
character_id,
|
||||||
(stats.clone(), inventory.clone(), waypoint.cloned()),
|
(skill_set.clone(), inventory.clone(), waypoint.cloned()),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.chain(self.pending_logout_updates.drain())
|
.chain(self.pending_logout_updates.drain())
|
||||||
@ -161,11 +161,16 @@ impl CharacterUpdater {
|
|||||||
pub fn update(
|
pub fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
character_id: CharacterId,
|
character_id: CharacterId,
|
||||||
stats: &comp::Stats,
|
skill_set: &comp::SkillSet,
|
||||||
inventory: &comp::Inventory,
|
inventory: &comp::Inventory,
|
||||||
waypoint: Option<&comp::Waypoint>,
|
waypoint: Option<&comp::Waypoint>,
|
||||||
) {
|
) {
|
||||||
self.batch_update(std::iter::once((character_id, stats, inventory, waypoint)));
|
self.batch_update(std::iter::once((
|
||||||
|
character_id,
|
||||||
|
skill_set,
|
||||||
|
inventory,
|
||||||
|
waypoint,
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates to the batch update thread that a requested disconnection of
|
/// Indicates to the batch update thread that a requested disconnection of
|
||||||
|
@ -22,6 +22,7 @@ use tracing::info;
|
|||||||
pub type PersistedComponents = (
|
pub type PersistedComponents = (
|
||||||
comp::Body,
|
comp::Body,
|
||||||
comp::Stats,
|
comp::Stats,
|
||||||
|
comp::SkillSet,
|
||||||
comp::Inventory,
|
comp::Inventory,
|
||||||
Option<comp::Waypoint>,
|
Option<comp::Waypoint>,
|
||||||
);
|
);
|
||||||
|
@ -126,6 +126,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
_ => ServerEvent::CreateNpc {
|
_ => ServerEvent::CreateNpc {
|
||||||
pos: comp::Pos(spawn_pos),
|
pos: comp::Pos(spawn_pos),
|
||||||
stats: comp::Stats::new(entity.get_name()),
|
stats: comp::Stats::new(entity.get_name()),
|
||||||
|
skill_set: comp::SkillSet::default(),
|
||||||
health: comp::Health::new(body, 10),
|
health: comp::Health::new(body, 10),
|
||||||
loadout: match body {
|
loadout: match body {
|
||||||
comp::Body::Humanoid(_) => entity.get_loadout(),
|
comp::Body::Humanoid(_) => entity.get_loadout(),
|
||||||
|
@ -31,10 +31,12 @@ pub trait StateExt {
|
|||||||
/// Updates a component associated with the entity based on the `Effect`
|
/// Updates a component associated with the entity based on the `Effect`
|
||||||
fn apply_effect(&self, entity: EcsEntity, effect: Effect, source: Option<Uid>);
|
fn apply_effect(&self, entity: EcsEntity, effect: Effect, source: Option<Uid>);
|
||||||
/// Build a non-player character
|
/// Build a non-player character
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn create_npc(
|
fn create_npc(
|
||||||
&mut self,
|
&mut self,
|
||||||
pos: comp::Pos,
|
pos: comp::Pos,
|
||||||
stats: comp::Stats,
|
stats: comp::Stats,
|
||||||
|
skill_set: comp::SkillSet,
|
||||||
health: comp::Health,
|
health: comp::Health,
|
||||||
poise: comp::Poise,
|
poise: comp::Poise,
|
||||||
inventory: comp::Inventory,
|
inventory: comp::Inventory,
|
||||||
@ -161,6 +163,7 @@ impl StateExt for State {
|
|||||||
&mut self,
|
&mut self,
|
||||||
pos: comp::Pos,
|
pos: comp::Pos,
|
||||||
stats: comp::Stats,
|
stats: comp::Stats,
|
||||||
|
skill_set: comp::SkillSet,
|
||||||
health: comp::Health,
|
health: comp::Health,
|
||||||
poise: comp::Poise,
|
poise: comp::Poise,
|
||||||
inventory: comp::Inventory,
|
inventory: comp::Inventory,
|
||||||
@ -192,13 +195,13 @@ impl StateExt for State {
|
|||||||
.with(body)
|
.with(body)
|
||||||
.with(comp::Energy::new(
|
.with(comp::Energy::new(
|
||||||
body,
|
body,
|
||||||
stats
|
skill_set
|
||||||
.skill_set
|
|
||||||
.skill_level(Skill::General(GeneralSkill::EnergyIncrease))
|
.skill_level(Skill::General(GeneralSkill::EnergyIncrease))
|
||||||
.unwrap_or(None)
|
.unwrap_or(None)
|
||||||
.unwrap_or(0),
|
.unwrap_or(0),
|
||||||
))
|
))
|
||||||
.with(stats)
|
.with(stats)
|
||||||
|
.with(skill_set)
|
||||||
.with(health)
|
.with(health)
|
||||||
.with(poise)
|
.with(poise)
|
||||||
.with(comp::Alignment::Npc)
|
.with(comp::Alignment::Npc)
|
||||||
@ -252,6 +255,7 @@ impl StateExt for State {
|
|||||||
// recognize a possesed airship; that system should be refactored to use `.maybe()`
|
// recognize a possesed airship; that system should be refactored to use `.maybe()`
|
||||||
.with(comp::Energy::new(ship.into(), 0))
|
.with(comp::Energy::new(ship.into(), 0))
|
||||||
.with(comp::Stats::new("Airship".to_string()))
|
.with(comp::Stats::new("Airship".to_string()))
|
||||||
|
.with(comp::SkillSet::default())
|
||||||
.with(comp::Combo::default());
|
.with(comp::Combo::default());
|
||||||
|
|
||||||
if mountable {
|
if mountable {
|
||||||
@ -399,7 +403,7 @@ impl StateExt for State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn update_character_data(&mut self, entity: EcsEntity, components: PersistedComponents) {
|
fn update_character_data(&mut self, entity: EcsEntity, components: PersistedComponents) {
|
||||||
let (body, stats, inventory, waypoint) = components;
|
let (body, stats, skill_set, inventory, waypoint) = components;
|
||||||
|
|
||||||
if let Some(player_uid) = self.read_component_copied::<Uid>(entity) {
|
if let Some(player_uid) = self.read_component_copied::<Uid>(entity) {
|
||||||
// Notify clients of a player list update
|
// Notify clients of a player list update
|
||||||
@ -420,13 +424,11 @@ impl StateExt for State {
|
|||||||
});
|
});
|
||||||
self.write_component_ignore_entity_dead(entity, body);
|
self.write_component_ignore_entity_dead(entity, body);
|
||||||
let (health_level, energy_level) = (
|
let (health_level, energy_level) = (
|
||||||
stats
|
skill_set
|
||||||
.skill_set
|
|
||||||
.skill_level(Skill::General(GeneralSkill::HealthIncrease))
|
.skill_level(Skill::General(GeneralSkill::HealthIncrease))
|
||||||
.unwrap_or(None)
|
.unwrap_or(None)
|
||||||
.unwrap_or(0),
|
.unwrap_or(0),
|
||||||
stats
|
skill_set
|
||||||
.skill_set
|
|
||||||
.skill_level(Skill::General(GeneralSkill::EnergyIncrease))
|
.skill_level(Skill::General(GeneralSkill::EnergyIncrease))
|
||||||
.unwrap_or(None)
|
.unwrap_or(None)
|
||||||
.unwrap_or(0),
|
.unwrap_or(0),
|
||||||
@ -435,6 +437,7 @@ impl StateExt for State {
|
|||||||
self.write_component_ignore_entity_dead(entity, comp::Energy::new(body, energy_level));
|
self.write_component_ignore_entity_dead(entity, comp::Energy::new(body, energy_level));
|
||||||
self.write_component_ignore_entity_dead(entity, comp::Poise::new(body));
|
self.write_component_ignore_entity_dead(entity, comp::Poise::new(body));
|
||||||
self.write_component_ignore_entity_dead(entity, stats);
|
self.write_component_ignore_entity_dead(entity, stats);
|
||||||
|
self.write_component_ignore_entity_dead(entity, skill_set);
|
||||||
self.write_component_ignore_entity_dead(entity, inventory);
|
self.write_component_ignore_entity_dead(entity, inventory);
|
||||||
self.write_component_ignore_entity_dead(
|
self.write_component_ignore_entity_dead(
|
||||||
entity,
|
entity,
|
||||||
|
@ -16,7 +16,7 @@ use common::{
|
|||||||
skills::{AxeSkill, BowSkill, HammerSkill, Skill, StaffSkill, SwordSkill},
|
skills::{AxeSkill, BowSkill, HammerSkill, Skill, StaffSkill, SwordSkill},
|
||||||
Agent, Alignment, BehaviorCapability, BehaviorState, Body, CharacterState, ControlAction,
|
Agent, Alignment, BehaviorCapability, BehaviorState, Body, CharacterState, ControlAction,
|
||||||
ControlEvent, Controller, Energy, Health, HealthChange, InputKind, Inventory,
|
ControlEvent, Controller, Energy, Health, HealthChange, InputKind, Inventory,
|
||||||
InventoryAction, LightEmitter, MountState, Ori, PhysicsState, Pos, Scale, Stats,
|
InventoryAction, LightEmitter, MountState, Ori, PhysicsState, Pos, Scale, SkillSet, Stats,
|
||||||
UnresolvedChatMsg, Vel,
|
UnresolvedChatMsg, Vel,
|
||||||
},
|
},
|
||||||
effect::{BuffEffect, Effect},
|
effect::{BuffEffect, Effect},
|
||||||
@ -55,7 +55,7 @@ struct AgentData<'a> {
|
|||||||
energy: &'a Energy,
|
energy: &'a Energy,
|
||||||
body: Option<&'a Body>,
|
body: Option<&'a Body>,
|
||||||
inventory: &'a Inventory,
|
inventory: &'a Inventory,
|
||||||
stats: &'a Stats,
|
skill_set: &'a SkillSet,
|
||||||
physics_state: &'a PhysicsState,
|
physics_state: &'a PhysicsState,
|
||||||
alignment: Option<&'a Alignment>,
|
alignment: Option<&'a Alignment>,
|
||||||
traversal_config: TraversalConfig,
|
traversal_config: TraversalConfig,
|
||||||
@ -84,6 +84,7 @@ pub struct ReadData<'a> {
|
|||||||
healths: ReadStorage<'a, Health>,
|
healths: ReadStorage<'a, Health>,
|
||||||
inventories: ReadStorage<'a, Inventory>,
|
inventories: ReadStorage<'a, Inventory>,
|
||||||
stats: ReadStorage<'a, Stats>,
|
stats: ReadStorage<'a, Stats>,
|
||||||
|
skill_set: ReadStorage<'a, SkillSet>,
|
||||||
physics_states: ReadStorage<'a, PhysicsState>,
|
physics_states: ReadStorage<'a, PhysicsState>,
|
||||||
char_states: ReadStorage<'a, CharacterState>,
|
char_states: ReadStorage<'a, CharacterState>,
|
||||||
uids: ReadStorage<'a, Uid>,
|
uids: ReadStorage<'a, Uid>,
|
||||||
@ -147,7 +148,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
),
|
),
|
||||||
read_data.bodies.maybe(),
|
read_data.bodies.maybe(),
|
||||||
&read_data.inventories,
|
&read_data.inventories,
|
||||||
&read_data.stats,
|
&read_data.skill_set,
|
||||||
&read_data.physics_states,
|
&read_data.physics_states,
|
||||||
&read_data.uids,
|
&read_data.uids,
|
||||||
&mut agents,
|
&mut agents,
|
||||||
@ -176,7 +177,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
(pos, vel, ori),
|
(pos, vel, ori),
|
||||||
body,
|
body,
|
||||||
inventory,
|
inventory,
|
||||||
stats,
|
skill_set,
|
||||||
physics_state,
|
physics_state,
|
||||||
uid,
|
uid,
|
||||||
agent,
|
agent,
|
||||||
@ -269,7 +270,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
energy,
|
energy,
|
||||||
body,
|
body,
|
||||||
inventory,
|
inventory,
|
||||||
stats,
|
skill_set,
|
||||||
physics_state,
|
physics_state,
|
||||||
alignment: alignment.as_ref(),
|
alignment: alignment.as_ref(),
|
||||||
traversal_config,
|
traversal_config,
|
||||||
@ -1621,10 +1622,7 @@ impl<'a> AgentData<'a> {
|
|||||||
.actions
|
.actions
|
||||||
.push(ControlAction::basic_input(InputKind::Secondary));
|
.push(ControlAction::basic_input(InputKind::Secondary));
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else if self
|
} else if self.skill_set.has_skill(Skill::Axe(AxeSkill::UnlockLeap))
|
||||||
.stats
|
|
||||||
.skill_set
|
|
||||||
.has_skill(Skill::Axe(AxeSkill::UnlockLeap))
|
|
||||||
&& self.energy.current() > 800
|
&& self.energy.current() > 800
|
||||||
&& thread_rng().gen_bool(0.5)
|
&& thread_rng().gen_bool(0.5)
|
||||||
{
|
{
|
||||||
@ -1680,7 +1678,6 @@ impl<'a> AgentData<'a> {
|
|||||||
.push(ControlAction::basic_input(InputKind::Secondary));
|
.push(ControlAction::basic_input(InputKind::Secondary));
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else if self
|
} else if self
|
||||||
.stats
|
|
||||||
.skill_set
|
.skill_set
|
||||||
.has_skill(Skill::Hammer(HammerSkill::UnlockLeap))
|
.has_skill(Skill::Hammer(HammerSkill::UnlockLeap))
|
||||||
&& self.energy.current() > 700
|
&& self.energy.current() > 700
|
||||||
@ -1711,7 +1708,6 @@ impl<'a> AgentData<'a> {
|
|||||||
controller.inputs.move_dir =
|
controller.inputs.move_dir =
|
||||||
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed;
|
||||||
if self
|
if self
|
||||||
.stats
|
|
||||||
.skill_set
|
.skill_set
|
||||||
.has_skill(Skill::Hammer(HammerSkill::UnlockLeap))
|
.has_skill(Skill::Hammer(HammerSkill::UnlockLeap))
|
||||||
&& agent.action_timer > 5.0
|
&& agent.action_timer > 5.0
|
||||||
@ -1746,7 +1742,6 @@ impl<'a> AgentData<'a> {
|
|||||||
if dist_sqrd < min_attack_dist.powi(2) {
|
if dist_sqrd < min_attack_dist.powi(2) {
|
||||||
controller.inputs.move_dir = Vec2::zero();
|
controller.inputs.move_dir = Vec2::zero();
|
||||||
if self
|
if self
|
||||||
.stats
|
|
||||||
.skill_set
|
.skill_set
|
||||||
.has_skill(Skill::Sword(SwordSkill::UnlockSpin))
|
.has_skill(Skill::Sword(SwordSkill::UnlockSpin))
|
||||||
&& agent.action_timer < 2.0
|
&& agent.action_timer < 2.0
|
||||||
@ -1841,7 +1836,6 @@ impl<'a> AgentData<'a> {
|
|||||||
.push(ControlAction::basic_input(InputKind::Secondary));
|
.push(ControlAction::basic_input(InputKind::Secondary));
|
||||||
agent.action_timer += dt.0;
|
agent.action_timer += dt.0;
|
||||||
} else if self
|
} else if self
|
||||||
.stats
|
|
||||||
.skill_set
|
.skill_set
|
||||||
.has_skill(Skill::Bow(BowSkill::UnlockRepeater))
|
.has_skill(Skill::Bow(BowSkill::UnlockRepeater))
|
||||||
&& self.energy.current() > 400
|
&& self.energy.current() > 400
|
||||||
@ -1924,7 +1918,6 @@ impl<'a> AgentData<'a> {
|
|||||||
agent.action_timer = 0.0;
|
agent.action_timer = 0.0;
|
||||||
}
|
}
|
||||||
if self
|
if self
|
||||||
.stats
|
|
||||||
.skill_set
|
.skill_set
|
||||||
.has_skill(Skill::Staff(StaffSkill::UnlockShockwave))
|
.has_skill(Skill::Staff(StaffSkill::UnlockShockwave))
|
||||||
&& self.energy.current() > 800
|
&& self.energy.current() > 800
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{client::Client, presence::Presence, Settings};
|
use crate::{client::Client, presence::Presence, Settings};
|
||||||
use common::{
|
use common::{
|
||||||
comp::{CanBuild, ControlEvent, Controller, ForceUpdate, Health, Ori, Pos, Stats, Vel},
|
comp::{CanBuild, ControlEvent, Controller, ForceUpdate, Health, Ori, Pos, SkillSet, Vel},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
terrain::TerrainGrid,
|
terrain::TerrainGrid,
|
||||||
vol::ReadVol,
|
vol::ReadVol,
|
||||||
@ -21,7 +21,7 @@ impl Sys {
|
|||||||
terrain: &ReadExpect<'_, TerrainGrid>,
|
terrain: &ReadExpect<'_, TerrainGrid>,
|
||||||
can_build: &ReadStorage<'_, CanBuild>,
|
can_build: &ReadStorage<'_, CanBuild>,
|
||||||
force_updates: &ReadStorage<'_, ForceUpdate>,
|
force_updates: &ReadStorage<'_, ForceUpdate>,
|
||||||
stats: &mut WriteStorage<'_, Stats>,
|
skill_sets: &mut WriteStorage<'_, SkillSet>,
|
||||||
healths: &ReadStorage<'_, Health>,
|
healths: &ReadStorage<'_, Health>,
|
||||||
block_changes: &mut Write<'_, BlockChange>,
|
block_changes: &mut Write<'_, BlockChange>,
|
||||||
positions: &mut WriteStorage<'_, Pos>,
|
positions: &mut WriteStorage<'_, Pos>,
|
||||||
@ -139,19 +139,19 @@ impl Sys {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
ClientGeneral::UnlockSkill(skill) => {
|
ClientGeneral::UnlockSkill(skill) => {
|
||||||
stats
|
skill_sets
|
||||||
.get_mut(entity)
|
.get_mut(entity)
|
||||||
.map(|mut s| s.skill_set.unlock_skill(skill));
|
.map(|mut skill_set| skill_set.unlock_skill(skill));
|
||||||
},
|
},
|
||||||
ClientGeneral::RefundSkill(skill) => {
|
ClientGeneral::RefundSkill(skill) => {
|
||||||
stats
|
skill_sets
|
||||||
.get_mut(entity)
|
.get_mut(entity)
|
||||||
.map(|mut s| s.skill_set.refund_skill(skill));
|
.map(|mut skill_set| skill_set.refund_skill(skill));
|
||||||
},
|
},
|
||||||
ClientGeneral::UnlockSkillGroup(skill_group_kind) => {
|
ClientGeneral::UnlockSkillGroup(skill_group_kind) => {
|
||||||
stats
|
skill_sets
|
||||||
.get_mut(entity)
|
.get_mut(entity)
|
||||||
.map(|mut s| s.skill_set.unlock_skill_group(skill_group_kind));
|
.map(|mut skill_set| skill_set.unlock_skill_group(skill_group_kind));
|
||||||
},
|
},
|
||||||
ClientGeneral::RequestSiteInfo(id) => {
|
ClientGeneral::RequestSiteInfo(id) => {
|
||||||
server_emitter.emit(ServerEvent::RequestSiteInfo { entity, id });
|
server_emitter.emit(ServerEvent::RequestSiteInfo { entity, id });
|
||||||
@ -173,7 +173,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
ReadExpect<'a, TerrainGrid>,
|
ReadExpect<'a, TerrainGrid>,
|
||||||
ReadStorage<'a, CanBuild>,
|
ReadStorage<'a, CanBuild>,
|
||||||
ReadStorage<'a, ForceUpdate>,
|
ReadStorage<'a, ForceUpdate>,
|
||||||
WriteStorage<'a, Stats>,
|
WriteStorage<'a, SkillSet>,
|
||||||
ReadStorage<'a, Health>,
|
ReadStorage<'a, Health>,
|
||||||
Write<'a, BlockChange>,
|
Write<'a, BlockChange>,
|
||||||
WriteStorage<'a, Pos>,
|
WriteStorage<'a, Pos>,
|
||||||
@ -198,7 +198,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
terrain,
|
terrain,
|
||||||
can_build,
|
can_build,
|
||||||
force_updates,
|
force_updates,
|
||||||
mut stats,
|
mut skill_sets,
|
||||||
healths,
|
healths,
|
||||||
mut block_changes,
|
mut block_changes,
|
||||||
mut positions,
|
mut positions,
|
||||||
@ -225,7 +225,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
&terrain,
|
&terrain,
|
||||||
&can_build,
|
&can_build,
|
||||||
&force_updates,
|
&force_updates,
|
||||||
&mut stats,
|
&mut skill_sets,
|
||||||
&healths,
|
&healths,
|
||||||
&mut block_changes,
|
&mut block_changes,
|
||||||
&mut positions,
|
&mut positions,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{persistence::character_updater, presence::Presence, sys::SysScheduler};
|
use crate::{persistence::character_updater, presence::Presence, sys::SysScheduler};
|
||||||
use common::comp::{Inventory, Stats, Waypoint};
|
use common::comp::{Inventory, SkillSet, Waypoint};
|
||||||
use common_ecs::{Job, Origin, Phase, System};
|
use common_ecs::{Job, Origin, Phase, System};
|
||||||
use common_net::msg::PresenceKind;
|
use common_net::msg::PresenceKind;
|
||||||
use specs::{Join, ReadStorage, Write, WriteExpect};
|
use specs::{Join, ReadStorage, Write, WriteExpect};
|
||||||
@ -11,7 +11,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
type SystemData = (
|
type SystemData = (
|
||||||
ReadStorage<'a, Presence>,
|
ReadStorage<'a, Presence>,
|
||||||
ReadStorage<'a, Stats>,
|
ReadStorage<'a, SkillSet>,
|
||||||
ReadStorage<'a, Inventory>,
|
ReadStorage<'a, Inventory>,
|
||||||
ReadStorage<'a, Waypoint>,
|
ReadStorage<'a, Waypoint>,
|
||||||
WriteExpect<'a, character_updater::CharacterUpdater>,
|
WriteExpect<'a, character_updater::CharacterUpdater>,
|
||||||
@ -26,7 +26,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
_job: &mut Job<Self>,
|
_job: &mut Job<Self>,
|
||||||
(
|
(
|
||||||
presences,
|
presences,
|
||||||
player_stats,
|
player_skill_set,
|
||||||
player_inventories,
|
player_inventories,
|
||||||
player_waypoint,
|
player_waypoint,
|
||||||
mut updater,
|
mut updater,
|
||||||
@ -37,14 +37,16 @@ impl<'a> System<'a> for Sys {
|
|||||||
updater.batch_update(
|
updater.batch_update(
|
||||||
(
|
(
|
||||||
&presences,
|
&presences,
|
||||||
&player_stats,
|
&player_skill_set,
|
||||||
&player_inventories,
|
&player_inventories,
|
||||||
player_waypoint.maybe(),
|
player_waypoint.maybe(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
.filter_map(
|
.filter_map(
|
||||||
|(presence, stats, inventory, waypoint)| match presence.kind {
|
|(presence, skill_set, inventory, waypoint)| match presence.kind {
|
||||||
PresenceKind::Character(id) => Some((id, stats, inventory, waypoint)),
|
PresenceKind::Character(id) => {
|
||||||
|
Some((id, skill_set, inventory, waypoint))
|
||||||
|
},
|
||||||
PresenceKind::Spectator => None,
|
PresenceKind::Spectator => None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -2,7 +2,8 @@ use common::{
|
|||||||
comp::{
|
comp::{
|
||||||
item::MaterialStatManifest, Auras, BeamSegment, Body, Buffs, CanBuild, CharacterState,
|
item::MaterialStatManifest, Auras, BeamSegment, Body, Buffs, CanBuild, CharacterState,
|
||||||
Collider, Combo, Energy, Gravity, Group, Health, Inventory, Item, LightEmitter, Mass,
|
Collider, Combo, Energy, Gravity, Group, Health, Inventory, Item, LightEmitter, Mass,
|
||||||
MountState, Mounting, Ori, Player, Poise, Pos, Scale, Shockwave, Stats, Sticky, Vel,
|
MountState, Mounting, Ori, Player, Poise, Pos, Scale, Shockwave, SkillSet, Stats, Sticky,
|
||||||
|
Vel,
|
||||||
},
|
},
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
};
|
};
|
||||||
@ -42,6 +43,7 @@ pub struct TrackedComps<'a> {
|
|||||||
pub body: ReadStorage<'a, Body>,
|
pub body: ReadStorage<'a, Body>,
|
||||||
pub player: ReadStorage<'a, Player>,
|
pub player: ReadStorage<'a, Player>,
|
||||||
pub stats: ReadStorage<'a, Stats>,
|
pub stats: ReadStorage<'a, Stats>,
|
||||||
|
pub skill_set: ReadStorage<'a, SkillSet>,
|
||||||
pub buffs: ReadStorage<'a, Buffs>,
|
pub buffs: ReadStorage<'a, Buffs>,
|
||||||
pub auras: ReadStorage<'a, Auras>,
|
pub auras: ReadStorage<'a, Auras>,
|
||||||
pub energy: ReadStorage<'a, Energy>,
|
pub energy: ReadStorage<'a, Energy>,
|
||||||
@ -84,6 +86,10 @@ impl<'a> TrackedComps<'a> {
|
|||||||
.get(entity)
|
.get(entity)
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|c| comps.push(c.into()));
|
.map(|c| comps.push(c.into()));
|
||||||
|
self.skill_set
|
||||||
|
.get(entity)
|
||||||
|
.cloned()
|
||||||
|
.map(|c| comps.push(c.into()));
|
||||||
self.buffs
|
self.buffs
|
||||||
.get(entity)
|
.get(entity)
|
||||||
.cloned()
|
.cloned()
|
||||||
@ -179,6 +185,7 @@ pub struct ReadTrackers<'a> {
|
|||||||
pub body: ReadExpect<'a, UpdateTracker<Body>>,
|
pub body: ReadExpect<'a, UpdateTracker<Body>>,
|
||||||
pub player: ReadExpect<'a, UpdateTracker<Player>>,
|
pub player: ReadExpect<'a, UpdateTracker<Player>>,
|
||||||
pub stats: ReadExpect<'a, UpdateTracker<Stats>>,
|
pub stats: ReadExpect<'a, UpdateTracker<Stats>>,
|
||||||
|
pub skill_set: ReadExpect<'a, UpdateTracker<SkillSet>>,
|
||||||
pub buffs: ReadExpect<'a, UpdateTracker<Buffs>>,
|
pub buffs: ReadExpect<'a, UpdateTracker<Buffs>>,
|
||||||
pub auras: ReadExpect<'a, UpdateTracker<Auras>>,
|
pub auras: ReadExpect<'a, UpdateTracker<Auras>>,
|
||||||
pub energy: ReadExpect<'a, UpdateTracker<Energy>>,
|
pub energy: ReadExpect<'a, UpdateTracker<Energy>>,
|
||||||
@ -214,6 +221,7 @@ impl<'a> ReadTrackers<'a> {
|
|||||||
.with_component(&comps.uid, &*self.body, &comps.body, filter)
|
.with_component(&comps.uid, &*self.body, &comps.body, filter)
|
||||||
.with_component(&comps.uid, &*self.player, &comps.player, filter)
|
.with_component(&comps.uid, &*self.player, &comps.player, filter)
|
||||||
.with_component(&comps.uid, &*self.stats, &comps.stats, filter)
|
.with_component(&comps.uid, &*self.stats, &comps.stats, filter)
|
||||||
|
.with_component(&comps.uid, &*self.skill_set, &comps.skill_set, filter)
|
||||||
.with_component(&comps.uid, &*self.buffs, &comps.buffs, filter)
|
.with_component(&comps.uid, &*self.buffs, &comps.buffs, filter)
|
||||||
.with_component(&comps.uid, &*self.auras, &comps.auras, filter)
|
.with_component(&comps.uid, &*self.auras, &comps.auras, filter)
|
||||||
.with_component(&comps.uid, &*self.energy, &comps.energy, filter)
|
.with_component(&comps.uid, &*self.energy, &comps.energy, filter)
|
||||||
@ -256,6 +264,7 @@ pub struct WriteTrackers<'a> {
|
|||||||
body: WriteExpect<'a, UpdateTracker<Body>>,
|
body: WriteExpect<'a, UpdateTracker<Body>>,
|
||||||
player: WriteExpect<'a, UpdateTracker<Player>>,
|
player: WriteExpect<'a, UpdateTracker<Player>>,
|
||||||
stats: WriteExpect<'a, UpdateTracker<Stats>>,
|
stats: WriteExpect<'a, UpdateTracker<Stats>>,
|
||||||
|
skill_set: WriteExpect<'a, UpdateTracker<SkillSet>>,
|
||||||
buffs: WriteExpect<'a, UpdateTracker<Buffs>>,
|
buffs: WriteExpect<'a, UpdateTracker<Buffs>>,
|
||||||
auras: WriteExpect<'a, UpdateTracker<Auras>>,
|
auras: WriteExpect<'a, UpdateTracker<Auras>>,
|
||||||
energy: WriteExpect<'a, UpdateTracker<Energy>>,
|
energy: WriteExpect<'a, UpdateTracker<Energy>>,
|
||||||
@ -285,6 +294,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
|
|||||||
trackers.body.record_changes(&comps.body);
|
trackers.body.record_changes(&comps.body);
|
||||||
trackers.player.record_changes(&comps.player);
|
trackers.player.record_changes(&comps.player);
|
||||||
trackers.stats.record_changes(&comps.stats);
|
trackers.stats.record_changes(&comps.stats);
|
||||||
|
trackers.skill_set.record_changes(&comps.skill_set);
|
||||||
trackers.buffs.record_changes(&comps.buffs);
|
trackers.buffs.record_changes(&comps.buffs);
|
||||||
trackers.auras.record_changes(&comps.auras);
|
trackers.auras.record_changes(&comps.auras);
|
||||||
trackers.energy.record_changes(&comps.energy);
|
trackers.energy.record_changes(&comps.energy);
|
||||||
@ -329,6 +339,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
|
|||||||
log_counts!(auras, "Auras");
|
log_counts!(auras, "Auras");
|
||||||
log_counts!(player, "Players");
|
log_counts!(player, "Players");
|
||||||
log_counts!(stats, "Stats");
|
log_counts!(stats, "Stats");
|
||||||
|
log_counts!(skill_set, "SkillSet");
|
||||||
log_counts!(energy, "Energies");
|
log_counts!(energy, "Energies");
|
||||||
log_counts!(combo, "Combos");
|
log_counts!(combo, "Combos");
|
||||||
log_vounts!(health, "Healths");
|
log_vounts!(health, "Healths");
|
||||||
@ -354,6 +365,7 @@ pub fn register_trackers(world: &mut World) {
|
|||||||
world.register_tracker::<Body>();
|
world.register_tracker::<Body>();
|
||||||
world.register_tracker::<Player>();
|
world.register_tracker::<Player>();
|
||||||
world.register_tracker::<Stats>();
|
world.register_tracker::<Stats>();
|
||||||
|
world.register_tracker::<SkillSet>();
|
||||||
world.register_tracker::<Buffs>();
|
world.register_tracker::<Buffs>();
|
||||||
world.register_tracker::<Auras>();
|
world.register_tracker::<Auras>();
|
||||||
world.register_tracker::<Energy>();
|
world.register_tracker::<Energy>();
|
||||||
|
@ -154,7 +154,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
let economy = entity.trading_information.as_ref();
|
let economy = entity.trading_information.as_ref();
|
||||||
let skillset_config = entity.skillset_config;
|
let skillset_config = entity.skillset_config;
|
||||||
|
|
||||||
stats.skill_set =
|
let skill_set =
|
||||||
SkillSetBuilder::build_skillset(&main_tool, skillset_config).build();
|
SkillSetBuilder::build_skillset(&main_tool, skillset_config).build();
|
||||||
let loadout =
|
let loadout =
|
||||||
LoadoutBuilder::build_loadout(body, main_tool, loadout_config, economy).build();
|
LoadoutBuilder::build_loadout(body, main_tool, loadout_config, economy).build();
|
||||||
@ -189,6 +189,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
server_emitter.emit(ServerEvent::CreateNpc {
|
server_emitter.emit(ServerEvent::CreateNpc {
|
||||||
pos: Pos(entity.pos),
|
pos: Pos(entity.pos),
|
||||||
stats,
|
stats,
|
||||||
|
skill_set,
|
||||||
health,
|
health,
|
||||||
poise,
|
poise,
|
||||||
loadout,
|
loadout,
|
||||||
|
@ -20,7 +20,7 @@ use common::{
|
|||||||
combat::{combat_rating, Damage},
|
combat::{combat_rating, Damage},
|
||||||
comp::{
|
comp::{
|
||||||
item::{ItemDef, MaterialStatManifest, Quality},
|
item::{ItemDef, MaterialStatManifest, Quality},
|
||||||
Body, Energy, Health, Inventory, Poise, Stats,
|
Body, Energy, Health, Inventory, Poise, SkillSet, Stats,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
@ -473,6 +473,7 @@ pub struct Bag<'a> {
|
|||||||
pulse: f32,
|
pulse: f32,
|
||||||
localized_strings: &'a Localization,
|
localized_strings: &'a Localization,
|
||||||
stats: &'a Stats,
|
stats: &'a Stats,
|
||||||
|
skill_set: &'a SkillSet,
|
||||||
health: &'a Health,
|
health: &'a Health,
|
||||||
energy: &'a Energy,
|
energy: &'a Energy,
|
||||||
show: &'a Show,
|
show: &'a Show,
|
||||||
@ -494,6 +495,7 @@ impl<'a> Bag<'a> {
|
|||||||
pulse: f32,
|
pulse: f32,
|
||||||
localized_strings: &'a Localization,
|
localized_strings: &'a Localization,
|
||||||
stats: &'a Stats,
|
stats: &'a Stats,
|
||||||
|
skill_set: &'a SkillSet,
|
||||||
health: &'a Health,
|
health: &'a Health,
|
||||||
energy: &'a Energy,
|
energy: &'a Energy,
|
||||||
show: &'a Show,
|
show: &'a Show,
|
||||||
@ -513,6 +515,7 @@ impl<'a> Bag<'a> {
|
|||||||
pulse,
|
pulse,
|
||||||
localized_strings,
|
localized_strings,
|
||||||
stats,
|
stats,
|
||||||
|
skill_set,
|
||||||
energy,
|
energy,
|
||||||
health,
|
health,
|
||||||
show,
|
show,
|
||||||
@ -738,8 +741,14 @@ impl<'a> Widget for Bag<'a> {
|
|||||||
.resize(STATS.len(), &mut ui.widget_id_generator())
|
.resize(STATS.len(), &mut ui.widget_id_generator())
|
||||||
});
|
});
|
||||||
// Stats
|
// Stats
|
||||||
let combat_rating =
|
let combat_rating = combat_rating(
|
||||||
combat_rating(inventory, self.health, self.stats, *self.body, &self.msm).min(999.9);
|
inventory,
|
||||||
|
self.health,
|
||||||
|
self.skill_set,
|
||||||
|
*self.body,
|
||||||
|
&self.msm,
|
||||||
|
)
|
||||||
|
.min(999.9);
|
||||||
let indicator_col = cr_color(combat_rating);
|
let indicator_col = cr_color(combat_rating);
|
||||||
for i in STATS.iter().copied().enumerate() {
|
for i in STATS.iter().copied().enumerate() {
|
||||||
let btn = Button::image(match i.1 {
|
let btn = Button::image(match i.1 {
|
||||||
|
@ -9,7 +9,7 @@ use crate::{
|
|||||||
GlobalState,
|
GlobalState,
|
||||||
};
|
};
|
||||||
use client::Client;
|
use client::Client;
|
||||||
use common::comp::Stats;
|
use common::comp::{SkillSet, Stats};
|
||||||
use conrod_core::{
|
use conrod_core::{
|
||||||
widget::{self, Button, Image, Text},
|
widget::{self, Button, Image, Text},
|
||||||
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
|
||||||
@ -59,6 +59,7 @@ pub struct Buttons<'a> {
|
|||||||
tooltip_manager: &'a mut TooltipManager,
|
tooltip_manager: &'a mut TooltipManager,
|
||||||
localized_strings: &'a Localization,
|
localized_strings: &'a Localization,
|
||||||
stats: &'a Stats,
|
stats: &'a Stats,
|
||||||
|
skill_set: &'a SkillSet,
|
||||||
pulse: f32,
|
pulse: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,6 +75,7 @@ impl<'a> Buttons<'a> {
|
|||||||
tooltip_manager: &'a mut TooltipManager,
|
tooltip_manager: &'a mut TooltipManager,
|
||||||
localized_strings: &'a Localization,
|
localized_strings: &'a Localization,
|
||||||
stats: &'a Stats,
|
stats: &'a Stats,
|
||||||
|
skill_set: &'a SkillSet,
|
||||||
pulse: f32,
|
pulse: f32,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -87,6 +89,7 @@ impl<'a> Buttons<'a> {
|
|||||||
tooltip_manager,
|
tooltip_manager,
|
||||||
localized_strings,
|
localized_strings,
|
||||||
stats,
|
stats,
|
||||||
|
skill_set,
|
||||||
pulse,
|
pulse,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -335,7 +338,7 @@ impl<'a> Widget for Buttons<'a> {
|
|||||||
.set(state.ids.map_text, ui);
|
.set(state.ids.map_text, ui);
|
||||||
}
|
}
|
||||||
// Diary
|
// Diary
|
||||||
let unspent_sp = self.stats.skill_set.has_available_sp();
|
let unspent_sp = self.skill_set.has_available_sp();
|
||||||
if Button::image(if !unspent_sp {
|
if Button::image(if !unspent_sp {
|
||||||
self.imgs.spellbook_button
|
self.imgs.spellbook_button
|
||||||
} else {
|
} else {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -348,6 +348,7 @@ impl<'a> Widget for Group<'a> {
|
|||||||
};
|
};
|
||||||
let client_state = self.client.state();
|
let client_state = self.client.state();
|
||||||
let stats = client_state.ecs().read_storage::<common::comp::Stats>();
|
let stats = client_state.ecs().read_storage::<common::comp::Stats>();
|
||||||
|
let skill_sets = client_state.ecs().read_storage::<common::comp::SkillSet>();
|
||||||
let healths = client_state.ecs().read_storage::<common::comp::Health>();
|
let healths = client_state.ecs().read_storage::<common::comp::Health>();
|
||||||
let energy = client_state.ecs().read_storage::<common::comp::Energy>();
|
let energy = client_state.ecs().read_storage::<common::comp::Energy>();
|
||||||
let buffs = client_state.ecs().read_storage::<common::comp::Buffs>();
|
let buffs = client_state.ecs().read_storage::<common::comp::Buffs>();
|
||||||
@ -361,6 +362,7 @@ impl<'a> Widget for Group<'a> {
|
|||||||
self.show.group = true;
|
self.show.group = true;
|
||||||
let entity = uid_allocator.retrieve_entity_internal(uid.into());
|
let entity = uid_allocator.retrieve_entity_internal(uid.into());
|
||||||
let stats = entity.and_then(|entity| stats.get(entity));
|
let stats = entity.and_then(|entity| stats.get(entity));
|
||||||
|
let skill_set = entity.and_then(|entity| skill_sets.get(entity));
|
||||||
let health = entity.and_then(|entity| healths.get(entity));
|
let health = entity.and_then(|entity| healths.get(entity));
|
||||||
let energy = entity.and_then(|entity| energy.get(entity));
|
let energy = entity.and_then(|entity| energy.get(entity));
|
||||||
let buffs = entity.and_then(|entity| buffs.get(entity));
|
let buffs = entity.and_then(|entity| buffs.get(entity));
|
||||||
@ -368,11 +370,11 @@ impl<'a> Widget for Group<'a> {
|
|||||||
let is_leader = uid == leader;
|
let is_leader = uid == leader;
|
||||||
let body = entity.and_then(|entity| bodies.get(entity));
|
let body = entity.and_then(|entity| bodies.get(entity));
|
||||||
|
|
||||||
if let (Some(stats), Some(inventory), Some(health), Some(body)) =
|
if let (Some(stats), Some(skill_set), Some(inventory), Some(health), Some(body)) =
|
||||||
(stats, inventory, health, body)
|
(stats, skill_set, inventory, health, body)
|
||||||
{
|
{
|
||||||
let combat_rating =
|
let combat_rating =
|
||||||
combat::combat_rating(inventory, health, stats, *body, &self.msm);
|
combat::combat_rating(inventory, health, skill_set, *body, &self.msm);
|
||||||
let char_name = stats.name.to_string();
|
let char_name = stats.name.to_string();
|
||||||
let health_perc =
|
let health_perc =
|
||||||
health.current() as f64 / health.base_max().max(health.maximum()) as f64;
|
health.current() as f64 / health.base_max().max(health.maximum()) as f64;
|
||||||
|
@ -76,8 +76,11 @@ impl State {
|
|||||||
use specs::WorldExt;
|
use specs::WorldExt;
|
||||||
let inventories = client.state().ecs().read_storage::<Inventory>();
|
let inventories = client.state().ecs().read_storage::<Inventory>();
|
||||||
let inventory = inventories.get(client.entity());
|
let inventory = inventories.get(client.entity());
|
||||||
let stats = client.state().ecs().read_storage::<common::comp::Stats>();
|
let skill_sets = client
|
||||||
let stat = stats.get(client.entity());
|
.state()
|
||||||
|
.ecs()
|
||||||
|
.read_storage::<common::comp::SkillSet>();
|
||||||
|
let skill_set = skill_sets.get(client.entity());
|
||||||
|
|
||||||
let hands =
|
let hands =
|
||||||
|equip_slot| match inventory.and_then(|i| i.equipped(equip_slot).map(|i| i.kind())) {
|
|equip_slot| match inventory.and_then(|i| i.equipped(equip_slot).map(|i| i.kind())) {
|
||||||
@ -91,8 +94,8 @@ impl State {
|
|||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let should_be_present = if let (Some(inventory), Some(stat), Some(equip_slot)) =
|
let should_be_present = if let (Some(inventory), Some(skill_set), Some(equip_slot)) =
|
||||||
(inventory, stat, equip_slot)
|
(inventory, skill_set, equip_slot)
|
||||||
{
|
{
|
||||||
inventory.equipped(equip_slot).map_or(false, |i| {
|
inventory.equipped(equip_slot).map_or(false, |i| {
|
||||||
i.item_config_expect()
|
i.item_config_expect()
|
||||||
@ -100,9 +103,7 @@ impl State {
|
|||||||
.abilities
|
.abilities
|
||||||
.get(0)
|
.get(0)
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(false, |(s, _)| {
|
.map_or(false, |(s, _)| s.map_or(true, |s| skill_set.has_skill(s)))
|
||||||
s.map_or(true, |s| stat.skill_set.has_skill(s))
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@ -128,9 +129,12 @@ impl State {
|
|||||||
use specs::WorldExt;
|
use specs::WorldExt;
|
||||||
let inventories = client.state().ecs().read_storage::<Inventory>();
|
let inventories = client.state().ecs().read_storage::<Inventory>();
|
||||||
let inventory = inventories.get(client.entity());
|
let inventory = inventories.get(client.entity());
|
||||||
let stats = client.state().ecs().read_storage::<common::comp::Stats>();
|
let skill_sets = client
|
||||||
let stat = stats.get(client.entity());
|
.state()
|
||||||
let should_be_present = if let (Some(inventory), Some(stat)) = (inventory, stat) {
|
.ecs()
|
||||||
|
.read_storage::<common::comp::SkillSet>();
|
||||||
|
let skill_set = skill_sets.get(client.entity());
|
||||||
|
let should_be_present = if let (Some(inventory), Some(skill_set)) = (inventory, skill_set) {
|
||||||
let hands = |equip_slot| match inventory.equipped(equip_slot).map(|i| i.kind()) {
|
let hands = |equip_slot| match inventory.equipped(equip_slot).map(|i| i.kind()) {
|
||||||
Some(ItemKind::Tool(tool)) => Some(tool.hands),
|
Some(ItemKind::Tool(tool)) => Some(tool.hands),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -154,9 +158,7 @@ impl State {
|
|||||||
.abilities
|
.abilities
|
||||||
.get(skill_index)
|
.get(skill_index)
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(false, |(s, _)| {
|
.map_or(false, |(s, _)| s.map_or(true, |s| skill_set.has_skill(s)))
|
||||||
s.map_or(true, |s| stat.skill_set.has_skill(s))
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -959,6 +959,7 @@ impl Hud {
|
|||||||
let ecs = client.state().ecs();
|
let ecs = client.state().ecs();
|
||||||
let pos = ecs.read_storage::<comp::Pos>();
|
let pos = ecs.read_storage::<comp::Pos>();
|
||||||
let stats = ecs.read_storage::<comp::Stats>();
|
let stats = ecs.read_storage::<comp::Stats>();
|
||||||
|
let skill_sets = ecs.read_storage::<comp::SkillSet>();
|
||||||
let healths = ecs.read_storage::<comp::Health>();
|
let healths = ecs.read_storage::<comp::Health>();
|
||||||
let buffs = ecs.read_storage::<comp::Buffs>();
|
let buffs = ecs.read_storage::<comp::Buffs>();
|
||||||
let energy = ecs.read_storage::<comp::Energy>();
|
let energy = ecs.read_storage::<comp::Energy>();
|
||||||
@ -1456,11 +1457,12 @@ impl Hud {
|
|||||||
let speech_bubbles = &self.speech_bubbles;
|
let speech_bubbles = &self.speech_bubbles;
|
||||||
|
|
||||||
// Render overhead name tags and health bars
|
// Render overhead name tags and health bars
|
||||||
for (pos, info, bubble, _, health, _, height_offset, hpfl, in_group) in (
|
for (pos, info, bubble, _, _, health, _, height_offset, hpfl, in_group) in (
|
||||||
&entities,
|
&entities,
|
||||||
&pos,
|
&pos,
|
||||||
interpolated.maybe(),
|
interpolated.maybe(),
|
||||||
&stats,
|
&stats,
|
||||||
|
&skill_sets,
|
||||||
healths.maybe(),
|
healths.maybe(),
|
||||||
&buffs,
|
&buffs,
|
||||||
energy.maybe(),
|
energy.maybe(),
|
||||||
@ -1472,7 +1474,7 @@ impl Hud {
|
|||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
.filter(|t| {
|
.filter(|t| {
|
||||||
let health = t.4;
|
let health = t.5;
|
||||||
let entity = t.0;
|
let entity = t.0;
|
||||||
entity != me && !health.map_or(false, |h| h.is_dead)
|
entity != me && !health.map_or(false, |h| h.is_dead)
|
||||||
})
|
})
|
||||||
@ -1482,6 +1484,7 @@ impl Hud {
|
|||||||
pos,
|
pos,
|
||||||
interpolated,
|
interpolated,
|
||||||
stats,
|
stats,
|
||||||
|
skill_set,
|
||||||
health,
|
health,
|
||||||
buffs,
|
buffs,
|
||||||
energy,
|
energy,
|
||||||
@ -1523,7 +1526,7 @@ impl Hud {
|
|||||||
buffs,
|
buffs,
|
||||||
energy,
|
energy,
|
||||||
combat_rating: health.map_or(0.0, |health| {
|
combat_rating: health.map_or(0.0, |health| {
|
||||||
combat::combat_rating(inventory, health, stats, *body, &msm)
|
combat::combat_rating(inventory, health, skill_set, *body, &msm)
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
let bubble = if dist_sqr < SPEECH_BUBBLE_RANGE.powi(2) {
|
let bubble = if dist_sqr < SPEECH_BUBBLE_RANGE.powi(2) {
|
||||||
@ -1538,6 +1541,7 @@ impl Hud {
|
|||||||
info,
|
info,
|
||||||
bubble,
|
bubble,
|
||||||
stats,
|
stats,
|
||||||
|
skill_set,
|
||||||
health,
|
health,
|
||||||
buffs,
|
buffs,
|
||||||
body.height() * scale.map_or(1.0, |s| s.0) + 0.5,
|
body.height() * scale.map_or(1.0, |s| s.0) + 0.5,
|
||||||
@ -2167,10 +2171,12 @@ impl Hud {
|
|||||||
|
|
||||||
// Bag button and nearby icons
|
// Bag button and nearby icons
|
||||||
let ecs = client.state().ecs();
|
let ecs = client.state().ecs();
|
||||||
|
let entity = client.entity();
|
||||||
let stats = ecs.read_storage::<comp::Stats>();
|
let stats = ecs.read_storage::<comp::Stats>();
|
||||||
|
let skill_sets = ecs.read_storage::<comp::SkillSet>();
|
||||||
let buffs = ecs.read_storage::<comp::Buffs>();
|
let buffs = ecs.read_storage::<comp::Buffs>();
|
||||||
let msm = ecs.read_resource::<MaterialStatManifest>();
|
let msm = ecs.read_resource::<MaterialStatManifest>();
|
||||||
if let Some(player_stats) = stats.get(client.entity()) {
|
if let (Some(player_stats), Some(skill_set)) = (stats.get(entity), skill_sets.get(entity)) {
|
||||||
match Buttons::new(
|
match Buttons::new(
|
||||||
client,
|
client,
|
||||||
self.show.bag,
|
self.show.bag,
|
||||||
@ -2181,6 +2187,7 @@ impl Hud {
|
|||||||
tooltip_manager,
|
tooltip_manager,
|
||||||
i18n,
|
i18n,
|
||||||
&player_stats,
|
&player_stats,
|
||||||
|
&skill_set,
|
||||||
self.pulse,
|
self.pulse,
|
||||||
)
|
)
|
||||||
.set(self.ids.buttons, ui_widgets)
|
.set(self.ids.buttons, ui_widgets)
|
||||||
@ -2342,8 +2349,9 @@ impl Hud {
|
|||||||
}
|
}
|
||||||
// Bag contents
|
// Bag contents
|
||||||
if self.show.bag {
|
if self.show.bag {
|
||||||
if let (Some(player_stats), Some(health), Some(energy), Some(body)) = (
|
if let (Some(player_stats), Some(skill_set), Some(health), Some(energy), Some(body)) = (
|
||||||
stats.get(client.entity()),
|
stats.get(client.entity()),
|
||||||
|
skill_sets.get(client.entity()),
|
||||||
healths.get(entity),
|
healths.get(entity),
|
||||||
energies.get(entity),
|
energies.get(entity),
|
||||||
bodies.get(entity),
|
bodies.get(entity),
|
||||||
@ -2360,6 +2368,7 @@ impl Hud {
|
|||||||
self.pulse,
|
self.pulse,
|
||||||
i18n,
|
i18n,
|
||||||
&player_stats,
|
&player_stats,
|
||||||
|
&skill_set,
|
||||||
&health,
|
&health,
|
||||||
&energy,
|
&energy,
|
||||||
&self.show,
|
&self.show,
|
||||||
@ -2758,12 +2767,12 @@ impl Hud {
|
|||||||
// Diary
|
// Diary
|
||||||
if self.show.diary {
|
if self.show.diary {
|
||||||
let entity = client.entity();
|
let entity = client.entity();
|
||||||
let stats = ecs.read_storage::<comp::Stats>();
|
let skill_sets = ecs.read_storage::<comp::SkillSet>();
|
||||||
if let Some(stats) = stats.get(entity) {
|
if let Some(skill_set) = skill_sets.get(entity) {
|
||||||
for event in Diary::new(
|
for event in Diary::new(
|
||||||
&self.show,
|
&self.show,
|
||||||
client,
|
client,
|
||||||
&stats,
|
&skill_set,
|
||||||
&self.imgs,
|
&self.imgs,
|
||||||
&self.item_imgs,
|
&self.item_imgs,
|
||||||
&self.fonts,
|
&self.fonts,
|
||||||
|
Loading…
Reference in New Issue
Block a user