Added AbilityInfo struct to attack states

This commit is contained in:
Sam
2021-02-14 01:01:53 -05:00
parent 50cbe42b07
commit 18309fe4c6
13 changed files with 105 additions and 66 deletions

View File

@ -6,7 +6,7 @@ use crate::{
}, },
states::{ states::{
behavior::JoinData, behavior::JoinData,
utils::{AbilityKey, StageSection}, utils::{AbilityInfo, StageSection},
*, *,
}, },
Knockback, Knockback,
@ -1060,8 +1060,8 @@ impl CharacterAbility {
} }
} }
impl From<(&CharacterAbility, AbilityKey)> for CharacterState { impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
fn from((ability, key): (&CharacterAbility, AbilityKey)) -> Self { fn from((ability, ability_info): (&CharacterAbility, AbilityInfo)) -> Self {
match ability { match ability {
CharacterAbility::BasicMelee { CharacterAbility::BasicMelee {
buildup_duration, buildup_duration,
@ -1083,7 +1083,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
knockback: *knockback, knockback: *knockback,
range: *range, range: *range,
max_angle: *max_angle, max_angle: *max_angle,
ability_key: key, ability_info,
}, },
timer: Duration::default(), timer: Duration::default(),
stage_section: StageSection::Buildup, stage_section: StageSection::Buildup,
@ -1109,7 +1109,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
projectile_gravity: *projectile_gravity, projectile_gravity: *projectile_gravity,
projectile_speed: *projectile_speed, projectile_speed: *projectile_speed,
can_continue: *can_continue, can_continue: *can_continue,
ability_key: key, ability_info,
}, },
timer: Duration::default(), timer: Duration::default(),
stage_section: StageSection::Buildup, stage_section: StageSection::Buildup,
@ -1162,7 +1162,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
swing_duration: Duration::from_secs_f32(*swing_duration), swing_duration: Duration::from_secs_f32(*swing_duration),
recover_duration: Duration::from_secs_f32(*recover_duration), recover_duration: Duration::from_secs_f32(*recover_duration),
is_interruptible: *is_interruptible, is_interruptible: *is_interruptible,
ability_key: key, ability_info,
}, },
auto_charge: false, auto_charge: false,
timer: Duration::default(), timer: Duration::default(),
@ -1212,7 +1212,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
max_speed_increase: *max_speed_increase, max_speed_increase: *max_speed_increase,
scales_from_combo: *scales_from_combo, scales_from_combo: *scales_from_combo,
is_interruptible: *is_interruptible, is_interruptible: *is_interruptible,
ability_key: key, ability_info,
}, },
stage: 1, stage: 1,
combo: 0, combo: 0,
@ -1246,7 +1246,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
max_angle: *max_angle, max_angle: *max_angle,
forward_leap_strength: *forward_leap_strength, forward_leap_strength: *forward_leap_strength,
vertical_leap_strength: *vertical_leap_strength, vertical_leap_strength: *vertical_leap_strength,
ability_key: key, ability_info,
}, },
timer: Duration::default(), timer: Duration::default(),
stage_section: StageSection::Buildup, stage_section: StageSection::Buildup,
@ -1281,7 +1281,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
is_interruptible: *is_interruptible, is_interruptible: *is_interruptible,
forward_speed: *forward_speed, forward_speed: *forward_speed,
num_spins: *num_spins, num_spins: *num_spins,
ability_key: key, ability_info,
}, },
timer: Duration::default(), timer: Duration::default(),
spins_remaining: *num_spins - 1, spins_remaining: *num_spins - 1,
@ -1321,7 +1321,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
swing_duration: Duration::from_secs_f32(*swing_duration), swing_duration: Duration::from_secs_f32(*swing_duration),
hit_timing: *hit_timing, hit_timing: *hit_timing,
recover_duration: Duration::from_secs_f32(*recover_duration), recover_duration: Duration::from_secs_f32(*recover_duration),
ability_key: key, ability_info,
}, },
stage_section: StageSection::Charge, stage_section: StageSection::Charge,
timer: Duration::default(), timer: Duration::default(),
@ -1362,7 +1362,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
initial_projectile_speed: *initial_projectile_speed, initial_projectile_speed: *initial_projectile_speed,
scaled_projectile_speed: *scaled_projectile_speed, scaled_projectile_speed: *scaled_projectile_speed,
move_speed: *move_speed, move_speed: *move_speed,
ability_key: key, ability_info,
}, },
timer: Duration::default(), timer: Duration::default(),
stage_section: StageSection::Buildup, stage_section: StageSection::Buildup,
@ -1393,7 +1393,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
projectile_light: *projectile_light, projectile_light: *projectile_light,
projectile_gravity: *projectile_gravity, projectile_gravity: *projectile_gravity,
projectile_speed: *projectile_speed, projectile_speed: *projectile_speed,
ability_key: key, ability_info,
}, },
timer: Duration::default(), timer: Duration::default(),
stage_section: StageSection::Movement, stage_section: StageSection::Movement,
@ -1427,7 +1427,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
shockwave_duration: Duration::from_secs_f32(*shockwave_duration), shockwave_duration: Duration::from_secs_f32(*shockwave_duration),
requires_ground: *requires_ground, requires_ground: *requires_ground,
move_efficiency: *move_efficiency, move_efficiency: *move_efficiency,
ability_key: key, ability_info,
}, },
timer: Duration::default(), timer: Duration::default(),
stage_section: StageSection::Buildup, stage_section: StageSection::Buildup,
@ -1459,7 +1459,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
energy_regen: *energy_regen, energy_regen: *energy_regen,
energy_cost: *energy_cost, energy_cost: *energy_cost,
energy_drain: *energy_drain, energy_drain: *energy_drain,
ability_key: key, ability_info,
}, },
timer: Duration::default(), timer: Duration::default(),
stage_section: StageSection::Buildup, stage_section: StageSection::Buildup,

