mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Make all_available_abilities charstate-independent
+ Fix wrong index bug with Auxiliary abilities
This commit is contained in:
parent
06caf1fd31
commit
9b1d074b27
@ -216,11 +216,26 @@ impl ActiveAbilities {
|
|||||||
context_index,
|
context_index,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This function is an attempt to generalize ability handling
|
||||||
let inst_ability = |slot: EquipSlot, offhand: bool| {
|
let inst_ability = |slot: EquipSlot, offhand: bool| {
|
||||||
ability_set(slot).and_then(|abilities| {
|
ability_set(slot).and_then(|abilities| {
|
||||||
|
// We use AbilityInput here as an object to match on, which
|
||||||
|
// roughly corresponds to all needed data we need to know about
|
||||||
|
// ability.
|
||||||
use AbilityInput as I;
|
use AbilityInput as I;
|
||||||
|
|
||||||
let dispatched = match input {
|
// Also we don't provide `ability`, nor `ability_input` as an
|
||||||
|
// argument to the closure, and that wins us a bit of code
|
||||||
|
// duplication we would need to do otherwise, but it's
|
||||||
|
// important that we can and do re-create all needed Ability
|
||||||
|
// information here to make decisions.
|
||||||
|
//
|
||||||
|
// For example, we should't take `input` argument provided to
|
||||||
|
// activate_abilities, because in case of Auxiliary abilities,
|
||||||
|
// it has wrong index.
|
||||||
|
//
|
||||||
|
// We could alternatively just take `ability`, but it works too.
|
||||||
|
let dispatched = match ability.try_ability_set_key()? {
|
||||||
I::Guard => abilities.guard(Some(skill_set), context),
|
I::Guard => abilities.guard(Some(skill_set), context),
|
||||||
I::Primary => abilities.primary(Some(skill_set), context),
|
I::Primary => abilities.primary(Some(skill_set), context),
|
||||||
I::Secondary => abilities.secondary(Some(skill_set), context),
|
I::Secondary => abilities.secondary(Some(skill_set), context),
|
||||||
@ -297,55 +312,40 @@ impl ActiveAbilities {
|
|||||||
pub fn all_available_abilities(
|
pub fn all_available_abilities(
|
||||||
inv: Option<&Inventory>,
|
inv: Option<&Inventory>,
|
||||||
skill_set: Option<&SkillSet>,
|
skill_set: Option<&SkillSet>,
|
||||||
char_state: Option<&CharacterState>,
|
|
||||||
) -> Vec<AuxiliaryAbility> {
|
) -> Vec<AuxiliaryAbility> {
|
||||||
let source = AbilitySource::determine(char_state);
|
let mut ability_buff = vec![];
|
||||||
|
// Check if uses combo of two "equal" weapons
|
||||||
|
let paired = inv
|
||||||
|
.and_then(|inv| {
|
||||||
|
let a = inv.equipped(EquipSlot::ActiveMainhand)?;
|
||||||
|
let b = inv.equipped(EquipSlot::ActiveOffhand)?;
|
||||||
|
|
||||||
match source {
|
if let (ItemKind::Tool(tool_a), ItemKind::Tool(tool_b)) = (&*a.kind(), &*b.kind()) {
|
||||||
AbilitySource::Weapons => {
|
Some((a.ability_spec(), tool_a.kind, b.ability_spec(), tool_b.kind))
|
||||||
// Check if uses combo of two "equal" weapons
|
|
||||||
let paired = inv
|
|
||||||
.and_then(|inv| {
|
|
||||||
let a = inv.equipped(EquipSlot::ActiveMainhand)?;
|
|
||||||
let b = inv.equipped(EquipSlot::ActiveOffhand)?;
|
|
||||||
|
|
||||||
if let (ItemKind::Tool(tool_a), ItemKind::Tool(tool_b)) =
|
|
||||||
(&*a.kind(), &*b.kind())
|
|
||||||
{
|
|
||||||
Some((a.ability_spec(), tool_a.kind, b.ability_spec(), tool_b.kind))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.is_some_and(|(a_spec, a_kind, b_spec, b_kind)| {
|
|
||||||
(a_spec, a_kind) == (b_spec, b_kind)
|
|
||||||
});
|
|
||||||
|
|
||||||
// If equal, just take the first
|
|
||||||
if paired {
|
|
||||||
Self::iter_available_abilities_on(inv, skill_set, EquipSlot::ActiveMainhand)
|
|
||||||
.map(AuxiliaryAbility::MainWeapon)
|
|
||||||
.collect()
|
|
||||||
} else {
|
} else {
|
||||||
Self::iter_available_abilities_on(inv, skill_set, EquipSlot::ActiveMainhand)
|
None
|
||||||
.map(AuxiliaryAbility::MainWeapon)
|
|
||||||
.chain(
|
|
||||||
Self::iter_available_abilities_on(
|
|
||||||
inv,
|
|
||||||
skill_set,
|
|
||||||
EquipSlot::ActiveOffhand,
|
|
||||||
)
|
|
||||||
.map(AuxiliaryAbility::OffWeapon),
|
|
||||||
)
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
},
|
})
|
||||||
AbilitySource::Glider => {
|
.is_some_and(|(a_spec, a_kind, b_spec, b_kind)| (a_spec, a_kind) == (b_spec, b_kind));
|
||||||
Self::iter_available_abilities_on(inv, skill_set, EquipSlot::Glider)
|
|
||||||
.map(AuxiliaryAbility::Glider)
|
// Push main weapon abilities
|
||||||
.collect()
|
Self::iter_available_abilities_on(inv, skill_set, EquipSlot::ActiveMainhand)
|
||||||
},
|
.map(AuxiliaryAbility::MainWeapon)
|
||||||
|
.for_each(|a| ability_buff.push(a));
|
||||||
|
|
||||||
|
// Push secondary weapon abilities, if different
|
||||||
|
// If equal, just take the first
|
||||||
|
if !paired {
|
||||||
|
Self::iter_available_abilities_on(inv, skill_set, EquipSlot::ActiveOffhand)
|
||||||
|
.map(AuxiliaryAbility::OffWeapon)
|
||||||
|
.for_each(|a| ability_buff.push(a));
|
||||||
}
|
}
|
||||||
|
// Push glider abilities
|
||||||
|
Self::iter_available_abilities_on(inv, skill_set, EquipSlot::Glider)
|
||||||
|
.map(AuxiliaryAbility::Glider)
|
||||||
|
.for_each(|a| ability_buff.push(a));
|
||||||
|
|
||||||
|
ability_buff
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_ability_set<'a>(
|
fn default_ability_set<'a>(
|
||||||
@ -370,7 +370,7 @@ impl ActiveAbilities {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum AbilityInput {
|
pub enum AbilityInput {
|
||||||
Guard,
|
Guard,
|
||||||
Primary,
|
Primary,
|
||||||
@ -394,9 +394,11 @@ pub enum Ability {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Ability {
|
impl Ability {
|
||||||
// Reverses input this ability would have originated from
|
|
||||||
// Used for generic ability dispatch (inst_ability) in this file
|
// Used for generic ability dispatch (inst_ability) in this file
|
||||||
fn try_input(&self) -> Option<AbilityInput> {
|
//
|
||||||
|
// It does use AbilityInput to avoid creating just another enum, but it is
|
||||||
|
// semantically different.
|
||||||
|
fn try_ability_set_key(&self) -> Option<AbilityInput> {
|
||||||
let input = match self {
|
let input = match self {
|
||||||
Self::ToolGuard => AbilityInput::Guard,
|
Self::ToolGuard => AbilityInput::Guard,
|
||||||
Self::ToolPrimary => AbilityInput::Primary,
|
Self::ToolPrimary => AbilityInput::Primary,
|
||||||
@ -439,7 +441,7 @@ impl Ability {
|
|||||||
ability_set(slot).and_then(|abilities| {
|
ability_set(slot).and_then(|abilities| {
|
||||||
use AbilityInput as I;
|
use AbilityInput as I;
|
||||||
|
|
||||||
let dispatched = match self.try_input()? {
|
let dispatched = match self.try_ability_set_key()? {
|
||||||
I::Guard => abilities.guard(skill_set, context),
|
I::Guard => abilities.guard(skill_set, context),
|
||||||
I::Primary => abilities.primary(skill_set, context),
|
I::Primary => abilities.primary(skill_set, context),
|
||||||
I::Secondary => abilities.secondary(skill_set, context),
|
I::Secondary => abilities.secondary(skill_set, context),
|
||||||
@ -447,9 +449,8 @@ impl Ability {
|
|||||||
I::Movement => return None,
|
I::Movement => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
dispatched
|
dispatched.map(|(a, _)| a.id.as_str()).or_else(|| {
|
||||||
.map(|(a, _)| a.id.as_str())
|
match self.try_ability_set_key()? {
|
||||||
.or_else(|| match self.try_input()? {
|
|
||||||
I::Guard => abilities
|
I::Guard => abilities
|
||||||
.guard
|
.guard
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -458,7 +459,8 @@ impl Ability {
|
|||||||
I::Secondary => contextual_id(Some(&abilities.secondary)),
|
I::Secondary => contextual_id(Some(&abilities.secondary)),
|
||||||
I::Auxiliary(index) => contextual_id(abilities.abilities.get(index)),
|
I::Auxiliary(index) => contextual_id(abilities.abilities.get(index)),
|
||||||
I::Movement => None,
|
I::Movement => None,
|
||||||
})
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -553,7 +555,7 @@ impl SpecifiedAbility {
|
|||||||
ability_set(slot).and_then(|abilities| {
|
ability_set(slot).and_then(|abilities| {
|
||||||
use AbilityInput as I;
|
use AbilityInput as I;
|
||||||
|
|
||||||
let dispatched = match self.ability.try_input()? {
|
let dispatched = match self.ability.try_ability_set_key()? {
|
||||||
I::Guard => abilities.guard.as_ref(),
|
I::Guard => abilities.guard.as_ref(),
|
||||||
I::Primary => Some(&abilities.primary),
|
I::Primary => Some(&abilities.primary),
|
||||||
I::Secondary => Some(&abilities.secondary),
|
I::Secondary => Some(&abilities.secondary),
|
||||||
|
@ -924,7 +924,6 @@ impl<'a> Widget for Diary<'a> {
|
|||||||
let abilities: Vec<_> = ActiveAbilities::all_available_abilities(
|
let abilities: Vec<_> = ActiveAbilities::all_available_abilities(
|
||||||
Some(self.inventory),
|
Some(self.inventory),
|
||||||
Some(self.skill_set),
|
Some(self.skill_set),
|
||||||
Some(self.char_state),
|
|
||||||
)
|
)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|a| {
|
.map(|a| {
|
||||||
|
Loading…
Reference in New Issue
Block a user