mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Ability sets now start with non-empty defaults.
This commit is contained in:
@ -74,41 +74,57 @@ impl ActiveAbilities {
|
|||||||
slot: usize,
|
slot: usize,
|
||||||
auxiliary_key: AuxiliaryKey,
|
auxiliary_key: AuxiliaryKey,
|
||||||
new_ability: AuxiliaryAbility,
|
new_ability: AuxiliaryAbility,
|
||||||
|
inventory: Option<&Inventory>,
|
||||||
|
skill_set: Option<&SkillSet>,
|
||||||
) {
|
) {
|
||||||
let auxiliary_set = self
|
let auxiliary_set = self
|
||||||
.auxiliary_sets
|
.auxiliary_sets
|
||||||
.entry(auxiliary_key)
|
.entry(auxiliary_key)
|
||||||
.or_insert([AuxiliaryAbility::Empty; 5]);
|
.or_insert(Self::default_ability_set(inventory, skill_set));
|
||||||
if let Some(ability) = auxiliary_set.get_mut(slot) {
|
if let Some(ability) = auxiliary_set.get_mut(slot) {
|
||||||
*ability = new_ability;
|
*ability = new_ability;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_ability(&self, input: AbilityInput, inventory: Option<&Inventory>) -> Ability {
|
pub fn auxiliary_set(
|
||||||
|
&self,
|
||||||
|
inv: Option<&Inventory>,
|
||||||
|
skill_set: Option<&SkillSet>,
|
||||||
|
) -> [AuxiliaryAbility; MAX_ABILITIES] {
|
||||||
|
let tool_kind = |slot| {
|
||||||
|
inv.and_then(|inv| inv.equipped(slot))
|
||||||
|
.and_then(|item| match item.kind() {
|
||||||
|
ItemKind::Tool(tool) => Some(tool.kind),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let aux_key = (
|
||||||
|
tool_kind(EquipSlot::ActiveMainhand),
|
||||||
|
tool_kind(EquipSlot::ActiveOffhand),
|
||||||
|
);
|
||||||
|
|
||||||
|
self.auxiliary_sets
|
||||||
|
.get(&aux_key)
|
||||||
|
.copied()
|
||||||
|
.unwrap_or_else(|| Self::default_ability_set(inv, skill_set))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_ability(
|
||||||
|
&self,
|
||||||
|
input: AbilityInput,
|
||||||
|
inventory: Option<&Inventory>,
|
||||||
|
skill_set: Option<&SkillSet>,
|
||||||
|
) -> Ability {
|
||||||
match input {
|
match input {
|
||||||
AbilityInput::Primary => self.primary.into(),
|
AbilityInput::Primary => self.primary.into(),
|
||||||
AbilityInput::Secondary => self.secondary.into(),
|
AbilityInput::Secondary => self.secondary.into(),
|
||||||
AbilityInput::Movement => self.movement.into(),
|
AbilityInput::Movement => self.movement.into(),
|
||||||
AbilityInput::Auxiliary(index) => inventory
|
AbilityInput::Auxiliary(index) => self
|
||||||
.and_then(|inv| {
|
.auxiliary_set(inventory, skill_set)
|
||||||
let tool_kind = |slot| {
|
.get(index)
|
||||||
inv.equipped(slot).and_then(|item| match item.kind() {
|
.copied()
|
||||||
ItemKind::Tool(tool) => Some(tool.kind),
|
.map(|a| a.into())
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let aux_key = (
|
|
||||||
tool_kind(EquipSlot::ActiveMainhand),
|
|
||||||
tool_kind(EquipSlot::ActiveOffhand),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.auxiliary_sets
|
|
||||||
.get(&aux_key)
|
|
||||||
.and_then(|entry| entry.get(index))
|
|
||||||
.copied()
|
|
||||||
.map(|a| a.into())
|
|
||||||
})
|
|
||||||
.unwrap_or(Ability::Empty),
|
.unwrap_or(Ability::Empty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,7 +139,7 @@ impl ActiveAbilities {
|
|||||||
body: Option<&Body>,
|
body: Option<&Body>,
|
||||||
// bool is from_offhand
|
// bool is from_offhand
|
||||||
) -> Option<(CharacterAbility, bool)> {
|
) -> Option<(CharacterAbility, bool)> {
|
||||||
let ability = self.get_ability(input, inv);
|
let ability = self.get_ability(input, inv, Some(skill_set));
|
||||||
|
|
||||||
let ability_set = |equip_slot| {
|
let ability_set = |equip_slot| {
|
||||||
inv.and_then(|inv| inv.equipped(equip_slot))
|
inv.and_then(|inv| inv.equipped(equip_slot))
|
||||||
@ -193,44 +209,27 @@ impl ActiveAbilities {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_aux_abilities<'a>(
|
pub fn default_ability_set<'a>(
|
||||||
&'a self,
|
inv: Option<&'a Inventory>,
|
||||||
inventory: Option<&'a Inventory>,
|
skill_set: Option<&'a SkillSet>,
|
||||||
) -> impl Iterator<Item = &AuxiliaryAbility> + 'a {
|
) -> [AuxiliaryAbility; MAX_ABILITIES] {
|
||||||
inventory
|
let mut iter = Self::iter_unlocked_abilities(inv, skill_set, EquipSlot::ActiveMainhand)
|
||||||
.and_then(|inv| {
|
.map(AuxiliaryAbility::MainWeapon)
|
||||||
let tool_kind = |slot| {
|
.chain(
|
||||||
inv.equipped(slot).and_then(|item| match item.kind() {
|
Self::iter_unlocked_abilities(inv, skill_set, EquipSlot::ActiveOffhand)
|
||||||
ItemKind::Tool(tool) => Some(tool.kind),
|
.map(AuxiliaryAbility::OffWeapon),
|
||||||
_ => None,
|
);
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
let aux_key = (
|
let mut array = [AuxiliaryAbility::Empty; MAX_ABILITIES];
|
||||||
tool_kind(EquipSlot::ActiveMainhand),
|
|
||||||
tool_kind(EquipSlot::ActiveOffhand),
|
|
||||||
);
|
|
||||||
|
|
||||||
self.auxiliary_sets.get(&aux_key)
|
for ability in array.iter_mut() {
|
||||||
})
|
if let Some(available_ability) = iter.next() {
|
||||||
.into_iter()
|
*ability = available_ability;
|
||||||
.flatten()
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
array
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Maybe keep this for autopopulating a new combination of weapons?
|
|
||||||
// pub fn auto_update(&mut self, inv: Option<&Inventory>, skill_set:
|
|
||||||
// Option<&SkillSet>) { let main_abilities =
|
|
||||||
// Self::iter_unlocked_abilities(inv, skill_set, EquipSlot::ActiveMainhand)
|
|
||||||
// .map(AuxiliaryAbility::MainWeapon);
|
|
||||||
// let off_abilities = Self::iter_unlocked_abilities(inv, skill_set,
|
|
||||||
// EquipSlot::ActiveOffhand) .map(AuxiliaryAbility::OffWeapon);
|
|
||||||
|
|
||||||
// (0..MAX_ABILITIES)
|
|
||||||
// .zip(main_abilities.chain(off_abilities))
|
|
||||||
// .for_each(|(i, ability)| {
|
|
||||||
// self.change_ability(i, ability);
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum AbilityInput {
|
pub enum AbilityInput {
|
||||||
|
@ -204,6 +204,12 @@ pub enum ServerEvent {
|
|||||||
EntityAttackedHook {
|
EntityAttackedHook {
|
||||||
entity: EcsEntity,
|
entity: EcsEntity,
|
||||||
},
|
},
|
||||||
|
ChangeAbility {
|
||||||
|
entity: EcsEntity,
|
||||||
|
slot: usize,
|
||||||
|
auxiliary_key: comp::ability::AuxiliaryKey,
|
||||||
|
new_ability: comp::ability::AuxiliaryAbility,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventBus<E> {
|
pub struct EventBus<E> {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
agent::{Sound, SoundKind},
|
agent::{Sound, SoundKind},
|
||||||
ActiveAbilities, Body, BuffChange, ControlEvent, Controller, Pos,
|
Body, BuffChange, ControlEvent, Controller, Pos,
|
||||||
},
|
},
|
||||||
event::{EventBus, ServerEvent},
|
event::{EventBus, ServerEvent},
|
||||||
uid::UidAllocator,
|
uid::UidAllocator,
|
||||||
@ -27,20 +27,13 @@ pub struct ReadData<'a> {
|
|||||||
pub struct Sys;
|
pub struct Sys;
|
||||||
|
|
||||||
impl<'a> System<'a> for Sys {
|
impl<'a> System<'a> for Sys {
|
||||||
type SystemData = (
|
type SystemData = (ReadData<'a>, WriteStorage<'a, Controller>);
|
||||||
ReadData<'a>,
|
|
||||||
WriteStorage<'a, Controller>,
|
|
||||||
WriteStorage<'a, ActiveAbilities>,
|
|
||||||
);
|
|
||||||
|
|
||||||
const NAME: &'static str = "controller";
|
const NAME: &'static str = "controller";
|
||||||
const ORIGIN: Origin = Origin::Common;
|
const ORIGIN: Origin = Origin::Common;
|
||||||
const PHASE: Phase = Phase::Create;
|
const PHASE: Phase = Phase::Create;
|
||||||
|
|
||||||
fn run(
|
fn run(_job: &mut Job<Self>, (read_data, mut controllers): Self::SystemData) {
|
||||||
_job: &mut Job<Self>,
|
|
||||||
(read_data, mut controllers, mut active_abilities): Self::SystemData,
|
|
||||||
) {
|
|
||||||
let mut server_emitter = read_data.server_bus.emitter();
|
let mut server_emitter = read_data.server_bus.emitter();
|
||||||
|
|
||||||
for (entity, controller) in (&read_data.entities, &mut controllers).join() {
|
for (entity, controller) in (&read_data.entities, &mut controllers).join() {
|
||||||
@ -115,9 +108,12 @@ impl<'a> System<'a> for Sys {
|
|||||||
auxiliary_key,
|
auxiliary_key,
|
||||||
new_ability,
|
new_ability,
|
||||||
} => {
|
} => {
|
||||||
if let Some(mut active_abilities) = active_abilities.get_mut(entity) {
|
server_emitter.emit(ServerEvent::ChangeAbility {
|
||||||
active_abilities.change_ability(slot, auxiliary_key, new_ability);
|
entity,
|
||||||
}
|
slot,
|
||||||
|
auxiliary_key,
|
||||||
|
new_ability,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
client::Client,
|
client::Client,
|
||||||
comp::{
|
comp::{
|
||||||
|
ability,
|
||||||
agent::{Agent, AgentEvent, Sound, SoundKind},
|
agent::{Agent, AgentEvent, Sound, SoundKind},
|
||||||
skillset::SkillGroupKind,
|
skillset::SkillGroupKind,
|
||||||
BuffKind, BuffSource, PhysicsState,
|
BuffKind, BuffSource, PhysicsState,
|
||||||
@ -1260,3 +1261,26 @@ pub fn handle_entity_attacked_hook(server: &Server, entity: EcsEntity) {
|
|||||||
buff_change: buff::BuffChange::RemoveByKind(buff::BuffKind::Saturation),
|
buff_change: buff::BuffChange::RemoveByKind(buff::BuffKind::Saturation),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_change_ability(
|
||||||
|
server: &Server,
|
||||||
|
entity: EcsEntity,
|
||||||
|
slot: usize,
|
||||||
|
auxiliary_key: ability::AuxiliaryKey,
|
||||||
|
new_ability: ability::AuxiliaryAbility,
|
||||||
|
) {
|
||||||
|
let ecs = &server.state.ecs();
|
||||||
|
let inventories = ecs.read_storage::<comp::Inventory>();
|
||||||
|
let skill_sets = ecs.read_storage::<comp::SkillSet>();
|
||||||
|
|
||||||
|
if let Some(mut active_abilities) = ecs.write_storage::<comp::ActiveAbilities>().get_mut(entity)
|
||||||
|
{
|
||||||
|
active_abilities.change_ability(
|
||||||
|
slot,
|
||||||
|
auxiliary_key,
|
||||||
|
new_ability,
|
||||||
|
inventories.get(entity),
|
||||||
|
skill_sets.get(entity),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -6,10 +6,10 @@ use entity_creation::{
|
|||||||
handle_initialize_character, handle_loaded_character_data, handle_shockwave, handle_shoot,
|
handle_initialize_character, handle_loaded_character_data, handle_shockwave, handle_shoot,
|
||||||
};
|
};
|
||||||
use entity_manipulation::{
|
use entity_manipulation::{
|
||||||
handle_aura, handle_bonk, handle_buff, handle_combo_change, handle_delete, handle_destroy,
|
handle_aura, handle_bonk, handle_buff, handle_change_ability, handle_combo_change,
|
||||||
handle_energy_change, handle_entity_attacked_hook, handle_explosion, handle_health_change,
|
handle_delete, handle_destroy, handle_energy_change, handle_entity_attacked_hook,
|
||||||
handle_knockback, handle_land_on_ground, handle_parry, handle_poise, handle_respawn,
|
handle_explosion, handle_health_change, handle_knockback, handle_land_on_ground, handle_parry,
|
||||||
handle_teleport_to,
|
handle_poise, handle_respawn, handle_teleport_to,
|
||||||
};
|
};
|
||||||
use group_manip::handle_group;
|
use group_manip::handle_group;
|
||||||
use information::handle_site_info;
|
use information::handle_site_info;
|
||||||
@ -233,6 +233,12 @@ impl Server {
|
|||||||
ServerEvent::EntityAttackedHook { entity } => {
|
ServerEvent::EntityAttackedHook { entity } => {
|
||||||
handle_entity_attacked_hook(self, entity)
|
handle_entity_attacked_hook(self, entity)
|
||||||
},
|
},
|
||||||
|
ServerEvent::ChangeAbility {
|
||||||
|
entity,
|
||||||
|
slot,
|
||||||
|
auxiliary_key,
|
||||||
|
new_ability,
|
||||||
|
} => handle_change_ability(self, entity, slot, auxiliary_key, new_ability),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -780,7 +780,11 @@ impl<'a> Widget for Diary<'a> {
|
|||||||
for i in 0..MAX_ABILITIES {
|
for i in 0..MAX_ABILITIES {
|
||||||
let ability_id = self
|
let ability_id = self
|
||||||
.active_abilities
|
.active_abilities
|
||||||
.get_ability(AbilityInput::Auxiliary(i), Some(self.inventory))
|
.get_ability(
|
||||||
|
AbilityInput::Auxiliary(i),
|
||||||
|
Some(self.inventory),
|
||||||
|
Some(self.skill_set),
|
||||||
|
)
|
||||||
.ability_id(Some(self.inventory));
|
.ability_id(Some(self.inventory));
|
||||||
|
|
||||||
let image_size = 50.0;
|
let image_size = 50.0;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::hud::item_imgs::ItemKey;
|
use crate::hud::item_imgs::ItemKey;
|
||||||
use common::comp::inventory::item::Item;
|
use common::comp::{self, inventory::item::Item};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
@ -70,7 +70,14 @@ impl State {
|
|||||||
{
|
{
|
||||||
use common::comp::ability::AuxiliaryAbility;
|
use common::comp::ability::AuxiliaryAbility;
|
||||||
for ((i, ability), hotbar_slot) in active_abilities
|
for ((i, ability), hotbar_slot) in active_abilities
|
||||||
.iter_aux_abilities(client.inventories().get(client.entity()))
|
.auxiliary_set(
|
||||||
|
client.inventories().get(client.entity()),
|
||||||
|
client
|
||||||
|
.state()
|
||||||
|
.read_storage::<comp::SkillSet>()
|
||||||
|
.get(client.entity()),
|
||||||
|
)
|
||||||
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.zip(self.slots.iter_mut())
|
.zip(self.slots.iter_mut())
|
||||||
{
|
{
|
||||||
|
@ -601,14 +601,14 @@ impl<'a> Skillbar<'a> {
|
|||||||
|
|
||||||
// Helper
|
// Helper
|
||||||
let tooltip_text = |slot| {
|
let tooltip_text = |slot| {
|
||||||
let (hotbar, inventory, _, _, active_abilities, _) = content_source;
|
let (hotbar, inventory, _, skill_set, active_abilities, _) = content_source;
|
||||||
hotbar.get(slot).and_then(|content| match content {
|
hotbar.get(slot).and_then(|content| match content {
|
||||||
hotbar::SlotContents::Inventory(i, _) => inventory
|
hotbar::SlotContents::Inventory(i, _) => inventory
|
||||||
.get_by_hash(i)
|
.get_by_hash(i)
|
||||||
.map(|item| (item.name(), item.description())),
|
.map(|item| (item.name(), item.description())),
|
||||||
hotbar::SlotContents::Ability(i) => active_abilities
|
hotbar::SlotContents::Ability(i) => active_abilities
|
||||||
.iter_aux_abilities(Some(inventory))
|
.auxiliary_set(Some(inventory), Some(skill_set))
|
||||||
.nth(i)
|
.get(i)
|
||||||
.and_then(|a| Ability::from(*a).ability_id(Some(inventory)))
|
.and_then(|a| Ability::from(*a).ability_id(Some(inventory)))
|
||||||
.map(util::ability_description),
|
.map(util::ability_description),
|
||||||
})
|
})
|
||||||
|
@ -141,8 +141,8 @@ impl<'a> SlotKey<HotbarSource<'a>, HotbarImageSource<'a>> for HotbarSlot {
|
|||||||
},
|
},
|
||||||
hotbar::SlotContents::Ability(i) => {
|
hotbar::SlotContents::Ability(i) => {
|
||||||
let ability_id = active_abilities
|
let ability_id = active_abilities
|
||||||
.iter_aux_abilities(Some(inventory))
|
.auxiliary_set(Some(inventory), Some(skillset))
|
||||||
.nth(i)
|
.get(i)
|
||||||
.and_then(|a| Ability::from(*a).ability_id(Some(inventory)));
|
.and_then(|a| Ability::from(*a).ability_id(Some(inventory)));
|
||||||
|
|
||||||
ability_id
|
ability_id
|
||||||
|
Reference in New Issue
Block a user