View File

@ -44,7 +44,7 @@ pub struct StaticData {
/// Energy drained per /// Energy drained per
pub energy_drain: f32, pub energy_drain: f32,
/// What key is used to press ability /// What key is used to press ability
pub ability_key: AbilityKey, pub ability_info: AbilityInfo,
} }
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -68,7 +68,7 @@ impl CharacterBehavior for Data {
handle_move(data, &mut update, 0.4); handle_move(data, &mut update, 0.4);
handle_jump(data, &mut update); handle_jump(data, &mut update);
if !ability_key_is_pressed(data, self.static_data.ability_key) { if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
handle_interrupt(data, &mut update, false); handle_interrupt(data, &mut update, false);
match update.character { match update.character {
CharacterState::BasicBeam(_) => {}, CharacterState::BasicBeam(_) => {},
@ -78,11 +78,6 @@ impl CharacterBehavior for Data {
} }
} }
if unwrap_tool_data(data).is_none() {
update.character = CharacterState::Idle;
return update;
}
match self.stage_section { match self.stage_section {
StageSection::Buildup => { StageSection::Buildup => {
if self.timer < self.static_data.buildup_duration { if self.timer < self.static_data.buildup_duration {
@ -119,7 +114,7 @@ impl CharacterBehavior for Data {
} }
}, },
StageSection::Cast => { StageSection::Cast => {
if ability_key_is_pressed(data, self.static_data.ability_key) if ability_key_is_pressed(data, self.static_data.ability_info.key)
&& (self.static_data.energy_drain <= f32::EPSILON && (self.static_data.energy_drain <= f32::EPSILON
|| update.energy.current() > 0) || update.energy.current() > 0)
{ {

View File

@ -30,7 +30,7 @@ pub struct StaticData {
/// Max angle (45.0 will give you a 90.0 angle window) /// Max angle (45.0 will give you a 90.0 angle window)
pub max_angle: f32, pub max_angle: f32,
/// What key is used to press ability /// What key is used to press ability
pub ability_key: AbilityKey, pub ability_info: AbilityInfo,
} }
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -52,7 +52,7 @@ impl CharacterBehavior for Data {
handle_move(data, &mut update, 0.7); handle_move(data, &mut update, 0.7);
handle_jump(data, &mut update); handle_jump(data, &mut update);
if !ability_key_is_pressed(data, self.static_data.ability_key) { if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
handle_interrupt(data, &mut update, false); handle_interrupt(data, &mut update, false);
match update.character { match update.character {
CharacterState::BasicMelee(_) => {}, CharacterState::BasicMelee(_) => {},

View File

@ -23,7 +23,7 @@ pub struct StaticData {
pub projectile_gravity: Option<Gravity>, pub projectile_gravity: Option<Gravity>,
pub projectile_speed: f32, pub projectile_speed: f32,
/// What key is used to press ability /// What key is used to press ability
pub ability_key: AbilityKey, pub ability_info: AbilityInfo,
/// Whether or not the ability can auto continue /// Whether or not the ability can auto continue
pub can_continue: bool, pub can_continue: bool,
} }
@ -50,7 +50,7 @@ impl CharacterBehavior for Data {
handle_move(data, &mut update, 0.3); handle_move(data, &mut update, 0.3);
handle_jump(data, &mut update); handle_jump(data, &mut update);
if !ability_key_is_pressed(data, self.static_data.ability_key) { if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
handle_interrupt(data, &mut update, false); handle_interrupt(data, &mut update, false);
match update.character { match update.character {
CharacterState::BasicRanged(_) => {}, CharacterState::BasicRanged(_) => {},
@ -103,7 +103,7 @@ impl CharacterBehavior for Data {
..*self ..*self
}); });
} else if self.timer < self.static_data.recover_duration { } else if self.timer < self.static_data.recover_duration {
if ability_key_is_pressed(data, self.static_data.ability_key) { if ability_key_is_pressed(data, self.static_data.ability_info.key) {
// Recovers // Recovers
update.character = CharacterState::BasicRanged(Data { update.character = CharacterState::BasicRanged(Data {
timer: self timer: self

View File

@ -44,7 +44,7 @@ pub struct StaticData {
/// How long the state has until exiting /// How long the state has until exiting
pub recover_duration: Duration, pub recover_duration: Duration,
/// What key is used to press ability /// What key is used to press ability
pub ability_key: AbilityKey, pub ability_info: AbilityInfo,
} }
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -68,7 +68,7 @@ impl CharacterBehavior for Data {
handle_move(data, &mut update, 0.7); handle_move(data, &mut update, 0.7);
handle_jump(data, &mut update); handle_jump(data, &mut update);
if !ability_key_is_pressed(data, self.static_data.ability_key) { if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
handle_interrupt(data, &mut update, false); handle_interrupt(data, &mut update, false);
match update.character { match update.character {
CharacterState::ChargedMelee(_) => {}, CharacterState::ChargedMelee(_) => {},
@ -80,7 +80,7 @@ impl CharacterBehavior for Data {
match self.stage_section { match self.stage_section {
StageSection::Charge => { StageSection::Charge => {
if ability_key_is_pressed(data, self.static_data.ability_key) if ability_key_is_pressed(data, self.static_data.ability_info.key)
&& update.energy.current() as f32 >= self.static_data.energy_cost && update.energy.current() as f32 >= self.static_data.energy_cost
&& self.timer < self.static_data.charge_duration && self.timer < self.static_data.charge_duration
{ {
@ -107,7 +107,7 @@ impl CharacterBehavior for Data {
* self.static_data.speed) as i32, * self.static_data.speed) as i32,
source: EnergySource::Ability, source: EnergySource::Ability,
}); });
} else if ability_key_is_pressed(data, self.static_data.ability_key) } else if ability_key_is_pressed(data, self.static_data.ability_info.key)
&& update.energy.current() as f32 >= self.static_data.energy_cost && update.energy.current() as f32 >= self.static_data.energy_cost
{ {
// Maintains charge // Maintains charge

View File

@ -46,7 +46,7 @@ pub struct StaticData {
/// Move speed efficiency /// Move speed efficiency
pub move_speed: f32, pub move_speed: f32,
/// What key is used to press ability /// What key is used to press ability
pub ability_key: AbilityKey, pub ability_info: AbilityInfo,
} }
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -68,7 +68,7 @@ impl CharacterBehavior for Data {
handle_move(data, &mut update, self.static_data.move_speed); handle_move(data, &mut update, self.static_data.move_speed);
handle_jump(data, &mut update); handle_jump(data, &mut update);
if !ability_key_is_pressed(data, self.static_data.ability_key) { if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
handle_interrupt(data, &mut update, false); handle_interrupt(data, &mut update, false);
match update.character { match update.character {
CharacterState::ChargedRanged(_) => {}, CharacterState::ChargedRanged(_) => {},
@ -99,7 +99,7 @@ impl CharacterBehavior for Data {
} }
}, },
StageSection::Charge => { StageSection::Charge => {
if !ability_key_is_pressed(data, self.static_data.ability_key) && !self.exhausted { if !ability_key_is_pressed(data, self.static_data.ability_info.key) && !self.exhausted {
let charge_frac = (self.timer.as_secs_f32() let charge_frac = (self.timer.as_secs_f32()
/ self.static_data.charge_duration.as_secs_f32()) / self.static_data.charge_duration.as_secs_f32())
.min(1.0); .min(1.0);
@ -156,7 +156,7 @@ impl CharacterBehavior for Data {
..*self ..*self
}); });
} else if self.timer < self.static_data.charge_duration } else if self.timer < self.static_data.charge_duration
&& ability_key_is_pressed(data, self.static_data.ability_key) && ability_key_is_pressed(data, self.static_data.ability_info.key)
{ {
// Charges // Charges
update.character = CharacterState::ChargedRanged(Data { update.character = CharacterState::ChargedRanged(Data {
@ -176,7 +176,7 @@ impl CharacterBehavior for Data {
* self.static_data.speed) as i32, * self.static_data.speed) as i32,
source: EnergySource::Ability, source: EnergySource::Ability,
}); });
} else if ability_key_is_pressed(data, self.static_data.ability_key) { } else if ability_key_is_pressed(data, self.static_data.ability_info.key) {
// Holds charge // Holds charge
update.character = CharacterState::ChargedRanged(Data { update.character = CharacterState::ChargedRanged(Data {
timer: self timer: self

View File

@ -98,7 +98,7 @@ pub struct StaticData {
/// Whether the state can be interrupted by other abilities /// Whether the state can be interrupted by other abilities
pub is_interruptible: bool, pub is_interruptible: bool,
/// What key is used to press ability /// What key is used to press ability
pub ability_key: AbilityKey, pub ability_info: AbilityInfo,
} }
/// A sequence of attacks that can incrementally become faster and more /// A sequence of attacks that can incrementally become faster and more
/// damaging. /// damaging.
@ -125,7 +125,7 @@ impl CharacterBehavior for Data {
handle_orientation(data, &mut update, 1.0); handle_orientation(data, &mut update, 1.0);
handle_move(data, &mut update, 0.3); handle_move(data, &mut update, 0.3);
if !ability_key_is_pressed(data, self.static_data.ability_key) { if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
handle_interrupt(data, &mut update, self.static_data.is_interruptible); handle_interrupt(data, &mut update, self.static_data.is_interruptible);
if let CharacterState::Roll(roll) = &mut update.character { if let CharacterState::Roll(roll) = &mut update.character {
roll.was_combo = Some((self.stage, self.combo)); roll.was_combo = Some((self.stage, self.combo));
@ -259,7 +259,7 @@ impl CharacterBehavior for Data {
StageSection::Recover => { StageSection::Recover => {
if self.timer < self.static_data.stage_data[stage_index].base_recover_duration { if self.timer < self.static_data.stage_data[stage_index].base_recover_duration {
// Recovers // Recovers
if ability_key_is_pressed(data, self.static_data.ability_key) { if ability_key_is_pressed(data, self.static_data.ability_info.key) {
// Checks if state will transition to next stage after recover // Checks if state will transition to next stage after recover
update.character = CharacterState::ComboMelee(Data { update.character = CharacterState::ComboMelee(Data {
static_data: self.static_data.clone(), static_data: self.static_data.clone(),

View File

@ -47,7 +47,7 @@ pub struct StaticData {
/// Whether the state can be interrupted by other abilities /// Whether the state can be interrupted by other abilities
pub is_interruptible: bool, pub is_interruptible: bool,
/// What key is used to press ability /// What key is used to press ability
pub ability_key: AbilityKey, pub ability_info: AbilityInfo,
} }
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -73,7 +73,7 @@ impl CharacterBehavior for Data {
handle_orientation(data, &mut update, 1.0); handle_orientation(data, &mut update, 1.0);
handle_move(data, &mut update, 0.1); handle_move(data, &mut update, 0.1);
if !ability_key_is_pressed(data, self.static_data.ability_key) { if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
handle_interrupt(data, &mut update, self.static_data.is_interruptible); handle_interrupt(data, &mut update, self.static_data.is_interruptible);
match update.character { match update.character {
CharacterState::DashMelee(_) => {}, CharacterState::DashMelee(_) => {},
@ -97,7 +97,7 @@ impl CharacterBehavior for Data {
} else { } else {
// Transitions to charge section of stage // Transitions to charge section of stage
update.character = CharacterState::DashMelee(Data { update.character = CharacterState::DashMelee(Data {
auto_charge: !ability_key_is_pressed(data, self.static_data.ability_key), auto_charge: !ability_key_is_pressed(data, self.static_data.ability_info.key),
timer: Duration::default(), timer: Duration::default(),
stage_section: StageSection::Charge, stage_section: StageSection::Charge,
..*self ..*self
@ -107,7 +107,7 @@ impl CharacterBehavior for Data {
StageSection::Charge => { StageSection::Charge => {
if (self.static_data.infinite_charge if (self.static_data.infinite_charge
|| self.timer < self.static_data.charge_duration) || self.timer < self.static_data.charge_duration)
&& (ability_key_is_pressed(data, self.static_data.ability_key) && (ability_key_is_pressed(data, self.static_data.ability_info.key)
|| (self.auto_charge && self.timer < self.static_data.charge_duration)) || (self.auto_charge && self.timer < self.static_data.charge_duration))
&& update.energy.current() > 0 && update.energy.current() > 0
{ {

View File

@ -36,7 +36,7 @@ pub struct StaticData {
/// Affects how high the player leaps /// Affects how high the player leaps
pub vertical_leap_strength: f32, pub vertical_leap_strength: f32,
/// What key is used to press ability /// What key is used to press ability
pub ability_key: AbilityKey, pub ability_info: AbilityInfo,
} }
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -58,7 +58,7 @@ impl CharacterBehavior for Data {
handle_move(data, &mut update, 0.3); handle_move(data, &mut update, 0.3);
handle_jump(data, &mut update); handle_jump(data, &mut update);
if !ability_key_is_pressed(data, self.static_data.ability_key) { if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
handle_interrupt(data, &mut update, false); handle_interrupt(data, &mut update, false);
match update.character { match update.character {
CharacterState::LeapMelee(_) => {}, CharacterState::LeapMelee(_) => {},

View File

@ -31,7 +31,7 @@ pub struct StaticData {
pub projectile_gravity: Option<Gravity>, pub projectile_gravity: Option<Gravity>,
pub projectile_speed: f32, pub projectile_speed: f32,
/// What key is used to press ability /// What key is used to press ability
pub ability_key: AbilityKey, pub ability_info: AbilityInfo,
} }
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -53,7 +53,7 @@ impl CharacterBehavior for Data {
handle_move(data, &mut update, 1.0); handle_move(data, &mut update, 1.0);
handle_jump(data, &mut update); handle_jump(data, &mut update);
if !ability_key_is_pressed(data, self.static_data.ability_key) { if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
handle_interrupt(data, &mut update, false); handle_interrupt(data, &mut update, false);
match update.character { match update.character {
CharacterState::RepeaterRanged(_) => {}, CharacterState::RepeaterRanged(_) => {},

View File

@ -41,7 +41,7 @@ pub struct StaticData {
/// Movement speed efficiency /// Movement speed efficiency
pub move_efficiency: f32, pub move_efficiency: f32,
/// What key is used to press ability /// What key is used to press ability
pub ability_key: AbilityKey, pub ability_info: AbilityInfo,
} }
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -60,7 +60,7 @@ impl CharacterBehavior for Data {
let mut update = StateUpdate::from(data); let mut update = StateUpdate::from(data);
handle_move(data, &mut update, self.static_data.move_efficiency); handle_move(data, &mut update, self.static_data.move_efficiency);
if !ability_key_is_pressed(data, self.static_data.ability_key) { if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
handle_interrupt(data, &mut update, false); handle_interrupt(data, &mut update, false);
match update.character { match update.character {
CharacterState::Shockwave(_) => {}, CharacterState::Shockwave(_) => {},

View File

@ -42,7 +42,7 @@ pub struct StaticData {
/// Number of spins /// Number of spins
pub num_spins: u32, pub num_spins: u32,
/// What key is used to press ability /// What key is used to press ability
pub ability_key: AbilityKey, pub ability_info: AbilityInfo,
} }
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -75,7 +75,7 @@ impl CharacterBehavior for Data {
}, },
} }
if !ability_key_is_pressed(data, self.static_data.ability_key) { if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
handle_interrupt(data, &mut update, self.static_data.is_interruptible); handle_interrupt(data, &mut update, self.static_data.is_interruptible);
match update.character { match update.character {
CharacterState::SpinMelee(_) => {}, CharacterState::SpinMelee(_) => {},
@ -176,7 +176,7 @@ impl CharacterBehavior for Data {
} else if update.energy.current() as f32 >= self.static_data.energy_cost } else if update.energy.current() as f32 >= self.static_data.energy_cost
&& (self.spins_remaining != 0 && (self.spins_remaining != 0
|| (self.static_data.is_infinite || (self.static_data.is_infinite
&& ability_key_is_pressed(data, self.static_data.ability_key))) && ability_key_is_pressed(data, self.static_data.ability_info.key)))
{ {
let new_spins_remaining = if self.static_data.is_infinite { let new_spins_remaining = if self.static_data.is_infinite {
self.spins_remaining self.spins_remaining

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
comp::{ comp::{
inventory::slot::EquipSlot, inventory::slot::EquipSlot,
item::{Hands, ItemKind, Tool}, item::{Hands, ItemKind, Tool, ToolKind},
quadruped_low, quadruped_medium, theropod, Body, CharacterState, LoadoutManip, StateUpdate, quadruped_low, quadruped_medium, theropod, Body, CharacterState, LoadoutManip, StateUpdate,
}, },
consts::{FRIC_GROUND, GRAVITY}, consts::{FRIC_GROUND, GRAVITY},
@ -407,12 +407,12 @@ pub fn handle_ability1_input(data: &JoinData, update: &mut StateUpdate) {
.equipped(EquipSlot::Mainhand) .equipped(EquipSlot::Mainhand)
.map(|i| &i.item_config_expect().abilities.primary) .map(|i| &i.item_config_expect().abilities.primary)
.map(|a| { .map(|a| {
let tool = unwrap_tool_data(data).map(|t| t.kind); let tool = unwrap_tool_data(data, EquipSlot::Mainhand).map(|t| t.kind);
a.clone().adjusted_by_skills(&data.stats.skill_set, tool) a.clone().adjusted_by_skills(&data.stats.skill_set, tool)
}) })
.filter(|ability| ability.requirements_paid(data, update)) .filter(|ability| ability.requirements_paid(data, update))
{ {
update.character = (&ability, AbilityKey::Mouse1).into(); update.character = (&ability, AbilityInfo::from_key(data, AbilityKey::Mouse1, false)).into();
} }
} }
} }
@ -450,12 +450,12 @@ pub fn handle_ability2_input(data: &JoinData, update: &mut StateUpdate) {
.equipped(equip_slot) .equipped(equip_slot)
.map(|i| &i.item_config_expect().abilities.secondary) .map(|i| &i.item_config_expect().abilities.secondary)
.map(|a| { .map(|a| {
let tool = unwrap_tool_data(data).map(|t| t.kind); let tool = unwrap_tool_data(data, equip_slot).map(|t| t.kind);
a.clone().adjusted_by_skills(&data.stats.skill_set, tool) a.clone().adjusted_by_skills(&data.stats.skill_set, tool)
}) })
.filter(|ability| ability.requirements_paid(data, update)) .filter(|ability| ability.requirements_paid(data, update))
{ {
update.character = (&ability, AbilityKey::Mouse2).into(); update.character = (&ability, AbilityInfo::from_key(data, AbilityKey::Mouse2, matches!(equip_slot, EquipSlot::Offhand))).into();
} }
} }
} }
@ -472,12 +472,12 @@ pub fn handle_ability3_input(data: &JoinData, update: &mut StateUpdate) {
.then_some(a) .then_some(a)
}) })
.map(|a| { .map(|a| {
let tool = unwrap_tool_data(data).map(|t| t.kind); let tool = unwrap_tool_data(data, EquipSlot::Mainhand).map(|t| t.kind);
a.clone().adjusted_by_skills(&data.stats.skill_set, tool) a.clone().adjusted_by_skills(&data.stats.skill_set, tool)
}) })
.filter(|ability| ability.requirements_paid(data, update)) .filter(|ability| ability.requirements_paid(data, update))
{ {
update.character = (&ability, AbilityKey::Skill1).into(); update.character = (&ability, AbilityInfo::from_key(data, AbilityKey::Skill1, false)).into();
} }
} }
} }
@ -519,12 +519,12 @@ pub fn handle_ability4_input(data: &JoinData, update: &mut StateUpdate) {
.then_some(a) .then_some(a)
}) })
.map(|a| { .map(|a| {
let tool = unwrap_tool_data(data).map(|t| t.kind); let tool = unwrap_tool_data(data, equip_slot).map(|t| t.kind);
a.clone().adjusted_by_skills(&data.stats.skill_set, tool) a.clone().adjusted_by_skills(&data.stats.skill_set, tool)
}) })
.filter(|ability| ability.requirements_paid(data, update)) .filter(|ability| ability.requirements_paid(data, update))
{ {
update.character = (&ability, AbilityKey::Skill1).into(); update.character = (&ability, AbilityInfo::from_key(data, AbilityKey::Skill2, matches!(equip_slot, EquipSlot::Offhand))).into();
} }
} }
} }
@ -546,26 +546,26 @@ pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
.filter(|ability| ability.requirements_paid(data, update)) .filter(|ability| ability.requirements_paid(data, update))
{ {
if data.character.is_wield() { if data.character.is_wield() {
update.character = (&ability, AbilityKey::Dodge).into(); update.character = (&ability, AbilityInfo::from_key(data, AbilityKey::Dodge, false)).into();
if let CharacterState::Roll(roll) = &mut update.character { if let CharacterState::Roll(roll) = &mut update.character {
roll.was_wielded = true; roll.was_wielded = true;
} }
} else if data.character.is_stealthy() { } else if data.character.is_stealthy() {
update.character = (&ability, AbilityKey::Dodge).into(); update.character = (&ability, AbilityInfo::from_key(data, AbilityKey::Dodge, false)).into();
if let CharacterState::Roll(roll) = &mut update.character { if let CharacterState::Roll(roll) = &mut update.character {
roll.was_sneak = true; roll.was_sneak = true;
} }
} else { } else {
update.character = (&ability, AbilityKey::Dodge).into(); update.character = (&ability, AbilityInfo::from_key(data, AbilityKey::Dodge, false)).into();
} }
} }
} }
} }
pub fn unwrap_tool_data<'a>(data: &'a JoinData) -> Option<&'a Tool> { pub fn unwrap_tool_data<'a>(data: &'a JoinData, equip_slot: EquipSlot) -> Option<&'a Tool> {
if let Some(ItemKind::Tool(tool)) = data if let Some(ItemKind::Tool(tool)) = data
.inventory .inventory
.equipped(EquipSlot::Mainhand) .equipped(equip_slot)
.map(|i| i.kind()) .map(|i| i.kind())
{ {
Some(&tool) Some(&tool)
@ -658,3 +658,47 @@ impl MovementDirection {
.unwrap_or_default() .unwrap_or_default()
} }
} }
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct AbilityInfo {
pub tool: Option<ToolKind>,
pub hand: Option<HandInfo>,
pub key: AbilityKey,
}
impl AbilityInfo {
pub fn from_key(data: &JoinData, key: AbilityKey, from_offhand: bool) -> Self {
let tool_data = if from_offhand {
unwrap_tool_data(data, EquipSlot::Offhand)
} else {
unwrap_tool_data(data, EquipSlot::Mainhand)
};
let (tool, hand) = if from_offhand {
(tool_data.map(|t| t.kind), Some(HandInfo::OffHand))
} else {
(tool_data.map(|t| t.kind), tool_data.map(|t| HandInfo::from_main_tool(t)))
};
Self {
tool,
hand,
key,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub enum HandInfo {
TwoHanded,
MainHand,
OffHand,
}
impl HandInfo {
pub fn from_main_tool(tool: &Tool) -> Self {
match tool.hands {
Hands::TwoHand => Self::TwoHanded,
Hands::OneHand => Self::MainHand,
}
}
}