mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Ability pool mostly functional.
This commit is contained in:
parent
7438252560
commit
a8bec0280c
@ -15,6 +15,7 @@ sum_type! {
|
|||||||
CanBuild(comp::CanBuild),
|
CanBuild(comp::CanBuild),
|
||||||
Stats(comp::Stats),
|
Stats(comp::Stats),
|
||||||
SkillSet(comp::SkillSet),
|
SkillSet(comp::SkillSet),
|
||||||
|
AbilityPool(comp::AbilityPool),
|
||||||
Buffs(comp::Buffs),
|
Buffs(comp::Buffs),
|
||||||
Auras(comp::Auras),
|
Auras(comp::Auras),
|
||||||
Energy(comp::Energy),
|
Energy(comp::Energy),
|
||||||
@ -50,6 +51,7 @@ sum_type! {
|
|||||||
CanBuild(PhantomData<comp::CanBuild>),
|
CanBuild(PhantomData<comp::CanBuild>),
|
||||||
Stats(PhantomData<comp::Stats>),
|
Stats(PhantomData<comp::Stats>),
|
||||||
SkillSet(PhantomData<comp::SkillSet>),
|
SkillSet(PhantomData<comp::SkillSet>),
|
||||||
|
AbilityPool(PhantomData<comp::AbilityPool>),
|
||||||
Buffs(PhantomData<comp::Buffs>),
|
Buffs(PhantomData<comp::Buffs>),
|
||||||
Auras(PhantomData<comp::Auras>),
|
Auras(PhantomData<comp::Auras>),
|
||||||
Energy(PhantomData<comp::Energy>),
|
Energy(PhantomData<comp::Energy>),
|
||||||
@ -85,6 +87,7 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
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::SkillSet(comp) => sync::handle_insert(comp, entity, world),
|
||||||
|
EcsCompPacket::AbilityPool(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),
|
||||||
@ -124,6 +127,7 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
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::SkillSet(comp) => sync::handle_modify(comp, entity, world),
|
||||||
|
EcsCompPacket::AbilityPool(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),
|
||||||
@ -163,6 +167,9 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
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::SkillSet(_) => sync::handle_remove::<comp::SkillSet>(entity, world),
|
||||||
|
EcsCompPhantom::AbilityPool(_) => {
|
||||||
|
sync::handle_remove::<comp::AbilityPool>(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),
|
||||||
|
@ -3,9 +3,17 @@ use crate::{
|
|||||||
combat::{self, CombatEffect, DamageKind, Knockback},
|
combat::{self, CombatEffect, DamageKind, Knockback},
|
||||||
comp::{
|
comp::{
|
||||||
self, aura, beam, buff,
|
self, aura, beam, buff,
|
||||||
inventory::item::tool::{Stats, ToolKind},
|
controller::InputKind,
|
||||||
|
inventory::{
|
||||||
|
item::{
|
||||||
|
tool::{Stats, ToolKind},
|
||||||
|
ItemKind,
|
||||||
|
},
|
||||||
|
slot::EquipSlot,
|
||||||
|
Inventory,
|
||||||
|
},
|
||||||
projectile::ProjectileConstructor,
|
projectile::ProjectileConstructor,
|
||||||
skills::{self, SKILL_MODIFIERS},
|
skills::{self, Skill, SkillSet, SKILL_MODIFIERS},
|
||||||
Body, CharacterState, LightEmitter, StateUpdate,
|
Body, CharacterState, LightEmitter, StateUpdate,
|
||||||
},
|
},
|
||||||
states::{
|
states::{
|
||||||
@ -16,8 +24,162 @@ use crate::{
|
|||||||
terrain::SpriteKind,
|
terrain::SpriteKind,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use specs::{Component, DerefFlaggedStorage};
|
||||||
|
use specs_idvs::IdvStorage;
|
||||||
use std::{convert::TryFrom, time::Duration};
|
use std::{convert::TryFrom, time::Duration};
|
||||||
|
|
||||||
|
pub const MAX_ABILITIES: usize = 5;
|
||||||
|
|
||||||
|
// TODO: Should primary, secondary, and dodge be moved into here? Would
|
||||||
|
// essentially require custom enum that are only used for those (except maybe
|
||||||
|
// dodge if we make movement and have potentially differ based off of armor) but
|
||||||
|
// would also allow logic to be a bit more centralized
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct AbilityPool {
|
||||||
|
primary: Ability,
|
||||||
|
secondary: Ability,
|
||||||
|
movement: Ability,
|
||||||
|
abilities: [Ability; MAX_ABILITIES],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for AbilityPool {
|
||||||
|
type Storage = DerefFlaggedStorage<Self, IdvStorage<Self>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AbilityPool {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
primary: Ability::ToolPrimary,
|
||||||
|
secondary: Ability::ToolSecondary,
|
||||||
|
movement: Ability::SpeciesMovement,
|
||||||
|
abilities: [Ability::Empty; MAX_ABILITIES],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AbilityPool {
|
||||||
|
pub fn new(inv: Option<&Inventory>, skill_set: Option<&SkillSet>) -> Self {
|
||||||
|
let mut pool = Self::default();
|
||||||
|
pool.auto_update(inv, skill_set);
|
||||||
|
pool
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn change_ability(&mut self, slot: usize, new_ability: Ability) {
|
||||||
|
if let Some(ability) = self.abilities.get_mut(slot) {
|
||||||
|
*ability = new_ability;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn activate_ability(
|
||||||
|
&self,
|
||||||
|
input: InputKind,
|
||||||
|
inv: Option<&Inventory>,
|
||||||
|
skill_set: &SkillSet,
|
||||||
|
body: &Body,
|
||||||
|
// bool is from_offhand
|
||||||
|
) -> Option<(CharacterAbility, bool)> {
|
||||||
|
let ability = match input {
|
||||||
|
InputKind::Primary => Some(self.primary),
|
||||||
|
InputKind::Secondary => Some(self.secondary),
|
||||||
|
InputKind::Roll => Some(self.movement),
|
||||||
|
InputKind::Ability(index) => self.abilities.get(index).copied(),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
.unwrap_or(Ability::Empty);
|
||||||
|
|
||||||
|
let ability_set = |equip_slot| {
|
||||||
|
inv.and_then(|inv| inv.equipped(equip_slot))
|
||||||
|
.map(|i| &i.item_config_expect().abilities)
|
||||||
|
};
|
||||||
|
|
||||||
|
let scale_ability = |ability: CharacterAbility, equip_slot| {
|
||||||
|
let tool_kind =
|
||||||
|
inv.and_then(|inv| inv.equipped(equip_slot))
|
||||||
|
.and_then(|item| match &item.kind {
|
||||||
|
ItemKind::Tool(tool) => Some(tool.kind),
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
ability.adjusted_by_skills(skill_set, tool_kind)
|
||||||
|
};
|
||||||
|
|
||||||
|
let unlocked = |(s, a): (Option<Skill>, CharacterAbility)| {
|
||||||
|
// If there is a skill requirement and the skillset does not contain the
|
||||||
|
// required skill, return None
|
||||||
|
s.map_or(true, |s| skill_set.has_skill(s)).then_some(a)
|
||||||
|
};
|
||||||
|
|
||||||
|
match ability {
|
||||||
|
Ability::ToolPrimary => ability_set(EquipSlot::ActiveMainhand)
|
||||||
|
.map(|abilities| abilities.primary.clone())
|
||||||
|
.map(|ability| (scale_ability(ability, EquipSlot::ActiveMainhand), false)),
|
||||||
|
Ability::ToolSecondary => ability_set(EquipSlot::ActiveOffhand)
|
||||||
|
.map(|abilities| abilities.secondary.clone())
|
||||||
|
.map(|ability| (scale_ability(ability, EquipSlot::ActiveOffhand), true))
|
||||||
|
.or({
|
||||||
|
ability_set(EquipSlot::ActiveMainhand)
|
||||||
|
.map(|abilities| abilities.secondary.clone())
|
||||||
|
.map(|ability| (scale_ability(ability, EquipSlot::ActiveMainhand), false))
|
||||||
|
}),
|
||||||
|
Ability::SpeciesMovement => matches!(body, Body::Humanoid(_))
|
||||||
|
.then_some(CharacterAbility::default_roll())
|
||||||
|
.map(|ability| (ability.adjusted_by_skills(skill_set, None), false)),
|
||||||
|
Ability::MainWeaponAbility(index) => ability_set(EquipSlot::ActiveMainhand)
|
||||||
|
.and_then(|abilities| abilities.abilities.get(index).cloned())
|
||||||
|
.and_then(unlocked)
|
||||||
|
.map(|ability| (scale_ability(ability, EquipSlot::ActiveMainhand), false)),
|
||||||
|
Ability::OffWeaponAbility(index) => ability_set(EquipSlot::ActiveOffhand)
|
||||||
|
.and_then(|abilities| abilities.abilities.get(index).cloned())
|
||||||
|
.and_then(unlocked)
|
||||||
|
.map(|ability| (scale_ability(ability, EquipSlot::ActiveOffhand), true)),
|
||||||
|
Ability::Empty => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Potentially remove after there is an actual UI
|
||||||
|
pub fn auto_update(&mut self, inv: Option<&Inventory>, skill_set: Option<&SkillSet>) {
|
||||||
|
fn iter_unlocked_abilities(
|
||||||
|
inv: Option<&Inventory>,
|
||||||
|
skill_set: Option<&SkillSet>,
|
||||||
|
equip_slot: EquipSlot,
|
||||||
|
) -> Vec<Ability> {
|
||||||
|
let ability_from_slot = move |i| match equip_slot {
|
||||||
|
EquipSlot::ActiveMainhand => Ability::MainWeaponAbility(i),
|
||||||
|
EquipSlot::ActiveOffhand => Ability::OffWeaponAbility(i),
|
||||||
|
_ => Ability::Empty,
|
||||||
|
};
|
||||||
|
|
||||||
|
inv
|
||||||
|
.and_then(|inv| inv.equipped(equip_slot))
|
||||||
|
.iter()
|
||||||
|
.flat_map(|i| &i.item_config_expect().abilities.abilities)
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(move |(i, (skill, _))| skill.map_or(true, |s| skill_set.map_or(false, |ss| ss.has_skill(s))).then_some(ability_from_slot(i)))
|
||||||
|
// TODO: Let someone smarter than borrow checker remove collect
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
let main_abilities = iter_unlocked_abilities(inv, skill_set, EquipSlot::ActiveMainhand);
|
||||||
|
let off_abilities = iter_unlocked_abilities(inv, skill_set, EquipSlot::ActiveOffhand);
|
||||||
|
for (i, ability) in
|
||||||
|
(0..MAX_ABILITIES).zip(main_abilities.iter().chain(off_abilities.iter()))
|
||||||
|
{
|
||||||
|
self.change_ability(i, *ability);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
|
||||||
|
pub enum Ability {
|
||||||
|
ToolPrimary,
|
||||||
|
ToolSecondary,
|
||||||
|
SpeciesMovement,
|
||||||
|
MainWeaponAbility(usize),
|
||||||
|
OffWeaponAbility(usize),
|
||||||
|
Empty,
|
||||||
|
/* For future use
|
||||||
|
* ArmorAbility(usize), */
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug, Serialize, Deserialize)]
|
||||||
pub enum CharacterAbilityType {
|
pub enum CharacterAbilityType {
|
||||||
BasicMelee,
|
BasicMelee,
|
||||||
@ -899,7 +1061,7 @@ impl CharacterAbility {
|
|||||||
|
|
||||||
#[warn(clippy::pedantic)]
|
#[warn(clippy::pedantic)]
|
||||||
fn adjusted_by_mining_skills(&mut self, skillset: &skills::SkillSet) {
|
fn adjusted_by_mining_skills(&mut self, skillset: &skills::SkillSet) {
|
||||||
use skills::{MiningSkill::Speed, Skill};
|
use skills::MiningSkill::Speed;
|
||||||
|
|
||||||
if let CharacterAbility::BasicMelee {
|
if let CharacterAbility::BasicMelee {
|
||||||
ref mut buildup_duration,
|
ref mut buildup_duration,
|
||||||
@ -921,8 +1083,6 @@ impl CharacterAbility {
|
|||||||
|
|
||||||
#[warn(clippy::pedantic)]
|
#[warn(clippy::pedantic)]
|
||||||
fn adjusted_by_general_skills(&mut self, skillset: &skills::SkillSet) {
|
fn adjusted_by_general_skills(&mut self, skillset: &skills::SkillSet) {
|
||||||
use skills::Skill;
|
|
||||||
|
|
||||||
if let CharacterAbility::Roll {
|
if let CharacterAbility::Roll {
|
||||||
ref mut energy_cost,
|
ref mut energy_cost,
|
||||||
ref mut roll_strength,
|
ref mut roll_strength,
|
||||||
|
@ -47,7 +47,7 @@ pub mod visual;
|
|||||||
// Reexports
|
// Reexports
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub use self::{
|
pub use self::{
|
||||||
ability::{CharacterAbility, CharacterAbilityType},
|
ability::{Ability, AbilityPool, CharacterAbility, CharacterAbilityType},
|
||||||
admin::{Admin, AdminRole},
|
admin::{Admin, AdminRole},
|
||||||
agent::{Agent, Alignment, Behavior, BehaviorCapability, BehaviorState, PidController},
|
agent::{Agent, Alignment, Behavior, BehaviorCapability, BehaviorState, PidController},
|
||||||
anchor::Anchor,
|
anchor::Anchor,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
self, character_state::OutputEvents, item::MaterialStatManifest, Beam, Body,
|
self, character_state::OutputEvents, item::MaterialStatManifest, AbilityPool, Beam, Body,
|
||||||
CharacterState, Combo, ControlAction, Controller, ControllerInputs, Density, Energy,
|
CharacterState, Combo, ControlAction, Controller, ControllerInputs, Density, Energy,
|
||||||
Health, InputAttr, InputKind, Inventory, InventoryAction, Mass, Melee, Ori, PhysicsState,
|
Health, InputAttr, InputKind, Inventory, InventoryAction, Mass, Melee, Ori, PhysicsState,
|
||||||
Pos, SkillSet, StateUpdate, Stats, Vel,
|
Pos, SkillSet, StateUpdate, Stats, Vel,
|
||||||
@ -124,6 +124,7 @@ pub struct JoinData<'a> {
|
|||||||
pub updater: &'a LazyUpdate,
|
pub updater: &'a LazyUpdate,
|
||||||
pub stats: &'a Stats,
|
pub stats: &'a Stats,
|
||||||
pub skill_set: &'a SkillSet,
|
pub skill_set: &'a SkillSet,
|
||||||
|
pub ability_pool: &'a AbilityPool,
|
||||||
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>,
|
||||||
@ -149,6 +150,7 @@ pub struct JoinStruct<'a> {
|
|||||||
pub beam: Option<&'a Beam>,
|
pub beam: Option<&'a Beam>,
|
||||||
pub stat: &'a Stats,
|
pub stat: &'a Stats,
|
||||||
pub skill_set: &'a SkillSet,
|
pub skill_set: &'a SkillSet,
|
||||||
|
pub ability_pool: &'a AbilityPool,
|
||||||
pub combo: &'a Combo,
|
pub combo: &'a Combo,
|
||||||
pub alignment: Option<&'a comp::Alignment>,
|
pub alignment: Option<&'a comp::Alignment>,
|
||||||
pub terrain: &'a TerrainGrid,
|
pub terrain: &'a TerrainGrid,
|
||||||
@ -186,6 +188,7 @@ impl<'a> JoinData<'a> {
|
|||||||
combo: j.combo,
|
combo: j.combo,
|
||||||
alignment: j.alignment,
|
alignment: j.alignment,
|
||||||
terrain: j.terrain,
|
terrain: j.terrain,
|
||||||
|
ability_pool: j.ability_pool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -821,61 +821,16 @@ pub fn handle_jump(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_ability(data: &JoinData<'_>, update: &mut StateUpdate, input: InputKind) {
|
fn handle_ability(data: &JoinData<'_>, update: &mut StateUpdate, input: InputKind) {
|
||||||
let hands = get_hands(data);
|
if let Some((ability, from_offhand)) = data
|
||||||
|
.ability_pool
|
||||||
// Mouse1 and Skill1 always use the MainHand slot
|
.activate_ability(input, data.inventory, data.skill_set, data.body)
|
||||||
let always_main_hand = matches!(input, InputKind::Primary | InputKind::Ability(0));
|
.filter(|(ability, _)| ability.requirements_paid(data, update))
|
||||||
let no_main_hand = hands.0.is_none();
|
{
|
||||||
// skill_index used to select ability for the AbilityKey::Skill2 input
|
update.character = CharacterState::from((
|
||||||
let (equip_slot, skill_index) = if no_main_hand {
|
&ability,
|
||||||
(Some(EquipSlot::ActiveOffhand), 1)
|
AbilityInfo::from_input(data, from_offhand, input),
|
||||||
} else if always_main_hand {
|
data,
|
||||||
(Some(EquipSlot::ActiveMainhand), 0)
|
));
|
||||||
} else {
|
|
||||||
match hands {
|
|
||||||
(Some(Hands::Two), _) => (Some(EquipSlot::ActiveMainhand), 1),
|
|
||||||
(_, Some(Hands::One)) => (Some(EquipSlot::ActiveOffhand), 0),
|
|
||||||
(Some(Hands::One), _) => (Some(EquipSlot::ActiveMainhand), 1),
|
|
||||||
(_, _) => (None, 0),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let unlocked = |(s, a): (Option<Skill>, CharacterAbility)| {
|
|
||||||
s.map_or(true, |s| data.skill_set.has_skill(s)).then_some(a)
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(equip_slot) = equip_slot {
|
|
||||||
if let Some(ability) = data
|
|
||||||
.inventory
|
|
||||||
.and_then(|inv| inv.equipped(equip_slot))
|
|
||||||
.map(|i| &i.item_config_expect().abilities)
|
|
||||||
.and_then(|abilities| match input {
|
|
||||||
InputKind::Primary => Some(abilities.primary.clone()),
|
|
||||||
InputKind::Secondary => Some(abilities.secondary.clone()),
|
|
||||||
InputKind::Ability(0) => abilities.abilities.get(0).cloned().and_then(unlocked),
|
|
||||||
InputKind::Ability(i) => abilities
|
|
||||||
.abilities
|
|
||||||
.get(if i < 2 { skill_index } else { i })
|
|
||||||
.cloned()
|
|
||||||
.and_then(unlocked),
|
|
||||||
InputKind::Roll | InputKind::Jump | InputKind::Fly | InputKind::Block => None,
|
|
||||||
})
|
|
||||||
.map(|a| {
|
|
||||||
let tool = unwrap_tool_data(data, equip_slot).map(|t| t.kind);
|
|
||||||
a.adjusted_by_skills(data.skill_set, tool)
|
|
||||||
})
|
|
||||||
.filter(|ability| ability.requirements_paid(data, update))
|
|
||||||
{
|
|
||||||
update.character = CharacterState::from((
|
|
||||||
&ability,
|
|
||||||
AbilityInfo::from_input(
|
|
||||||
data,
|
|
||||||
matches!(equip_slot, EquipSlot::ActiveOffhand),
|
|
||||||
input,
|
|
||||||
),
|
|
||||||
data,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,6 +129,7 @@ impl State {
|
|||||||
ecs.register::<comp::Player>();
|
ecs.register::<comp::Player>();
|
||||||
ecs.register::<comp::Stats>();
|
ecs.register::<comp::Stats>();
|
||||||
ecs.register::<comp::SkillSet>();
|
ecs.register::<comp::SkillSet>();
|
||||||
|
ecs.register::<comp::AbilityPool>();
|
||||||
ecs.register::<comp::Buffs>();
|
ecs.register::<comp::Buffs>();
|
||||||
ecs.register::<comp::Auras>();
|
ecs.register::<comp::Auras>();
|
||||||
ecs.register::<comp::Energy>();
|
ecs.register::<comp::Energy>();
|
||||||
|
@ -5,9 +5,10 @@ use specs::{
|
|||||||
|
|
||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
self, character_state::OutputEvents, inventory::item::MaterialStatManifest, Beam, Body,
|
self, character_state::OutputEvents, inventory::item::MaterialStatManifest, AbilityPool,
|
||||||
CharacterState, Combo, Controller, Density, Energy, Health, Inventory, InventoryManip,
|
Beam, Body, CharacterState, Combo, Controller, Density, Energy, Health, Inventory,
|
||||||
Mass, Melee, Mounting, Ori, PhysicsState, Poise, Pos, SkillSet, StateUpdate, Stats, Vel,
|
InventoryManip, Mass, Melee, Mounting, Ori, PhysicsState, Poise, Pos, SkillSet,
|
||||||
|
StateUpdate, Stats, Vel,
|
||||||
},
|
},
|
||||||
event::{EventBus, LocalEvent, ServerEvent},
|
event::{EventBus, LocalEvent, ServerEvent},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
@ -38,6 +39,7 @@ pub struct ReadData<'a> {
|
|||||||
mountings: ReadStorage<'a, Mounting>,
|
mountings: ReadStorage<'a, Mounting>,
|
||||||
stats: ReadStorage<'a, Stats>,
|
stats: ReadStorage<'a, Stats>,
|
||||||
skill_sets: ReadStorage<'a, SkillSet>,
|
skill_sets: ReadStorage<'a, SkillSet>,
|
||||||
|
ability_pools: ReadStorage<'a, AbilityPool>,
|
||||||
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>,
|
||||||
@ -107,7 +109,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
health,
|
health,
|
||||||
body,
|
body,
|
||||||
physics,
|
physics,
|
||||||
(stat, skill_set),
|
(stat, skill_set, ability_pool),
|
||||||
combo,
|
combo,
|
||||||
) in (
|
) in (
|
||||||
&read_data.entities,
|
&read_data.entities,
|
||||||
@ -124,7 +126,11 @@ impl<'a> System<'a> for Sys {
|
|||||||
read_data.healths.maybe(),
|
read_data.healths.maybe(),
|
||||||
&read_data.bodies,
|
&read_data.bodies,
|
||||||
&read_data.physics_states,
|
&read_data.physics_states,
|
||||||
(&read_data.stats, &read_data.skill_sets),
|
(
|
||||||
|
&read_data.stats,
|
||||||
|
&read_data.skill_sets,
|
||||||
|
&read_data.ability_pools,
|
||||||
|
),
|
||||||
&read_data.combos,
|
&read_data.combos,
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
@ -181,6 +187,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
beam: read_data.beams.get(entity),
|
beam: read_data.beams.get(entity),
|
||||||
stat,
|
stat,
|
||||||
skill_set,
|
skill_set,
|
||||||
|
ability_pool,
|
||||||
combo,
|
combo,
|
||||||
alignment: read_data.alignments.get(entity),
|
alignment: read_data.alignments.get(entity),
|
||||||
terrain: &read_data.terrain,
|
terrain: &read_data.terrain,
|
||||||
|
@ -215,6 +215,7 @@ impl StateExt for State {
|
|||||||
.unwrap_or(0),
|
.unwrap_or(0),
|
||||||
))
|
))
|
||||||
.with(stats)
|
.with(stats)
|
||||||
|
.with(comp::AbilityPool::new(Some(&inventory), Some(&skill_set)))
|
||||||
.with(skill_set)
|
.with(skill_set)
|
||||||
.maybe_with(health)
|
.maybe_with(health)
|
||||||
.with(poise)
|
.with(poise)
|
||||||
@ -267,6 +268,7 @@ impl StateExt for State {
|
|||||||
.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::SkillSet::default())
|
||||||
|
.with(comp::AbilityPool::default())
|
||||||
.with(comp::Combo::default());
|
.with(comp::Combo::default());
|
||||||
|
|
||||||
if mountable {
|
if mountable {
|
||||||
@ -504,6 +506,10 @@ 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,
|
||||||
|
comp::AbilityPool::new(Some(&inventory), Some(&skill_set)),
|
||||||
|
);
|
||||||
self.write_component_ignore_entity_dead(entity, skill_set);
|
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(
|
||||||
|
Loading…
Reference in New Issue
Block a user