mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Make abilities depend on weapon
This commit is contained in:
parent
ac1c279a9b
commit
fe19698d52
@ -1,10 +1,12 @@
|
||||
use crate::comp::CharacterState;
|
||||
use specs::{Component, DenseVecStorage, FlaggedStorage, HashMapStorage};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum AbilityState {
|
||||
pub enum CharacterAbility {
|
||||
BasicAttack {
|
||||
/// Amount of energy required to use ability
|
||||
cost: i32,
|
||||
buildup_duration: Duration,
|
||||
recover_duration: Duration,
|
||||
},
|
||||
BasicBlock,
|
||||
Roll,
|
||||
@ -14,30 +16,43 @@ pub enum AbilityState {
|
||||
cost: i32,
|
||||
},
|
||||
}
|
||||
impl Default for AbilityState {
|
||||
fn default() -> Self { Self::BasicAttack { cost: -100 } }
|
||||
}
|
||||
|
||||
impl Component for AbilityState {
|
||||
impl Component for CharacterAbility {
|
||||
type Storage = DenseVecStorage<Self>;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize)]
|
||||
pub struct AbilityPool {
|
||||
pub primary: Option<AbilityState>,
|
||||
pub secondary: Option<AbilityState>,
|
||||
pub block: Option<AbilityState>,
|
||||
pub dodge: Option<AbilityState>,
|
||||
pub primary: Option<CharacterAbility>,
|
||||
pub secondary: Option<CharacterAbility>,
|
||||
pub block: Option<CharacterAbility>,
|
||||
pub dodge: Option<CharacterAbility>,
|
||||
}
|
||||
|
||||
impl Default for AbilityPool {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
primary: Some(AbilityState::default()),
|
||||
// primary: Some(AbilityState::TimedCombo),
|
||||
secondary: Some(AbilityState::BasicBlock),
|
||||
block: None,
|
||||
dodge: Some(AbilityState::Roll),
|
||||
impl From<CharacterAbility> for CharacterState {
|
||||
fn from(ability: CharacterAbility) -> Self {
|
||||
match ability {
|
||||
CharacterAbility::BasicAttack {
|
||||
buildup_duration,
|
||||
recover_duration,
|
||||
} => CharacterState::BasicAttack {
|
||||
exhausted: false,
|
||||
buildup_duration,
|
||||
recover_duration,
|
||||
},
|
||||
CharacterAbility::BasicBlock { .. } => CharacterState::BasicBlock {},
|
||||
CharacterAbility::Roll { .. } => CharacterState::Roll {
|
||||
remaining_duration: Duration::from_millis(600),
|
||||
},
|
||||
CharacterAbility::ChargeAttack { .. } => CharacterState::ChargeAttack {
|
||||
remaining_duration: Duration::from_millis(600),
|
||||
},
|
||||
CharacterAbility::TimedCombo { .. } => CharacterState::TimedCombo {
|
||||
stage: 1,
|
||||
stage_time_active: Duration::default(),
|
||||
stage_exhausted: false,
|
||||
can_transition: false,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ pub struct StateUpdate {
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
|
||||
pub enum CharacterState {
|
||||
Idle {},
|
||||
Climb {},
|
||||
Idle,
|
||||
Climb,
|
||||
Sit {},
|
||||
Equipping {
|
||||
/// The weapon being equipped
|
||||
@ -32,16 +32,18 @@ pub enum CharacterState {
|
||||
/// The weapon being wielded
|
||||
tool: ToolData,
|
||||
},
|
||||
Glide {},
|
||||
Glide,
|
||||
/// A basic attacking state
|
||||
BasicAttack {
|
||||
/// How long the state has until exiting
|
||||
remaining_duration: Duration,
|
||||
/// How long till the state deals damage
|
||||
buildup_duration: Duration,
|
||||
/// How long till the state remains after dealing damage
|
||||
recover_duration: Duration,
|
||||
/// Whether the attack can deal more damage
|
||||
exhausted: bool,
|
||||
},
|
||||
/// A basic blocking state
|
||||
BasicBlock {},
|
||||
BasicBlock,
|
||||
ChargeAttack {
|
||||
/// How long the state has until exiting
|
||||
remaining_duration: Duration,
|
||||
@ -53,8 +55,6 @@ pub enum CharacterState {
|
||||
/// A three-stage attack where play must click at appropriate times
|
||||
/// to continue attack chain.
|
||||
TimedCombo {
|
||||
/// The tool this state will read to handle damage, etc.
|
||||
tool: ToolData,
|
||||
/// `int` denoting what stage (of 3) the attack is in.
|
||||
stage: i8,
|
||||
/// How long current stage has been active
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
assets::{self, Asset},
|
||||
comp::AbilityState,
|
||||
comp::CharacterAbility,
|
||||
effect::Effect,
|
||||
terrain::{Block, BlockKind},
|
||||
};
|
||||
@ -25,47 +25,55 @@ pub enum ToolKind {
|
||||
Dagger,
|
||||
Staff,
|
||||
Shield,
|
||||
Debug(Debug),
|
||||
}
|
||||
|
||||
impl Default for ToolKind {
|
||||
fn default() -> Self { Self::Axe }
|
||||
Debug(DebugKind),
|
||||
}
|
||||
|
||||
impl ToolData {
|
||||
pub fn equip_time(&self) -> Duration { Duration::from_millis(self.equip_time_millis) }
|
||||
|
||||
pub fn attack_buildup_duration(&self) -> Duration {
|
||||
Duration::from_millis(self.attack_buildup_millis)
|
||||
}
|
||||
|
||||
pub fn attack_recover_duration(&self) -> Duration {
|
||||
Duration::from_millis(self.attack_recover_millis)
|
||||
}
|
||||
|
||||
pub fn attack_duration(&self) -> Duration {
|
||||
self.attack_buildup_duration() + self.attack_recover_duration()
|
||||
}
|
||||
|
||||
pub fn get_primary_abilities(&self) -> Vec<AbilityState> {
|
||||
use AbilityState::*;
|
||||
use SwordKind::*;
|
||||
pub fn get_abilities(&self) -> Vec<CharacterAbility> {
|
||||
use CharacterAbility::*;
|
||||
use DebugKind::*;
|
||||
use ToolKind::*;
|
||||
|
||||
let default_return = vec![AbilityState::default()];
|
||||
|
||||
match self.kind {
|
||||
Sword(kind) => match kind {
|
||||
Rapier => vec![TimedCombo { cost: -150 }],
|
||||
Scimitar => default_return,
|
||||
Sword(_) => vec![TimedCombo { cost: -150 }],
|
||||
Axe => vec![BasicAttack {
|
||||
buildup_duration: Duration::from_millis(1000),
|
||||
recover_duration: Duration::from_millis(500),
|
||||
}],
|
||||
Hammer => vec![BasicAttack {
|
||||
buildup_duration: Duration::from_millis(1000),
|
||||
recover_duration: Duration::from_millis(500),
|
||||
}],
|
||||
Bow => vec![BasicAttack {
|
||||
buildup_duration: Duration::from_millis(1000),
|
||||
recover_duration: Duration::from_millis(500),
|
||||
}],
|
||||
Dagger => vec![BasicAttack {
|
||||
buildup_duration: Duration::from_millis(1000),
|
||||
recover_duration: Duration::from_millis(500),
|
||||
}],
|
||||
Staff => vec![BasicAttack {
|
||||
buildup_duration: Duration::from_millis(1000),
|
||||
recover_duration: Duration::from_millis(500),
|
||||
}],
|
||||
Shield => vec![BasicAttack {
|
||||
buildup_duration: Duration::from_millis(1000),
|
||||
recover_duration: Duration::from_millis(500),
|
||||
}],
|
||||
Debug(kind) => match kind {
|
||||
Boost => vec![],
|
||||
Possess => vec![],
|
||||
},
|
||||
_ => default_return,
|
||||
|
||||
_ => vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub enum Debug {
|
||||
pub enum DebugKind {
|
||||
Boost,
|
||||
Possess,
|
||||
}
|
||||
@ -109,7 +117,7 @@ pub enum Ingredient {
|
||||
Grass,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct ToolData {
|
||||
pub kind: ToolKind,
|
||||
equip_time_millis: u64,
|
||||
|
@ -1,7 +1,7 @@
|
||||
pub mod item;
|
||||
|
||||
// Reexports
|
||||
pub use item::{Consumable, Debug, Item, ItemKind, SwordKind, ToolData, ToolKind};
|
||||
pub use item::{Consumable, DebugKind, Item, ItemKind, SwordKind, ToolData, ToolKind};
|
||||
|
||||
use crate::assets;
|
||||
use specs::{Component, FlaggedStorage, HashMapStorage};
|
||||
|
@ -16,7 +16,7 @@ mod stats;
|
||||
mod visual;
|
||||
|
||||
// Reexports
|
||||
pub use ability::{AbilityPool, AbilityState};
|
||||
pub use ability::{AbilityPool, CharacterAbility};
|
||||
pub use admin::Admin;
|
||||
pub use agent::{Agent, Alignment};
|
||||
pub use body::{
|
||||
|
@ -21,7 +21,7 @@ sum_type! {
|
||||
Mass(comp::Mass),
|
||||
Gravity(comp::Gravity),
|
||||
Sticky(comp::Sticky),
|
||||
AbilityState(comp::AbilityState),
|
||||
CharacterAbility(comp::CharacterAbility),
|
||||
AbilityPool(comp::AbilityPool),
|
||||
Attacking(comp::Attacking),
|
||||
CharacterState(comp::CharacterState),
|
||||
@ -45,7 +45,7 @@ sum_type! {
|
||||
Mass(PhantomData<comp::Mass>),
|
||||
Gravity(PhantomData<comp::Gravity>),
|
||||
Sticky(PhantomData<comp::Sticky>),
|
||||
AbilityState(PhantomData<comp::AbilityState>),
|
||||
CharacterAbility(PhantomData<comp::CharacterAbility>),
|
||||
AbilityPool(PhantomData<comp::AbilityPool>),
|
||||
Attacking(PhantomData<comp::Attacking>),
|
||||
CharacterState(PhantomData<comp::CharacterState>),
|
||||
@ -69,7 +69,7 @@ impl sync::CompPacket for EcsCompPacket {
|
||||
EcsCompPacket::Mass(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::Gravity(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::Sticky(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::AbilityState(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::CharacterAbility(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::AbilityPool(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::Attacking(comp) => sync::handle_insert(comp, entity, world),
|
||||
EcsCompPacket::CharacterState(comp) => sync::handle_insert(comp, entity, world),
|
||||
@ -91,7 +91,7 @@ impl sync::CompPacket for EcsCompPacket {
|
||||
EcsCompPacket::Mass(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::Gravity(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::Sticky(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::AbilityState(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::CharacterAbility(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::AbilityPool(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::Attacking(comp) => sync::handle_modify(comp, entity, world),
|
||||
EcsCompPacket::CharacterState(comp) => sync::handle_modify(comp, entity, world),
|
||||
@ -115,8 +115,8 @@ impl sync::CompPacket for EcsCompPacket {
|
||||
EcsCompPhantom::Mass(_) => sync::handle_remove::<comp::Mass>(entity, world),
|
||||
EcsCompPhantom::Gravity(_) => sync::handle_remove::<comp::Gravity>(entity, world),
|
||||
EcsCompPhantom::Sticky(_) => sync::handle_remove::<comp::Sticky>(entity, world),
|
||||
EcsCompPhantom::AbilityState(_) => {
|
||||
sync::handle_remove::<comp::AbilityState>(entity, world)
|
||||
EcsCompPhantom::CharacterAbility(_) => {
|
||||
sync::handle_remove::<comp::CharacterAbility>(entity, world)
|
||||
},
|
||||
EcsCompPhantom::AbilityPool(_) => {
|
||||
sync::handle_remove::<comp::AbilityPool>(entity, world)
|
||||
|
@ -107,7 +107,7 @@ impl State {
|
||||
ecs.register_sync_marker();
|
||||
// Register server -> all clients synced components.
|
||||
ecs.register::<comp::AbilityPool>();
|
||||
ecs.register::<comp::AbilityState>();
|
||||
ecs.register::<comp::CharacterAbility>();
|
||||
ecs.register::<comp::Projectile>();
|
||||
ecs.register::<comp::Body>();
|
||||
ecs.register::<comp::Player>();
|
||||
|
@ -18,51 +18,65 @@ pub fn behavior(data: &JoinData) -> StateUpdate {
|
||||
|
||||
if let CharacterState::BasicAttack {
|
||||
exhausted,
|
||||
remaining_duration,
|
||||
buildup_duration,
|
||||
recover_duration,
|
||||
} = data.character
|
||||
{
|
||||
let tool_kind = data.stats.equipment.main.as_ref().map(|i| i.kind);
|
||||
if let Some(Tool(tool)) = tool_kind {
|
||||
handle_move(data, &mut update);
|
||||
handle_move(data, &mut update);
|
||||
|
||||
let mut new_exhausted = *exhausted;
|
||||
|
||||
if !*exhausted && *remaining_duration < tool.attack_recover_duration() {
|
||||
if buildup_duration != &Duration::default() {
|
||||
// Start to swing
|
||||
update.character = CharacterState::BasicAttack {
|
||||
buildup_duration: buildup_duration
|
||||
.checked_sub(Duration::from_secs_f32(data.dt.0))
|
||||
.unwrap_or_default(),
|
||||
recover_duration: *recover_duration,
|
||||
exhausted: false,
|
||||
};
|
||||
} else if !*exhausted {
|
||||
// Swing hits
|
||||
if let Some(Tool(tool)) = tool_kind {
|
||||
data.updater.insert(data.entity, Attacking {
|
||||
weapon: Some(tool),
|
||||
applied: false,
|
||||
hit_count: 0,
|
||||
});
|
||||
new_exhausted = true;
|
||||
}
|
||||
|
||||
let new_remaining_duration = remaining_duration
|
||||
.checked_sub(Duration::from_secs_f32(data.dt.0))
|
||||
.unwrap_or_default();
|
||||
|
||||
if let Some(attack) = data.attacking {
|
||||
if attack.applied && attack.hit_count > 0 {
|
||||
data.updater.remove::<Attacking>(data.entity);
|
||||
update.energy.change_by(100, EnergySource::HitEnemy);
|
||||
}
|
||||
}
|
||||
|
||||
// Tick down
|
||||
update.character = CharacterState::BasicAttack {
|
||||
remaining_duration: new_remaining_duration,
|
||||
exhausted: new_exhausted,
|
||||
buildup_duration: *buildup_duration,
|
||||
recover_duration: *recover_duration,
|
||||
exhausted: true,
|
||||
};
|
||||
|
||||
// Check if attack duration has expired
|
||||
if new_remaining_duration == Duration::default() {
|
||||
} else if recover_duration != &Duration::default() {
|
||||
// Recover from swing
|
||||
update.character = CharacterState::BasicAttack {
|
||||
buildup_duration: *buildup_duration,
|
||||
recover_duration: recover_duration
|
||||
.checked_sub(Duration::from_secs_f32(data.dt.0))
|
||||
.unwrap_or_default(),
|
||||
exhausted: true,
|
||||
}
|
||||
} else {
|
||||
// Done
|
||||
if let Some(Tool(tool)) = tool_kind {
|
||||
update.character = CharacterState::Wielding { tool };
|
||||
data.updater.remove::<Attacking>(data.entity);
|
||||
} else {
|
||||
update.character = CharacterState::Idle;
|
||||
}
|
||||
|
||||
update
|
||||
} else {
|
||||
update
|
||||
}
|
||||
|
||||
// More handling
|
||||
if let Some(attack) = data.attacking {
|
||||
if attack.applied && attack.hit_count > 0 {
|
||||
data.updater.remove::<Attacking>(data.entity);
|
||||
update.energy.change_by(100, EnergySource::HitEnemy);
|
||||
}
|
||||
}
|
||||
|
||||
update
|
||||
} else {
|
||||
update.character = CharacterState::Idle {};
|
||||
update
|
||||
|
@ -17,77 +17,81 @@ pub fn behavior(data: &JoinData) -> StateUpdate {
|
||||
};
|
||||
|
||||
if let CharacterState::TimedCombo {
|
||||
tool,
|
||||
stage,
|
||||
stage_time_active,
|
||||
stage_exhausted,
|
||||
can_transition,
|
||||
} = data.character
|
||||
{
|
||||
let mut new_can_transition = *can_transition;
|
||||
let mut new_stage_exhausted = *stage_exhausted;
|
||||
let new_stage_time_active = stage_time_active
|
||||
.checked_add(Duration::from_secs_f32(data.dt.0))
|
||||
.unwrap_or(Duration::default());
|
||||
// Sorry adam, I don't want to fix this rn, check out basic_attack to
|
||||
// see how to do it
|
||||
//
|
||||
/*
|
||||
let mut new_can_transition = *can_transition;
|
||||
let mut new_stage_exhausted = *stage_exhausted;
|
||||
let new_stage_time_active = stage_time_active
|
||||
.checked_add(Duration::from_secs_f32(data.dt.0))
|
||||
.unwrap_or(Duration::default());
|
||||
|
||||
match stage {
|
||||
1 => {
|
||||
if new_stage_time_active > tool.attack_buildup_duration() {
|
||||
if !*stage_exhausted {
|
||||
// Try to deal damage
|
||||
data.updater.insert(data.entity, Attacking {
|
||||
weapon: Some(*tool),
|
||||
applied: false,
|
||||
hit_count: 0,
|
||||
});
|
||||
new_stage_exhausted = true;
|
||||
} else {
|
||||
// Make sure to remove Attacking component
|
||||
data.updater.remove::<Attacking>(data.entity);
|
||||
match stage {
|
||||
1 => {
|
||||
if new_stage_time_active > tool.attack_buildup_duration() {
|
||||
if !*stage_exhausted {
|
||||
// Try to deal damage
|
||||
data.updater.insert(data.entity, Attacking {
|
||||
weapon: Some(*tool),
|
||||
applied: false,
|
||||
hit_count: 0,
|
||||
});
|
||||
new_stage_exhausted = true;
|
||||
} else {
|
||||
// Make sure to remove Attacking component
|
||||
data.updater.remove::<Attacking>(data.entity);
|
||||
}
|
||||
|
||||
// Check if player has timed click right
|
||||
if data.inputs.primary.is_just_pressed() {
|
||||
println!("Can transition");
|
||||
new_can_transition = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if player has timed click right
|
||||
if data.inputs.primary.is_just_pressed() {
|
||||
println!("Can transition");
|
||||
new_can_transition = true;
|
||||
}
|
||||
}
|
||||
|
||||
if new_stage_time_active > tool.attack_duration() {
|
||||
if new_can_transition {
|
||||
update.character = CharacterState::TimedCombo {
|
||||
tool: *tool,
|
||||
stage: 2,
|
||||
stage_time_active: Duration::default(),
|
||||
stage_exhausted: false,
|
||||
can_transition: false,
|
||||
if new_stage_time_active > tool.attack_duration() {
|
||||
if new_can_transition {
|
||||
update.character = CharacterState::TimedCombo {
|
||||
tool: *tool,
|
||||
stage: 2,
|
||||
stage_time_active: Duration::default(),
|
||||
stage_exhausted: false,
|
||||
can_transition: false,
|
||||
}
|
||||
} else {
|
||||
println!("Failed");
|
||||
attempt_wield(data, &mut update);
|
||||
}
|
||||
} else {
|
||||
println!("Failed");
|
||||
attempt_wield(data, &mut update);
|
||||
update.character = CharacterState::TimedCombo {
|
||||
tool: *tool,
|
||||
stage: 1,
|
||||
stage_time_active: new_stage_time_active,
|
||||
stage_exhausted: new_stage_exhausted,
|
||||
can_transition: new_can_transition,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
update.character = CharacterState::TimedCombo {
|
||||
tool: *tool,
|
||||
stage: 1,
|
||||
stage_time_active: new_stage_time_active,
|
||||
stage_exhausted: new_stage_exhausted,
|
||||
can_transition: new_can_transition,
|
||||
}
|
||||
}
|
||||
},
|
||||
2 => {
|
||||
println!("2");
|
||||
attempt_wield(data, &mut update);
|
||||
},
|
||||
3 => {
|
||||
println!("3");
|
||||
attempt_wield(data, &mut update);
|
||||
},
|
||||
_ => {
|
||||
// Should never get here.
|
||||
},
|
||||
}
|
||||
},
|
||||
2 => {
|
||||
println!("2");
|
||||
attempt_wield(data, &mut update);
|
||||
},
|
||||
3 => {
|
||||
println!("3");
|
||||
attempt_wield(data, &mut update);
|
||||
},
|
||||
_ => {
|
||||
// Should never get here.
|
||||
},
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
update
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
comp::{AbilityState, CharacterState, EnergySource, ItemKind::Tool, StateUpdate, ToolData},
|
||||
comp::{CharacterAbility, CharacterState, EnergySource, ItemKind::Tool, StateUpdate, ToolData},
|
||||
event::LocalEvent,
|
||||
sys::{character_behavior::JoinData, phys::GRAVITY},
|
||||
};
|
||||
@ -191,8 +191,8 @@ pub fn handle_primary_input(data: &JoinData, update: &mut StateUpdate) {
|
||||
|
||||
/// Attempts to go into `ability_pool.primary` if is `Some()` on `AbilityPool`
|
||||
pub fn attempt_primary_ability(data: &JoinData, update: &mut StateUpdate) {
|
||||
if let Some(ability_state) = data.ability_pool.primary {
|
||||
update.character = ability_to_character_state(data, update, ability_state);
|
||||
if let Some(ability) = data.ability_pool.primary {
|
||||
update.character = ability.into();
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,15 +201,15 @@ pub fn attempt_primary_ability(data: &JoinData, update: &mut StateUpdate) {
|
||||
pub fn handle_secondary_input(data: &JoinData, update: &mut StateUpdate) {
|
||||
if data.inputs.secondary.is_pressed() {
|
||||
if let CharacterState::Wielding { .. } = update.character {
|
||||
attempt_seconday_ability(data, update);
|
||||
attempt_secondary_ability(data, update);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Attempts to go into `ability_pool.secondary` if is `Some()` on `AbilityPool`
|
||||
pub fn attempt_seconday_ability(data: &JoinData, update: &mut StateUpdate) {
|
||||
if let Some(ability_state) = data.ability_pool.secondary {
|
||||
update.character = ability_to_character_state(data, update, ability_state);
|
||||
pub fn attempt_secondary_ability(data: &JoinData, update: &mut StateUpdate) {
|
||||
if let Some(ability) = data.ability_pool.secondary {
|
||||
update.character = ability.into();
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,63 +232,7 @@ pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
|
||||
}
|
||||
|
||||
pub fn attempt_dodge_ability(data: &JoinData, update: &mut StateUpdate) {
|
||||
if let Some(ability_state) = data.ability_pool.dodge {
|
||||
update.character = ability_to_character_state(data, update, ability_state);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Might need a fn `CharacterState::new(data, update)` if
|
||||
// initialization gets too lengthy.
|
||||
|
||||
/// Maps from `AbilityState`s to `CharacterStates`s. Also handles intializing
|
||||
/// the new `CharacterState`
|
||||
pub fn ability_to_character_state(
|
||||
data: &JoinData,
|
||||
update: &mut StateUpdate,
|
||||
ability_state: AbilityState,
|
||||
) -> CharacterState {
|
||||
match ability_state {
|
||||
AbilityState::BasicAttack { cost, .. } => {
|
||||
if let Some(tool) = unwrap_tool_data(data) {
|
||||
if update.energy.try_change_by(cost, EnergySource::HitEnemy).is_ok() {
|
||||
return CharacterState::BasicAttack {
|
||||
exhausted: false,
|
||||
remaining_duration: tool.attack_duration(),
|
||||
};
|
||||
}
|
||||
}
|
||||
*data.character
|
||||
},
|
||||
AbilityState::BasicBlock { .. } => CharacterState::BasicBlock {},
|
||||
AbilityState::Roll { .. } => CharacterState::Roll {
|
||||
remaining_duration: Duration::from_millis(600),
|
||||
},
|
||||
AbilityState::ChargeAttack { .. } => CharacterState::ChargeAttack {
|
||||
remaining_duration: Duration::from_millis(600),
|
||||
},
|
||||
AbilityState::TimedCombo { .. } => {
|
||||
if let Some(tool) = unwrap_tool_data(data) {
|
||||
CharacterState::TimedCombo {
|
||||
tool,
|
||||
stage: 1,
|
||||
stage_time_active: Duration::default(),
|
||||
stage_exhausted: false,
|
||||
can_transition: false,
|
||||
}
|
||||
} else {
|
||||
*data.character
|
||||
}
|
||||
},
|
||||
|
||||
// Do not use default match
|
||||
// _ => *data.character
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unwrap_tool_data(data: &JoinData) -> Option<ToolData> {
|
||||
if let Some(Tool(tool)) = data.stats.equipment.main.as_ref().map(|i| i.kind) {
|
||||
Some(tool)
|
||||
} else {
|
||||
None
|
||||
if let Some(ability) = data.ability_pool.dodge {
|
||||
update.character = ability.into();
|
||||
}
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ impl Server {
|
||||
let spawn_point = state.ecs().read_resource::<SpawnPoint>().0;
|
||||
|
||||
state.write_component(entity, body);
|
||||
state.write_component(entity, comp::Stats::new(name, body, main));
|
||||
state.write_component(entity, comp::Stats::new(name, body, main.clone()));
|
||||
state.write_component(entity, comp::Energy::new(1000));
|
||||
state.write_component(entity, comp::Controller::default());
|
||||
state.write_component(entity, comp::Pos(spawn_point));
|
||||
@ -286,7 +286,27 @@ impl Server {
|
||||
entity,
|
||||
comp::InventoryUpdate::new(comp::InventoryUpdateEvent::default()),
|
||||
);
|
||||
state.write_component(entity, comp::AbilityPool::default());
|
||||
|
||||
state.write_component(
|
||||
entity,
|
||||
if let Some(comp::Item {
|
||||
kind: comp::ItemKind::Tool(tool),
|
||||
..
|
||||
}) = main
|
||||
{
|
||||
let mut abilities = tool.get_abilities();
|
||||
let mut ability_drain = abilities.drain(..);
|
||||
comp::AbilityPool {
|
||||
primary: ability_drain.next(),
|
||||
secondary: ability_drain.next(),
|
||||
block: Some(comp::CharacterAbility::BasicBlock),
|
||||
dodge: Some(comp::CharacterAbility::Roll),
|
||||
}
|
||||
} else {
|
||||
comp::AbilityPool::default()
|
||||
},
|
||||
);
|
||||
|
||||
// Make sure physics are accepted.
|
||||
state.write_component(entity, comp::ForceUpdate);
|
||||
|
||||
|
@ -10,7 +10,7 @@ use crate::{
|
||||
use common::{
|
||||
assets::load_expect,
|
||||
comp::{
|
||||
item::{Debug, ToolData, ToolKind},
|
||||
item::{DebugKind, ToolData, ToolKind},
|
||||
CharacterState, ControllerInputs, Energy, ItemKind, Stats,
|
||||
},
|
||||
};
|
||||
@ -597,7 +597,7 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
ToolKind::Axe => self.imgs.twohaxe_m1,
|
||||
ToolKind::Bow => self.imgs.bow_m1,
|
||||
ToolKind::Staff => self.imgs.staff_m1,
|
||||
ToolKind::Debug(Debug::Boost) => self.imgs.flyingrod_m1,
|
||||
ToolKind::Debug(DebugKind::Boost) => self.imgs.flyingrod_m1,
|
||||
_ => self.imgs.twohaxe_m1,
|
||||
},
|
||||
_ => self.imgs.twohaxe_m1,
|
||||
@ -690,7 +690,7 @@ impl<'a> Widget for Skillbar<'a> {
|
||||
ToolKind::Axe => self.imgs.twohaxe_m2,
|
||||
ToolKind::Bow => self.imgs.bow_m2,
|
||||
ToolKind::Staff => self.imgs.staff_m2,
|
||||
ToolKind::Debug(Debug::Boost) => self.imgs.flyingrod_m2,
|
||||
ToolKind::Debug(DebugKind::Boost) => self.imgs.flyingrod_m2,
|
||||
_ => self.imgs.twohaxe_m2,
|
||||
},
|
||||
_ => self.imgs.twohaxe_m2,
|
||||
|
Loading…
Reference in New Issue
Block a user