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

View File

@ -44,7 +44,7 @@ pub struct StaticData {
/// Energy drained per
pub energy_drain: f32,
/// What key is used to press ability
pub ability_key: AbilityKey,
pub ability_info: AbilityInfo,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -68,7 +68,7 @@ impl CharacterBehavior for Data {
handle_move(data, &mut update, 0.4);
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);
match update.character {
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 {
StageSection::Buildup => {
if self.timer < self.static_data.buildup_duration {
@ -119,7 +114,7 @@ impl CharacterBehavior for Data {
}
},
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
|| 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)
pub max_angle: f32,
/// What key is used to press ability
pub ability_key: AbilityKey,
pub ability_info: AbilityInfo,
}
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -52,7 +52,7 @@ impl CharacterBehavior for Data {
handle_move(data, &mut update, 0.7);
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);
match update.character {
CharacterState::BasicMelee(_) => {},

View File

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

View File

@ -44,7 +44,7 @@ pub struct StaticData {
/// How long the state has until exiting
pub recover_duration: Duration,
/// What key is used to press ability
pub ability_key: AbilityKey,
pub ability_info: AbilityInfo,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -68,7 +68,7 @@ impl CharacterBehavior for Data {
handle_move(data, &mut update, 0.7);
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);
match update.character {
CharacterState::ChargedMelee(_) => {},
@ -80,7 +80,7 @@ impl CharacterBehavior for Data {
match self.stage_section {
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
&& self.timer < self.static_data.charge_duration
{
@ -107,7 +107,7 @@ impl CharacterBehavior for Data {
* self.static_data.speed) as i32,
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
{
// Maintains charge

View File

@ -46,7 +46,7 @@ pub struct StaticData {
/// Move speed efficiency
pub move_speed: f32,
/// What key is used to press ability
pub ability_key: AbilityKey,
pub ability_info: AbilityInfo,
}
#[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_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);
match update.character {
CharacterState::ChargedRanged(_) => {},
@ -99,7 +99,7 @@ impl CharacterBehavior for Data {
}
},
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()
/ self.static_data.charge_duration.as_secs_f32())
.min(1.0);
@ -156,7 +156,7 @@ impl CharacterBehavior for Data {
..*self
});
} 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
update.character = CharacterState::ChargedRanged(Data {
@ -176,7 +176,7 @@ impl CharacterBehavior for Data {
* self.static_data.speed) as i32,
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
update.character = CharacterState::ChargedRanged(Data {
timer: self

View File

@ -98,7 +98,7 @@ pub struct StaticData {
/// Whether the state can be interrupted by other abilities
pub is_interruptible: bool,
/// 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
/// damaging.
@ -125,7 +125,7 @@ impl CharacterBehavior for Data {
handle_orientation(data, &mut update, 1.0);
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);
if let CharacterState::Roll(roll) = &mut update.character {
roll.was_combo = Some((self.stage, self.combo));
@ -259,7 +259,7 @@ impl CharacterBehavior for Data {
StageSection::Recover => {
if self.timer < self.static_data.stage_data[stage_index].base_recover_duration {
// 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
update.character = CharacterState::ComboMelee(Data {
static_data: self.static_data.clone(),

View File

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

View File

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

View File

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

View File

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

View File

@ -42,7 +42,7 @@ pub struct StaticData {
/// Number of spins
pub num_spins: u32,
/// What key is used to press ability
pub ability_key: AbilityKey,
pub ability_info: AbilityInfo,
}
#[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);
match update.character {
CharacterState::SpinMelee(_) => {},
@ -176,7 +176,7 @@ impl CharacterBehavior for Data {
} else if update.energy.current() as f32 >= self.static_data.energy_cost
&& (self.spins_remaining != 0
|| (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 {
self.spins_remaining

View File

@ -1,7 +1,7 @@
use crate::{
comp::{
inventory::slot::EquipSlot,
item::{Hands, ItemKind, Tool},
item::{Hands, ItemKind, Tool, ToolKind},
quadruped_low, quadruped_medium, theropod, Body, CharacterState, LoadoutManip, StateUpdate,
},
consts::{FRIC_GROUND, GRAVITY},
@ -407,12 +407,12 @@ pub fn handle_ability1_input(data: &JoinData, update: &mut StateUpdate) {
.equipped(EquipSlot::Mainhand)
.map(|i| &i.item_config_expect().abilities.primary)
.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)
})
.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)
.map(|i| &i.item_config_expect().abilities.secondary)
.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)
})
.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)
})
.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)
})
.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)
})
.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)
})
.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))
{
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 {
roll.was_wielded = true;
}
} 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 {
roll.was_sneak = true;
}
} 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
.inventory
.equipped(EquipSlot::Mainhand)
.equipped(equip_slot)
.map(|i| i.kind())
{
Some(&tool)
@ -658,3 +658,47 @@ impl MovementDirection {
.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,
}
}
}