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