mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Fixes to animations and making ability that the animation system thinks is being used more correct
This commit is contained in:
parent
38fb7b8cd5
commit
1cc99c9c4a
@ -6,7 +6,7 @@ FinisherMelee(
|
||||
melee_constructor: (
|
||||
kind: Slash(
|
||||
damage: 60,
|
||||
poise: 100,
|
||||
poise: 20,
|
||||
knockback: 0,
|
||||
energy_regen: 0,
|
||||
),
|
||||
|
@ -6,7 +6,7 @@ FinisherMelee(
|
||||
melee_constructor: (
|
||||
kind: Slash(
|
||||
damage: 75,
|
||||
poise: 100,
|
||||
poise: 25,
|
||||
knockback: 0,
|
||||
energy_regen: 0,
|
||||
),
|
||||
|
@ -9,8 +9,9 @@ ItemDef(
|
||||
data: (
|
||||
strength: 0.4,
|
||||
duration: Some(20),
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
secondary_duration: Some(5),
|
||||
),
|
||||
cat_ids: [RemoveOnAttack],
|
||||
)),
|
||||
|
||||
])
|
||||
|
@ -9,8 +9,9 @@ ItemDef(
|
||||
data: (
|
||||
strength: 0.4,
|
||||
duration: Some(20),
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
secondary_duration: Some(5),
|
||||
),
|
||||
cat_ids: [RemoveOnAttack],
|
||||
)),
|
||||
|
||||
])
|
||||
|
@ -9,8 +9,8 @@ ItemDef(
|
||||
data: (
|
||||
strength: 0.4,
|
||||
duration: Some(20),
|
||||
),
|
||||
cat_ids: [Natural],
|
||||
),
|
||||
cat_ids: [RemoveOnAttack],
|
||||
)),
|
||||
|
||||
])
|
||||
|
@ -1172,7 +1172,6 @@ impl CombatBuff {
|
||||
BuffData::new(
|
||||
self.strength.to_strength(damage, strength_modifier),
|
||||
Some(Secs(self.dur_secs as f64)),
|
||||
None,
|
||||
),
|
||||
Vec::new(),
|
||||
source,
|
||||
|
@ -6,7 +6,7 @@ use crate::{
|
||||
character_state::AttackFilters,
|
||||
inventory::{
|
||||
item::{
|
||||
tool::{AbilityContext, AbilityKind, Stats, ToolKind},
|
||||
tool::{AbilityContext, AbilityItem, AbilityKind, Stats, ToolKind},
|
||||
ItemKind,
|
||||
},
|
||||
slot::EquipSlot,
|
||||
@ -149,7 +149,7 @@ impl ActiveAbilities {
|
||||
char_state: Option<&CharacterState>,
|
||||
contexts: &[AbilityContext],
|
||||
// bool is from_offhand
|
||||
) -> Option<(CharacterAbility, bool)> {
|
||||
) -> Option<(CharacterAbility, bool, SpecifiedAbility)> {
|
||||
let ability = self.get_ability(input, inv, Some(skill_set));
|
||||
|
||||
let ability_set = |equip_slot| {
|
||||
@ -167,63 +167,116 @@ impl ActiveAbilities {
|
||||
ability.adjusted_by_skills(skill_set, tool_kind)
|
||||
};
|
||||
|
||||
let spec_ability = |context_index| SpecifiedAbility {
|
||||
ability,
|
||||
context_index,
|
||||
};
|
||||
|
||||
match ability {
|
||||
Ability::ToolGuard => ability_set(EquipSlot::ActiveMainhand)
|
||||
.and_then(|abilities| {
|
||||
abilities
|
||||
.guard(Some(skill_set), contexts)
|
||||
.map(|a| a.ability.clone())
|
||||
.map(|(a, i)| (a.ability.clone(), i))
|
||||
})
|
||||
.map(|(ability, i)| {
|
||||
(
|
||||
scale_ability(ability, EquipSlot::ActiveMainhand),
|
||||
true,
|
||||
spec_ability(i),
|
||||
)
|
||||
})
|
||||
.map(|ability| (scale_ability(ability, EquipSlot::ActiveMainhand), true))
|
||||
.or_else(|| {
|
||||
ability_set(EquipSlot::ActiveOffhand)
|
||||
.and_then(|abilities| {
|
||||
abilities
|
||||
.secondary(Some(skill_set), contexts)
|
||||
.map(|a| a.ability.clone())
|
||||
.guard(Some(skill_set), contexts)
|
||||
.map(|(a, i)| (a.ability.clone(), i))
|
||||
})
|
||||
.map(|(ability, i)| {
|
||||
(
|
||||
scale_ability(ability, EquipSlot::ActiveOffhand),
|
||||
false,
|
||||
spec_ability(i),
|
||||
)
|
||||
})
|
||||
.map(|ability| (scale_ability(ability, EquipSlot::ActiveOffhand), false))
|
||||
}),
|
||||
Ability::ToolPrimary => ability_set(EquipSlot::ActiveMainhand)
|
||||
.and_then(|abilities| {
|
||||
abilities
|
||||
.primary(Some(skill_set), contexts)
|
||||
.map(|a| a.ability.clone())
|
||||
.map(|(a, i)| (a.ability.clone(), i))
|
||||
})
|
||||
.map(|ability| (scale_ability(ability, EquipSlot::ActiveMainhand), false)),
|
||||
.map(|(ability, i)| {
|
||||
(
|
||||
scale_ability(ability, EquipSlot::ActiveMainhand),
|
||||
false,
|
||||
spec_ability(i),
|
||||
)
|
||||
}),
|
||||
Ability::ToolSecondary => ability_set(EquipSlot::ActiveOffhand)
|
||||
.and_then(|abilities| {
|
||||
abilities
|
||||
.secondary(Some(skill_set), contexts)
|
||||
.map(|a| a.ability.clone())
|
||||
.map(|(a, i)| (a.ability.clone(), i))
|
||||
})
|
||||
.map(|(ability, i)| {
|
||||
(
|
||||
scale_ability(ability, EquipSlot::ActiveOffhand),
|
||||
true,
|
||||
spec_ability(i),
|
||||
)
|
||||
})
|
||||
.map(|ability| (scale_ability(ability, EquipSlot::ActiveOffhand), true))
|
||||
.or_else(|| {
|
||||
ability_set(EquipSlot::ActiveMainhand)
|
||||
.and_then(|abilities| {
|
||||
abilities
|
||||
.secondary(Some(skill_set), contexts)
|
||||
.map(|a| a.ability.clone())
|
||||
.map(|(a, i)| (a.ability.clone(), i))
|
||||
})
|
||||
.map(|(ability, i)| {
|
||||
(
|
||||
scale_ability(ability, EquipSlot::ActiveMainhand),
|
||||
false,
|
||||
spec_ability(i),
|
||||
)
|
||||
})
|
||||
.map(|ability| (scale_ability(ability, EquipSlot::ActiveMainhand), false))
|
||||
}),
|
||||
Ability::SpeciesMovement => matches!(body, Some(Body::Humanoid(_)))
|
||||
.then(|| CharacterAbility::default_roll(char_state))
|
||||
.map(|ability| (ability.adjusted_by_skills(skill_set, None), false)),
|
||||
.map(|ability| {
|
||||
(
|
||||
ability.adjusted_by_skills(skill_set, None),
|
||||
false,
|
||||
spec_ability(None),
|
||||
)
|
||||
}),
|
||||
Ability::MainWeaponAux(index) => ability_set(EquipSlot::ActiveMainhand)
|
||||
.and_then(|abilities| {
|
||||
abilities
|
||||
.auxiliary(index, Some(skill_set), contexts)
|
||||
.map(|a| a.ability.clone())
|
||||
.map(|(a, i)| (a.ability.clone(), i))
|
||||
})
|
||||
.map(|ability| (scale_ability(ability, EquipSlot::ActiveMainhand), false)),
|
||||
.map(|(ability, i)| {
|
||||
(
|
||||
scale_ability(ability, EquipSlot::ActiveMainhand),
|
||||
false,
|
||||
spec_ability(i),
|
||||
)
|
||||
}),
|
||||
Ability::OffWeaponAux(index) => ability_set(EquipSlot::ActiveOffhand)
|
||||
.and_then(|abilities| {
|
||||
abilities
|
||||
.auxiliary(index, Some(skill_set), contexts)
|
||||
.map(|a| a.ability.clone())
|
||||
.map(|(a, i)| (a.ability.clone(), i))
|
||||
})
|
||||
.map(|ability| (scale_ability(ability, EquipSlot::ActiveOffhand), true)),
|
||||
.map(|(ability, i)| {
|
||||
(
|
||||
scale_ability(ability, EquipSlot::ActiveOffhand),
|
||||
true,
|
||||
spec_ability(i),
|
||||
)
|
||||
}),
|
||||
Ability::Empty => None,
|
||||
}
|
||||
}
|
||||
@ -318,7 +371,7 @@ impl Ability {
|
||||
.and_then(|abilities| {
|
||||
abilities
|
||||
.guard(skillset, contexts)
|
||||
.map(|a| a.id.as_str())
|
||||
.map(|a| a.0.id.as_str())
|
||||
.or_else(|| {
|
||||
abilities
|
||||
.guard
|
||||
@ -330,7 +383,7 @@ impl Ability {
|
||||
ability_set(EquipSlot::ActiveOffhand).and_then(|abilities| {
|
||||
abilities
|
||||
.guard(skillset, contexts)
|
||||
.map(|a| a.id.as_str())
|
||||
.map(|a| a.0.id.as_str())
|
||||
.or_else(|| {
|
||||
abilities
|
||||
.guard
|
||||
@ -342,21 +395,21 @@ impl Ability {
|
||||
Ability::ToolPrimary => ability_set(EquipSlot::ActiveMainhand).and_then(|abilities| {
|
||||
abilities
|
||||
.primary(skillset, contexts)
|
||||
.map(|a| a.id.as_str())
|
||||
.map(|a| a.0.id.as_str())
|
||||
.or_else(|| contextual_id(Some(&abilities.primary)))
|
||||
}),
|
||||
Ability::ToolSecondary => ability_set(EquipSlot::ActiveOffhand)
|
||||
.and_then(|abilities| {
|
||||
abilities
|
||||
.secondary(skillset, contexts)
|
||||
.map(|a| a.id.as_str())
|
||||
.map(|a| a.0.id.as_str())
|
||||
.or_else(|| contextual_id(Some(&abilities.secondary)))
|
||||
})
|
||||
.or_else(|| {
|
||||
ability_set(EquipSlot::ActiveMainhand).and_then(|abilities| {
|
||||
abilities
|
||||
.secondary(skillset, contexts)
|
||||
.map(|a| a.id.as_str())
|
||||
.map(|a| a.0.id.as_str())
|
||||
.or_else(|| contextual_id(Some(&abilities.secondary)))
|
||||
})
|
||||
}),
|
||||
@ -365,7 +418,7 @@ impl Ability {
|
||||
ability_set(EquipSlot::ActiveMainhand).and_then(|abilities| {
|
||||
abilities
|
||||
.auxiliary(index, skillset, contexts)
|
||||
.map(|a| a.id.as_str())
|
||||
.map(|a| a.0.id.as_str())
|
||||
.or_else(|| contextual_id(abilities.abilities.get(index)))
|
||||
})
|
||||
},
|
||||
@ -373,7 +426,7 @@ impl Ability {
|
||||
ability_set(EquipSlot::ActiveOffhand).and_then(|abilities| {
|
||||
abilities
|
||||
.auxiliary(index, skillset, contexts)
|
||||
.map(|a| a.id.as_str())
|
||||
.map(|a| a.0.id.as_str())
|
||||
.or_else(|| contextual_id(abilities.abilities.get(index)))
|
||||
})
|
||||
},
|
||||
@ -396,6 +449,59 @@ impl From<GuardAbility> for Ability {
|
||||
}
|
||||
}
|
||||
|
||||
// Only use for specifying to the front end what ability is being used, do not
|
||||
// actually use it for any logic in common or server
|
||||
#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
pub struct SpecifiedAbility {
|
||||
pub ability: Ability,
|
||||
pub context_index: Option<usize>,
|
||||
}
|
||||
|
||||
impl SpecifiedAbility {
|
||||
pub fn ability_id(self, inv: Option<&Inventory>) -> Option<&str> {
|
||||
let ability_set = |equip_slot| {
|
||||
inv.and_then(|inv| inv.equipped(equip_slot))
|
||||
.map(|i| &i.item_config_expect().abilities)
|
||||
};
|
||||
|
||||
fn ability_id(spec_ability: SpecifiedAbility, ability: &AbilityKind<AbilityItem>) -> &str {
|
||||
match ability {
|
||||
AbilityKind::Simple(_, a) => a.id.as_str(),
|
||||
AbilityKind::Contextualized {
|
||||
pseudo_id,
|
||||
abilities,
|
||||
} => spec_ability
|
||||
.context_index
|
||||
.and_then(|i| abilities.get(i))
|
||||
.map_or(pseudo_id.as_str(), |(_, (_, a))| a.id.as_str()),
|
||||
}
|
||||
}
|
||||
|
||||
match self.ability {
|
||||
Ability::ToolPrimary => ability_set(EquipSlot::ActiveMainhand)
|
||||
.map(|abilities| ability_id(self, &abilities.primary)),
|
||||
Ability::ToolSecondary => ability_set(EquipSlot::ActiveOffhand)
|
||||
.map(|abilities| ability_id(self, &abilities.secondary))
|
||||
.or_else(|| {
|
||||
ability_set(EquipSlot::ActiveMainhand)
|
||||
.map(|abilities| ability_id(self, &abilities.secondary))
|
||||
}),
|
||||
Ability::ToolGuard => ability_set(EquipSlot::ActiveMainhand)
|
||||
.and_then(|abilities| abilities.guard.as_ref().map(|a| ability_id(self, a)))
|
||||
.or_else(|| {
|
||||
ability_set(EquipSlot::ActiveOffhand)
|
||||
.and_then(|abilities| abilities.guard.as_ref().map(|a| ability_id(self, a)))
|
||||
}),
|
||||
Ability::SpeciesMovement => None, // TODO: Make not None
|
||||
Ability::MainWeaponAux(index) => ability_set(EquipSlot::ActiveMainhand)
|
||||
.and_then(|abilities| abilities.abilities.get(index).map(|a| ability_id(self, a))),
|
||||
Ability::OffWeaponAux(index) => ability_set(EquipSlot::ActiveOffhand)
|
||||
.and_then(|abilities| abilities.abilities.get(index).map(|a| ability_id(self, a))),
|
||||
Ability::Empty => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
|
||||
pub enum PrimaryAbility {
|
||||
Tool,
|
||||
|
@ -158,11 +158,7 @@ impl AuraBuffConstructor {
|
||||
) -> Aura {
|
||||
let aura_kind = AuraKind::Buff {
|
||||
kind: self.kind,
|
||||
data: BuffData {
|
||||
strength: self.strength,
|
||||
duration: self.duration,
|
||||
delay: None,
|
||||
},
|
||||
data: BuffData::new(self.strength, self.duration),
|
||||
category: self.category,
|
||||
source: BuffSource::Character { by: *uid },
|
||||
};
|
||||
|
@ -74,6 +74,12 @@ pub enum BuffKind {
|
||||
/// Provides immunity to burning and increases movement speed in lava.
|
||||
/// Movement speed increases linearly with strength, 1.0 is a 100% increase.
|
||||
// SalamanderAspect, TODO: Readd in second dwarven mine MR
|
||||
/// Inflict burning on your attack
|
||||
Flame,
|
||||
/// Inflict frost on your attack
|
||||
Frigid,
|
||||
/// Gain Lifesteal on your attack
|
||||
Lifesteal,
|
||||
/// Guarantees that the next attack is a critical hit. Does this kind of
|
||||
/// hackily by adding 100% to the crit, will need to be adjusted if we ever
|
||||
/// allow double crits instead of treating 100 as a ceiling.
|
||||
@ -118,12 +124,6 @@ pub enum BuffKind {
|
||||
PotionSickness,
|
||||
// Changed into another body.
|
||||
Polymorphed(Body),
|
||||
// Inflict burning on your attack
|
||||
Flame,
|
||||
// Inflict frost on your attack
|
||||
Frigid,
|
||||
// Gain Lifesteal on your attack
|
||||
Lifesteal,
|
||||
}
|
||||
|
||||
impl BuffKind {
|
||||
@ -314,8 +314,8 @@ impl BuffKind {
|
||||
None,
|
||||
CombatEffect::Buff(CombatBuff {
|
||||
kind: BuffKind::Burning,
|
||||
dur_secs: 5.0,
|
||||
strength: CombatBuffStrength::DamageFraction(0.2),
|
||||
dur_secs: data.secondary_duration.map_or(5.0, |dur| dur.0 as f32),
|
||||
strength: CombatBuffStrength::DamageFraction(data.strength),
|
||||
chance: 1.0,
|
||||
}),
|
||||
))],
|
||||
@ -323,14 +323,14 @@ impl BuffKind {
|
||||
None,
|
||||
CombatEffect::Buff(CombatBuff {
|
||||
kind: BuffKind::Frozen,
|
||||
dur_secs: 5.0,
|
||||
strength: CombatBuffStrength::DamageFraction(0.2),
|
||||
dur_secs: data.secondary_duration.map_or(5.0, |dur| dur.0 as f32),
|
||||
strength: CombatBuffStrength::DamageFraction(data.strength),
|
||||
chance: 1.0,
|
||||
}),
|
||||
))],
|
||||
BuffKind::Lifesteal => vec![BuffEffect::BuffOnHit(AttackEffect::new(
|
||||
None,
|
||||
CombatEffect::Lifesteal(0.2),
|
||||
CombatEffect::Lifesteal(data.strength),
|
||||
))],
|
||||
/*BuffKind::SalamanderAspect => vec![
|
||||
BuffEffect::BuffImmunity(BuffKind::Burning),
|
||||
@ -358,20 +358,34 @@ impl BuffKind {
|
||||
|
||||
// Struct used to store data relevant to a buff
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct BuffData {
|
||||
pub strength: f32,
|
||||
pub duration: Option<Secs>,
|
||||
pub delay: Option<Secs>,
|
||||
// Used for buffs that have rider buffs (e.g. Flame, Frigid)
|
||||
pub secondary_duration: Option<Secs>,
|
||||
}
|
||||
|
||||
impl BuffData {
|
||||
pub fn new(strength: f32, duration: Option<Secs>, delay: Option<Secs>) -> Self {
|
||||
pub fn new(strength: f32, duration: Option<Secs>) -> Self {
|
||||
Self {
|
||||
strength,
|
||||
duration,
|
||||
delay,
|
||||
delay: None,
|
||||
secondary_duration: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_delay(mut self, delay: Secs) -> Self {
|
||||
self.delay = Some(delay);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_secondary_duration(mut self, sec_dur: Secs) -> Self {
|
||||
self.secondary_duration = Some(sec_dur);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// De/buff category ID.
|
||||
|
@ -342,7 +342,11 @@ impl<T> AbilityKind<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ability(&self, skillset: Option<&SkillSet>, contexts: &[AbilityContext]) -> Option<&T> {
|
||||
pub fn ability(
|
||||
&self,
|
||||
skillset: Option<&SkillSet>,
|
||||
contexts: &[AbilityContext],
|
||||
) -> Option<(&T, Option<usize>)> {
|
||||
let unlocked = |s: Option<Skill>, a| {
|
||||
// If there is a skill requirement and the skillset does not contain the
|
||||
// required skill, return None
|
||||
@ -351,18 +355,21 @@ impl<T> AbilityKind<T> {
|
||||
};
|
||||
|
||||
match self {
|
||||
AbilityKind::Simple(s, a) => unlocked(*s, a),
|
||||
AbilityKind::Simple(s, a) => unlocked(*s, a).map(|a| (a, None)),
|
||||
AbilityKind::Contextualized {
|
||||
pseudo_id: _,
|
||||
abilities,
|
||||
} => abilities
|
||||
.iter()
|
||||
.filter_map(|(req_contexts, (s, a))| unlocked(*s, a).map(|a| (req_contexts, a)))
|
||||
.find_map(|(req_contexts, a)| {
|
||||
.enumerate()
|
||||
.filter_map(|(i, (req_contexts, (s, a)))| {
|
||||
unlocked(*s, a).map(|a| (i, (req_contexts, a)))
|
||||
})
|
||||
.find_map(|(i, (req_contexts, a))| {
|
||||
req_contexts
|
||||
.iter()
|
||||
.all(|req| req.fulfilled_by(contexts))
|
||||
.then_some(a)
|
||||
.then_some((a, Some(i)))
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -465,13 +472,21 @@ impl<T> AbilitySet<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn guard(&self, skillset: Option<&SkillSet>, contexts: &[AbilityContext]) -> Option<&T> {
|
||||
pub fn guard(
|
||||
&self,
|
||||
skillset: Option<&SkillSet>,
|
||||
contexts: &[AbilityContext],
|
||||
) -> Option<(&T, Option<usize>)> {
|
||||
self.guard
|
||||
.as_ref()
|
||||
.and_then(|g| g.ability(skillset, contexts))
|
||||
}
|
||||
|
||||
pub fn primary(&self, skillset: Option<&SkillSet>, contexts: &[AbilityContext]) -> Option<&T> {
|
||||
pub fn primary(
|
||||
&self,
|
||||
skillset: Option<&SkillSet>,
|
||||
contexts: &[AbilityContext],
|
||||
) -> Option<(&T, Option<usize>)> {
|
||||
self.primary.ability(skillset, contexts)
|
||||
}
|
||||
|
||||
@ -479,7 +494,7 @@ impl<T> AbilitySet<T> {
|
||||
&self,
|
||||
skillset: Option<&SkillSet>,
|
||||
contexts: &[AbilityContext],
|
||||
) -> Option<&T> {
|
||||
) -> Option<(&T, Option<usize>)> {
|
||||
self.secondary.ability(skillset, contexts)
|
||||
}
|
||||
|
||||
@ -488,7 +503,7 @@ impl<T> AbilitySet<T> {
|
||||
index: usize,
|
||||
skillset: Option<&SkillSet>,
|
||||
contexts: &[AbilityContext],
|
||||
) -> Option<&T> {
|
||||
) -> Option<(&T, Option<usize>)> {
|
||||
self.abilities
|
||||
.get(index)
|
||||
.and_then(|a| a.ability(skillset, contexts))
|
||||
|
@ -82,11 +82,10 @@ impl CharacterBehavior for Data {
|
||||
// Creates buff
|
||||
let buff = Buff::new(
|
||||
self.static_data.buff_kind,
|
||||
BuffData {
|
||||
strength: self.static_data.buff_strength * scaling_factor,
|
||||
duration: self.static_data.buff_duration,
|
||||
delay: None,
|
||||
},
|
||||
BuffData::new(
|
||||
self.static_data.buff_strength * scaling_factor,
|
||||
self.static_data.buff_duration,
|
||||
),
|
||||
Vec::new(),
|
||||
BuffSource::Character { by: *data.uid },
|
||||
*data.time,
|
||||
|
@ -2,7 +2,7 @@ use crate::{
|
||||
astar::Astar,
|
||||
combat,
|
||||
comp::{
|
||||
ability::{Ability, AbilityInitEvent, AbilityInput, AbilityMeta, Capability, Stance},
|
||||
ability::{AbilityInitEvent, AbilityMeta, Capability, SpecifiedAbility, Stance},
|
||||
arthropod, biped_large, biped_small, bird_medium,
|
||||
character_state::OutputEvents,
|
||||
controller::InventoryManip,
|
||||
@ -1206,7 +1206,7 @@ fn handle_ability(
|
||||
) -> bool {
|
||||
let contexts = AbilityContext::from(data.stance, data.inventory, data.combo);
|
||||
if let Some(ability_input) = input.into() {
|
||||
if let Some((ability, from_offhand)) = data
|
||||
if let Some((ability, from_offhand, spec_ability)) = data
|
||||
.active_abilities
|
||||
.and_then(|a| {
|
||||
a.activate_ability(
|
||||
@ -1218,11 +1218,17 @@ fn handle_ability(
|
||||
&contexts,
|
||||
)
|
||||
})
|
||||
.filter(|(ability, _)| ability.requirements_paid(data, update))
|
||||
.filter(|(ability, _, _)| ability.requirements_paid(data, update))
|
||||
{
|
||||
update.character = CharacterState::from((
|
||||
&ability,
|
||||
AbilityInfo::from_input(data, from_offhand, input, ability.ability_meta()),
|
||||
AbilityInfo::new(
|
||||
data,
|
||||
from_offhand,
|
||||
input,
|
||||
Some(spec_ability),
|
||||
ability.ability_meta(),
|
||||
),
|
||||
data,
|
||||
));
|
||||
if let Some(init_event) = ability.ability_meta().init_event {
|
||||
@ -1508,14 +1514,15 @@ pub struct AbilityInfo {
|
||||
pub input: InputKind,
|
||||
pub input_attr: Option<InputAttr>,
|
||||
pub ability_meta: AbilityMeta,
|
||||
pub ability: Option<Ability>,
|
||||
pub ability: Option<SpecifiedAbility>,
|
||||
}
|
||||
|
||||
impl AbilityInfo {
|
||||
pub fn from_input(
|
||||
pub fn new(
|
||||
data: &JoinData<'_>,
|
||||
from_offhand: bool,
|
||||
input: InputKind,
|
||||
ability: Option<SpecifiedAbility>,
|
||||
ability_meta: AbilityMeta,
|
||||
) -> Self {
|
||||
let tool_data = if from_offhand {
|
||||
@ -1529,9 +1536,6 @@ impl AbilityInfo {
|
||||
Some(HandInfo::from_main_tool(hands, from_offhand)),
|
||||
)
|
||||
});
|
||||
let ability = Option::<AbilityInput>::from(input)
|
||||
.zip(data.active_abilities)
|
||||
.map(|(i, a)| a.get_ability(i, data.inventory, Some(data.skill_set)));
|
||||
|
||||
Self {
|
||||
tool,
|
||||
|
@ -142,7 +142,7 @@ impl<'a> System<'a> for Sys {
|
||||
entity,
|
||||
buff_change: BuffChange::Add(Buff::new(
|
||||
BuffKind::Ensnared,
|
||||
BuffData::new(1.0, Some(Secs(1.0)), None),
|
||||
BuffData::new(1.0, Some(Secs(1.0))),
|
||||
Vec::new(),
|
||||
BuffSource::World,
|
||||
*read_data.time,
|
||||
@ -160,7 +160,7 @@ impl<'a> System<'a> for Sys {
|
||||
entity,
|
||||
buff_change: BuffChange::Add(Buff::new(
|
||||
BuffKind::Bleeding,
|
||||
BuffData::new(1.0, Some(Secs(6.0)), None),
|
||||
BuffData::new(1.0, Some(Secs(6.0))),
|
||||
Vec::new(),
|
||||
BuffSource::World,
|
||||
*read_data.time,
|
||||
@ -178,7 +178,7 @@ impl<'a> System<'a> for Sys {
|
||||
entity,
|
||||
buff_change: BuffChange::Add(Buff::new(
|
||||
BuffKind::Bleeding,
|
||||
BuffData::new(5.0, Some(Secs(3.0)), None),
|
||||
BuffData::new(5.0, Some(Secs(3.0))),
|
||||
Vec::new(),
|
||||
BuffSource::World,
|
||||
*read_data.time,
|
||||
@ -196,7 +196,7 @@ impl<'a> System<'a> for Sys {
|
||||
entity,
|
||||
buff_change: BuffChange::Add(Buff::new(
|
||||
BuffKind::Burning,
|
||||
BuffData::new(10.0, None, None),
|
||||
BuffData::new(10.0, None),
|
||||
Vec::new(),
|
||||
BuffSource::World,
|
||||
*read_data.time,
|
||||
@ -214,7 +214,7 @@ impl<'a> System<'a> for Sys {
|
||||
entity,
|
||||
buff_change: BuffChange::Add(Buff::new(
|
||||
BuffKind::Bleeding,
|
||||
BuffData::new(15.0, Some(Secs(0.1)), None),
|
||||
BuffData::new(15.0, Some(Secs(0.1))),
|
||||
Vec::new(),
|
||||
BuffSource::World,
|
||||
*read_data.time,
|
||||
@ -227,7 +227,7 @@ impl<'a> System<'a> for Sys {
|
||||
entity,
|
||||
buff_change: BuffChange::Add(Buff::new(
|
||||
BuffKind::Frozen,
|
||||
BuffData::new(0.2, Some(Secs(1.0)), None),
|
||||
BuffData::new(0.2, Some(Secs(1.0))),
|
||||
Vec::new(),
|
||||
BuffSource::World,
|
||||
*read_data.time,
|
||||
@ -245,7 +245,7 @@ impl<'a> System<'a> for Sys {
|
||||
entity,
|
||||
buff_change: BuffChange::Add(Buff::new(
|
||||
BuffKind::Burning,
|
||||
BuffData::new(20.0, None, None),
|
||||
BuffData::new(20.0, None),
|
||||
Vec::new(),
|
||||
BuffSource::World,
|
||||
*read_data.time,
|
||||
@ -266,7 +266,7 @@ impl<'a> System<'a> for Sys {
|
||||
entity,
|
||||
buff_change: BuffChange::Add(Buff::new(
|
||||
BuffKind::Burning,
|
||||
BuffData::new(20.0, None, None),
|
||||
BuffData::new(20.0, None),
|
||||
vec![BuffCategory::Natural],
|
||||
BuffSource::World,
|
||||
*read_data.time,
|
||||
|
@ -1370,8 +1370,7 @@ impl<'a> AgentData<'a> {
|
||||
Some(self.char_state),
|
||||
&contexts,
|
||||
)
|
||||
.unwrap_or_default()
|
||||
.0
|
||||
.map_or(Default::default(), |a| a.0)
|
||||
};
|
||||
let (flamethrower, shockwave) = (
|
||||
extract_ability(AbilityInput::Secondary),
|
||||
|
@ -220,8 +220,7 @@ impl<'a> AgentData<'a> {
|
||||
Some(self.char_state),
|
||||
&context,
|
||||
)
|
||||
.unwrap_or_default()
|
||||
.0,
|
||||
.map_or(Default::default(), |a| a.0),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1856,7 +1856,7 @@ fn handle_spawn_campfire(
|
||||
Aura::new(
|
||||
AuraKind::Buff {
|
||||
kind: BuffKind::CampfireHeal,
|
||||
data: BuffData::new(0.02, Some(Secs(1.0)), None),
|
||||
data: BuffData::new(0.02, Some(Secs(1.0))),
|
||||
category: BuffCategory::Natural,
|
||||
source: BuffSource::World,
|
||||
},
|
||||
@ -1868,7 +1868,7 @@ fn handle_spawn_campfire(
|
||||
Aura::new(
|
||||
AuraKind::Buff {
|
||||
kind: BuffKind::Burning,
|
||||
data: BuffData::new(2.0, Some(Secs(10.0)), None),
|
||||
data: BuffData::new(2.0, Some(Secs(10.0))),
|
||||
category: BuffCategory::Natural,
|
||||
source: BuffSource::World,
|
||||
},
|
||||
@ -3960,7 +3960,7 @@ fn handle_buff(
|
||||
if let (Some(buff), strength, duration) = parse_cmd_args!(args, String, f32, f64) {
|
||||
let strength = strength.unwrap_or(0.01);
|
||||
let duration = duration.unwrap_or(1.0);
|
||||
let buffdata = BuffData::new(strength, Some(Secs(duration)), None);
|
||||
let buffdata = BuffData::new(strength, Some(Secs(duration)));
|
||||
if buff != "all" {
|
||||
cast_buff(&buff, buffdata, server, target)
|
||||
} else {
|
||||
|
@ -394,7 +394,7 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
|
||||
Aura::new(
|
||||
AuraKind::Buff {
|
||||
kind: BuffKind::CampfireHeal,
|
||||
data: BuffData::new(0.02, Some(Secs(1.0)), None),
|
||||
data: BuffData::new(0.02, Some(Secs(1.0))),
|
||||
category: BuffCategory::Natural,
|
||||
source: BuffSource::World,
|
||||
},
|
||||
@ -406,7 +406,7 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
|
||||
Aura::new(
|
||||
AuraKind::Buff {
|
||||
kind: BuffKind::Burning,
|
||||
data: BuffData::new(2.0, Some(Secs(10.0)), None),
|
||||
data: BuffData::new(2.0, Some(Secs(10.0))),
|
||||
category: BuffCategory::Natural,
|
||||
source: BuffSource::World,
|
||||
},
|
||||
|
@ -1399,7 +1399,7 @@ pub fn handle_parry_hook(
|
||||
if let Some(attacker) = attacker && matches!(source, AttackSource::Melee){
|
||||
// When attacker is parried, add the parried debuff for 2 seconds, which slows
|
||||
// them
|
||||
let data = buff::BuffData::new(1.0, Some(Secs(2.0)), None);
|
||||
let data = buff::BuffData::new(1.0, Some(Secs(2.0)));
|
||||
let source = if let Some(uid) = ecs.read_storage::<Uid>().get(defender) {
|
||||
BuffSource::Character { by: *uid }
|
||||
} else {
|
||||
|
@ -511,7 +511,7 @@ impl StateExt for State {
|
||||
.with(Auras::new(vec![Aura::new(
|
||||
AuraKind::Buff {
|
||||
kind: BuffKind::Invulnerability,
|
||||
data: BuffData::new(1.0, Some(Secs(1.0)), None),
|
||||
data: BuffData::new(1.0, Some(Secs(1.0))),
|
||||
category: BuffCategory::Natural,
|
||||
source: BuffSource::World,
|
||||
},
|
||||
|
@ -264,7 +264,7 @@ impl Animation for ChargeswingAnimation {
|
||||
next.control.orientation =
|
||||
Quaternion::rotation_x(s_a.ac.3 + move1 * -1.0 + tension / 30.0)
|
||||
* Quaternion::rotation_y(s_a.ac.4)
|
||||
* Quaternion::rotation_z(s_a.ac.5);
|
||||
* Quaternion::rotation_z(s_a.ac.5 - move1 * PI);
|
||||
|
||||
next.control.orientation.rotate_x(move2 * -3.0);
|
||||
next.control.position += Vec3::new(0.0, move2 * 8.0, move2 * -30.0);
|
||||
|
@ -912,7 +912,7 @@ impl Animation for ComboAnimation {
|
||||
next.control.orientation =
|
||||
Quaternion::rotation_x(s_a.ac.3 + move1 * -1.5)
|
||||
* Quaternion::rotation_y(s_a.ac.4)
|
||||
* Quaternion::rotation_z(s_a.ac.5 + move1 * 0.4);
|
||||
* Quaternion::rotation_z(s_a.ac.5 + move1 * (0.4 - PI));
|
||||
|
||||
next.chest.orientation.rotate_z(move1 * 0.4);
|
||||
next.head.orientation.rotate_z(move1 * -0.2);
|
||||
@ -925,7 +925,7 @@ impl Animation for ComboAnimation {
|
||||
next.shorts.orientation.rotate_z(move2 * 0.2);
|
||||
next.control.orientation = next.control.orientation
|
||||
* Quaternion::rotation_z(move2 * -0.5)
|
||||
* Quaternion::rotation_x(move2 * -2.0);
|
||||
* Quaternion::rotation_x(move2 * 2.0);
|
||||
next.control.orientation.rotate_y(move2 * -0.7);
|
||||
next.control.position += Vec3::new(move2 * 15.0, 0.0, move2 * -4.0);
|
||||
},
|
||||
@ -944,7 +944,7 @@ impl Animation for ComboAnimation {
|
||||
next.shorts.orientation.rotate_z(move2 * -0.2);
|
||||
next.control.orientation = next.control.orientation
|
||||
* Quaternion::rotation_z(move2 * 0.5)
|
||||
* Quaternion::rotation_x(move2 * -2.0);
|
||||
* Quaternion::rotation_x(move2 * 2.0);
|
||||
next.control.orientation.rotate_y(move2 * 0.7);
|
||||
next.control.position += Vec3::new(move2 * -15.0, 0.0, move2 * -4.0);
|
||||
},
|
||||
@ -985,7 +985,7 @@ impl Animation for ComboAnimation {
|
||||
Vec3::new(s_a.ac.0 + move1 * -1.0, s_a.ac.1 + move1 * -4.0, s_a.ac.2);
|
||||
next.control.orientation = Quaternion::rotation_x(s_a.ac.3 + move1 * -0.4)
|
||||
* Quaternion::rotation_y(s_a.ac.4 + move1 * -0.5)
|
||||
* Quaternion::rotation_z(s_a.ac.5 + move1 * 1.5);
|
||||
* Quaternion::rotation_z(s_a.ac.5 + move1 * (1.5 - PI));
|
||||
|
||||
next.control.orientation.rotate_z(move2 * -3.5);
|
||||
next.control.position += Vec3::new(move2 * 12.0, move2 * 4.0, 0.0);
|
||||
@ -1012,7 +1012,7 @@ impl Animation for ComboAnimation {
|
||||
Vec3::new(s_a.ac.0 + move1 * -1.0, s_a.ac.1 + move1 * -4.0, s_a.ac.2);
|
||||
next.control.orientation = Quaternion::rotation_x(s_a.ac.3 + move1 * 0.6)
|
||||
* Quaternion::rotation_y(s_a.ac.4 + move1 * -0.5)
|
||||
* Quaternion::rotation_z(s_a.ac.5 + move1 * 3.0);
|
||||
* Quaternion::rotation_z(s_a.ac.5 + move1 * (3.0 - PI));
|
||||
|
||||
next.chest.orientation = Quaternion::rotation_z(move1 * 0.6);
|
||||
next.head.orientation = Quaternion::rotation_z(move1 * -0.2);
|
||||
|
@ -161,7 +161,7 @@ impl Animation for FinisherMeleeAnimation {
|
||||
next.control.position = Vec3::new(s_a.ac.0, s_a.ac.1, s_a.ac.2);
|
||||
next.control.orientation = Quaternion::rotation_x(s_a.ac.3)
|
||||
* Quaternion::rotation_y(s_a.ac.4)
|
||||
* Quaternion::rotation_z(s_a.ac.5);
|
||||
* Quaternion::rotation_z(s_a.ac.5 - move1 * PI);
|
||||
|
||||
next.control.orientation.rotate_x(move1 * 0.9);
|
||||
next.chest.orientation.rotate_z(move1 * 1.2);
|
||||
@ -199,7 +199,7 @@ impl Animation for FinisherMeleeAnimation {
|
||||
next.control.position = Vec3::new(s_a.ac.0, s_a.ac.1, s_a.ac.2);
|
||||
next.control.orientation = Quaternion::rotation_x(s_a.ac.3)
|
||||
* Quaternion::rotation_y(s_a.ac.4)
|
||||
* Quaternion::rotation_z(s_a.ac.5);
|
||||
* Quaternion::rotation_z(s_a.ac.5 - move1 * PI);
|
||||
|
||||
next.control.orientation.rotate_x(move1 * 0.9);
|
||||
next.chest.orientation.rotate_z(move1 * 1.2);
|
||||
|
@ -3,6 +3,7 @@ use super::{
|
||||
CharacterSkeleton, SkeletonAttr,
|
||||
};
|
||||
use common::states::utils::{AbilityInfo, StageSection};
|
||||
use core::f32::consts::PI;
|
||||
|
||||
pub struct SelfBuffAnimation;
|
||||
impl Animation for SelfBuffAnimation {
|
||||
@ -188,7 +189,7 @@ impl Animation for SelfBuffAnimation {
|
||||
* Quaternion::rotation_z(s_a.ac.5);
|
||||
|
||||
next.control.orientation.rotate_z(move1 * -2.0);
|
||||
next.control.orientation.rotate_x(move1 * -3.5);
|
||||
next.control.orientation.rotate_x(move1 * 3.5);
|
||||
next.control.position += Vec3::new(move1 * 14.0, move1 * -6.0, move1 * 15.0);
|
||||
|
||||
next.head.orientation.rotate_x(move2 * 0.6);
|
||||
@ -248,7 +249,7 @@ impl Animation for SelfBuffAnimation {
|
||||
next.control.position = Vec3::new(s_a.ac.0, s_a.ac.1, s_a.ac.2);
|
||||
next.control.orientation = Quaternion::rotation_x(s_a.ac.3)
|
||||
* Quaternion::rotation_y(s_a.ac.4)
|
||||
* Quaternion::rotation_z(s_a.ac.5);
|
||||
* Quaternion::rotation_z(s_a.ac.5 - move1 * PI);
|
||||
|
||||
next.control.orientation.rotate_z(move1 * -1.8);
|
||||
next.control.orientation.rotate_y(move1 * 1.5);
|
||||
|
@ -1169,7 +1169,7 @@ impl<'a> Skillbar<'a> {
|
||||
self.contexts,
|
||||
)
|
||||
})
|
||||
.map_or(false, |(a, _)| {
|
||||
.map_or(false, |(a, _, _)| {
|
||||
self.energy.current() >= a.energy_cost()
|
||||
&& self.combo.map_or(false, |c| c.counter() >= a.combo_cost())
|
||||
&& a.ability_meta().requirements.requirements_met(self.stance)
|
||||
|
@ -186,7 +186,7 @@ impl<'a> SlotKey<HotbarSource<'a>, HotbarImageSource<'a>> for HotbarSlot {
|
||||
contexts,
|
||||
)
|
||||
})
|
||||
.map(|(ability, _)| {
|
||||
.map(|(ability, _, _)| {
|
||||
(
|
||||
image,
|
||||
if energy.current() >= ability.energy_cost()
|
||||
|
@ -37,11 +37,11 @@ use anim::{
|
||||
use common::{
|
||||
comp::{
|
||||
inventory::slot::EquipSlot,
|
||||
item::{tool::AbilityContext, Hands, ItemKind, ToolKind},
|
||||
item::{Hands, ItemKind, ToolKind},
|
||||
ship::{self, figuredata::VOXEL_COLLIDER_MANIFEST},
|
||||
Body, CharacterActivity, CharacterState, Collider, Combo, Controller, Health, Inventory,
|
||||
Item, ItemKey, Last, LightAnimation, LightEmitter, Object, Ori, PhysicsState, PoiseState,
|
||||
Pos, Scale, SkillSet, Stance, Vel,
|
||||
Body, CharacterActivity, CharacterState, Collider, Controller, Health, Inventory, Item,
|
||||
ItemKey, Last, LightAnimation, LightEmitter, Object, Ori, PhysicsState, PoiseState, Pos,
|
||||
Scale, Vel,
|
||||
},
|
||||
link::Is,
|
||||
mounting::{Rider, VolumeRider},
|
||||
@ -853,7 +853,7 @@ impl FigureMgr {
|
||||
inventory,
|
||||
item,
|
||||
light_emitter,
|
||||
(is_rider, is_volume_rider, collider, stance, skillset, combo),
|
||||
(is_rider, is_volume_rider, collider),
|
||||
),
|
||||
) in (
|
||||
&ecs.entities(),
|
||||
@ -875,9 +875,6 @@ impl FigureMgr {
|
||||
ecs.read_storage::<Is<Rider>>().maybe(),
|
||||
ecs.read_storage::<Is<VolumeRider>>().maybe(),
|
||||
ecs.read_storage::<Collider>().maybe(),
|
||||
ecs.read_storage::<Stance>().maybe(),
|
||||
ecs.read_storage::<SkillSet>().maybe(),
|
||||
ecs.read_storage::<Combo>().maybe(),
|
||||
),
|
||||
)
|
||||
.join()
|
||||
@ -1038,12 +1035,10 @@ impl FigureMgr {
|
||||
let second_tool_spec = second_tool_spec.as_deref();
|
||||
let hands = (active_tool_hand, second_tool_hand);
|
||||
|
||||
let contexts = AbilityContext::from(stance, inventory, combo);
|
||||
|
||||
let ability_id = character.and_then(|c| {
|
||||
c.ability_info()
|
||||
.and_then(|a| a.ability)
|
||||
.and_then(|a| a.ability_id(inventory, skillset, &contexts))
|
||||
.and_then(|a| a.ability_id(inventory))
|
||||
});
|
||||
|
||||
let move_dir = {
|
||||
|
Loading…
Reference in New Issue
Block a user