Make durations and damage depend on weapon type

This commit is contained in:
timokoesters 2020-03-15 14:34:17 +01:00
parent 598a4c6cbb
commit 447617dc69
18 changed files with 83 additions and 96 deletions

View File

@ -5,10 +5,6 @@ Item(
ToolData (
kind: Hammer,
equip_time_millis: 1000,
attack_buildup_millis: 700,
attack_recover_millis: 100,
range: 3,
base_damage: 10,
)
)
)

View File

@ -5,10 +5,6 @@ Item(
ToolData (
kind: Staff,
equip_time_millis: 800,
attack_buildup_millis: 400,
attack_recover_millis: 300,
range: 3,
base_damage: 10,
)
),
)

View File

@ -5,10 +5,6 @@ Item(
ToolData (
kind: Axe,
equip_time_millis: 1000,
attack_buildup_millis: 700,
attack_recover_millis: 100,
range: 3,
base_damage: 10,
)
),
)

View File

@ -5,10 +5,6 @@ Item(
ToolData (
kind: Bow,
equip_time_millis: 800,
attack_buildup_millis: 0,
attack_recover_millis: 800,
range: 3,
base_damage: 10,
)
),
)

View File

@ -5,10 +5,6 @@ Item(
ToolData (
kind: Dagger,
equip_time_millis: 300,
attack_buildup_millis: 100,
attack_recover_millis: 400,
range: 3,
base_damage: 10,
)
),
)

View File

@ -5,10 +5,6 @@ Item(
ToolData (
kind: Hammer,
equip_time_millis: 1000,
attack_buildup_millis: 700,
attack_recover_millis: 100,
range: 3,
base_damage: 10,
)
),
)

View File

@ -5,10 +5,6 @@ Item(
ToolData (
kind: Sword(Rapier),
equip_time_millis: 800,
attack_buildup_millis: 100,
attack_recover_millis: 500,
range: 3,
base_damage: 10,
)
),
)

View File

@ -10,14 +10,15 @@ pub enum CharacterAbility {
BasicAttack {
buildup_duration: Duration,
recover_duration: Duration,
base_damage: u32,
},
BasicBlock,
Roll,
ChargeAttack,
TimedCombo {
tool: ToolData,
buildup_duration: Duration,
recover_duration: Duration,
base_damage: u32,
},
}
@ -47,10 +48,12 @@ impl From<CharacterAbility> for CharacterState {
CharacterAbility::BasicAttack {
buildup_duration,
recover_duration,
base_damage,
} => CharacterState::BasicAttack(basic_attack::Data {
exhausted: false,
buildup_duration,
recover_duration,
base_damage,
}),
CharacterAbility::BasicBlock { .. } => CharacterState::BasicBlock,
CharacterAbility::Roll { .. } => CharacterState::Roll(roll::Data {
@ -62,16 +65,16 @@ impl From<CharacterAbility> for CharacterState {
})
},
CharacterAbility::TimedCombo {
tool,
buildup_duration,
recover_duration,
base_damage,
} => CharacterState::TimedCombo(timed_combo::Data {
tool,
buildup_duration,
recover_duration,
stage: 0,
stage_exhausted: false,
stage_time_active: Duration::default(),
base_damage,
}),
}
}

View File

@ -29,7 +29,7 @@ pub enum CharacterState {
/// Player is busy equipping or unequipping weapons
Equipping(equipping::Data),
/// Player is holding a weapon and can perform other actions
Wielding(wielding::Data),
Wielding,
/// Player rushes forward and slams an enemy with their weapon
ChargeAttack(charge_attack::Data),
/// A dodge where player can roll
@ -47,7 +47,7 @@ pub enum CharacterState {
impl CharacterState {
pub fn is_wield(&self) -> bool {
match self {
CharacterState::Wielding(_)
CharacterState::Wielding
| CharacterState::BasicAttack(_)
| CharacterState::TimedCombo(_)
| CharacterState::BasicBlock => true,

View File

@ -37,41 +37,37 @@ impl ToolData {
use ToolKind::*;
match self.kind {
Sword(_) => vec![TimedCombo {
buildup_duration: Duration::from_millis(500),
recover_duration: Duration::from_millis(1000),
tool: *self,
Sword(_) => vec![BasicAttack {
buildup_duration: Duration::from_millis(100),
recover_duration: Duration::from_millis(500),
base_damage: 60,
}],
Axe => vec![BasicAttack {
buildup_duration: Duration::from_millis(1000),
recover_duration: Duration::from_millis(500),
buildup_duration: Duration::from_millis(700),
recover_duration: Duration::from_millis(100),
base_damage: 80,
}],
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),
buildup_duration: Duration::from_millis(700),
recover_duration: Duration::from_millis(300),
base_damage: 100,
}],
Bow => vec![],
Dagger => vec![BasicAttack {
buildup_duration: Duration::from_millis(1000),
recover_duration: Duration::from_millis(500),
buildup_duration: Duration::from_millis(100),
recover_duration: Duration::from_millis(400),
base_damage: 50,
}],
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),
buildup_duration: Duration::from_millis(400),
recover_duration: Duration::from_millis(300),
base_damage: 70,
}],
Shield => vec![],
Debug(kind) => match kind {
Boost => vec![],
Possess => vec![],
},
_ => vec![],
}
}
}
@ -125,18 +121,24 @@ pub enum Ingredient {
pub struct ToolData {
pub kind: ToolKind,
equip_time_millis: u64,
attack_buildup_millis: u64,
attack_recover_millis: u64,
range: u32,
pub base_damage: u32,
// TODO: item specific abilities
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ItemKind {
/// Something wieldable
Tool(ToolData),
Armor { kind: Armor, power: u32 },
Consumable { kind: Consumable, effect: Effect },
Utility { kind: Utility },
Armor {
kind: Armor,
power: u32,
},
Consumable {
kind: Consumable,
effect: Effect,
},
Utility {
kind: Utility,
},
Ingredient(Ingredient),
}

View File

@ -134,7 +134,7 @@ impl Stats {
}
// TODO: Delete this once stat points will be a thing
pub fn update_max_hp(&mut self) { self.health.set_maximum(27 + 15 * self.level.amount); }
pub fn update_max_hp(&mut self) { self.health.set_maximum(200 + 47 * self.level.amount); }
}
impl Stats {

View File

@ -11,6 +11,8 @@ pub struct Data {
pub buildup_duration: Duration,
/// How long the state has until exiting
pub recover_duration: Duration,
/// Base damage
pub base_damage: u32,
/// Whether the attack can deal more damage
pub exhausted: bool,
}
@ -37,6 +39,7 @@ impl CharacterBehavior for Data {
.checked_sub(Duration::from_secs_f32(data.dt.0))
.unwrap_or_default(),
recover_duration: self.recover_duration,
base_damage: self.base_damage,
exhausted: false,
});
}
@ -44,7 +47,7 @@ impl CharacterBehavior for Data {
else if !self.exhausted {
if let Some(tool) = unwrap_tool_data(data) {
data.updater.insert(data.entity, Attacking {
base_damage: tool.base_damage,
base_damage: self.base_damage,
applied: false,
hit_count: 0,
});
@ -53,6 +56,7 @@ impl CharacterBehavior for Data {
update.character = CharacterState::BasicAttack(Data {
buildup_duration: self.buildup_duration,
recover_duration: self.recover_duration,
base_damage: self.base_damage,
exhausted: true,
});
}
@ -64,13 +68,14 @@ impl CharacterBehavior for Data {
.recover_duration
.checked_sub(Duration::from_secs_f32(data.dt.0))
.unwrap_or_default(),
base_damage: self.base_damage,
exhausted: true,
});
}
// Done
else {
if let Some(tool) = unwrap_tool_data(data) {
update.character = CharacterState::Wielding(wielding::Data { tool });
update.character = CharacterState::Wielding;
// Make sure attack component is removed
data.updater.remove::<Attacking>(data.entity);
} else {

View File

@ -31,7 +31,7 @@ impl CharacterBehavior for Data {
if self.time_left == Duration::default() {
// Wield delay has expired
update.character = CharacterState::Wielding(wielding::Data { tool: self.tool });
update.character = CharacterState::Wielding;
} else {
// Wield delay hasn't expired yet
// Update wield delay

View File

@ -18,6 +18,7 @@ impl CharacterBehavior for Data {
local_events: VecDeque::new(),
server_events: VecDeque::new(),
};
handle_move(data, &mut update);
handle_jump(data, &mut update);
handle_wield(data, &mut update);

View File

@ -1,6 +1,5 @@
use crate::{
comp::{Attacking, CharacterState, EnergySource, StateUpdate, ToolData},
states::wielding,
comp::{Attacking, CharacterState, EnergySource, StateUpdate},
sys::character_behavior::{CharacterBehavior, JoinData},
};
use std::{collections::VecDeque, time::Duration};
@ -16,8 +15,8 @@ pub struct Data {
pub recover_duration: Duration,
/// Tracks how long current stage has been active
pub stage_time_active: Duration,
/// `ToolData` to be sent to `Attacking` component
pub tool: ToolData,
/// Base damage
pub base_damage: u32,
}
impl CharacterBehavior for Data {
@ -44,17 +43,17 @@ impl CharacterBehavior for Data {
if data.inputs.primary.is_just_pressed() {
println!("Failed");
// They failed, go back to `Wielding`
update.character = CharacterState::Wielding(wielding::Data { tool: self.tool });
update.character = CharacterState::Wielding;
}
// Keep updating
else {
update.character = CharacterState::TimedCombo(Data {
tool: self.tool,
stage: self.stage,
buildup_duration: self.buildup_duration,
recover_duration: self.recover_duration,
stage_exhausted: false,
stage_time_active: new_stage_time_active,
base_damage: self.base_damage,
});
}
}
@ -62,18 +61,18 @@ impl CharacterBehavior for Data {
else if !self.stage_exhausted {
// Swing hits
data.updater.insert(data.entity, Attacking {
base_damage: self.tool.base_damage,
base_damage: self.base_damage,
applied: false,
hit_count: 0,
});
update.character = CharacterState::TimedCombo(Data {
tool: self.tool,
stage: self.stage,
buildup_duration: self.buildup_duration,
recover_duration: self.recover_duration,
stage_exhausted: true,
stage_time_active: new_stage_time_active,
base_damage: self.base_damage,
});
}
// Swing recovery window
@ -87,12 +86,12 @@ impl CharacterBehavior for Data {
if data.inputs.primary.is_just_pressed() {
println!("Transition");
update.character = CharacterState::TimedCombo(Data {
tool: self.tool,
stage: self.stage + 1,
buildup_duration: self.buildup_duration,
recover_duration: self.recover_duration,
stage_exhausted: true,
stage_time_active: Duration::default(),
base_damage: self.base_damage,
});
}
// Player didn't click this frame
@ -100,19 +99,19 @@ impl CharacterBehavior for Data {
// Update state
println!("Missed");
update.character = CharacterState::TimedCombo(Data {
tool: self.tool,
stage: self.stage,
buildup_duration: self.buildup_duration,
recover_duration: self.recover_duration,
stage_exhausted: true,
stage_time_active: new_stage_time_active,
base_damage: self.base_damage,
});
}
}
// Stage expired but missed transition to next stage
else {
// Back to `Wielding`
update.character = CharacterState::Wielding(wielding::Data { tool: self.tool });
update.character = CharacterState::Wielding;
// Make sure attack component is removed
data.updater.remove::<Attacking>(data.entity);
}
@ -121,12 +120,12 @@ impl CharacterBehavior for Data {
else {
println!("Success!");
// Back to `Wielding`
update.character = CharacterState::Wielding(wielding::Data { tool: self.tool });
update.character = CharacterState::Wielding;
// Make sure attack component is removed
data.updater.remove::<Attacking>(data.entity);
}
// Subtract energy on successful hit
// Grant energy on successful hit
if let Some(attack) = data.attacking {
if attack.applied && attack.hit_count > 0 {
println!("Hit");

View File

@ -1,14 +1,11 @@
use super::utils::*;
use crate::{
comp::{StateUpdate, ToolData},
comp::StateUpdate,
sys::character_behavior::{CharacterBehavior, JoinData},
};
use std::collections::VecDeque;
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
pub struct Data {
/// The weapon being wielded
pub tool: ToolData,
}
pub struct Data;
impl CharacterBehavior for Data {
fn behavior(&self, data: &JoinData) -> StateUpdate {

View File

@ -172,17 +172,17 @@ impl<'a> System<'a> for Sys {
}
let mut state_update = match j.character {
CharacterState::Idle => states::idle::Data::behavior(&states::idle::Data, &j),
CharacterState::Climb => states::climb::Data::behavior(&states::climb::Data, &j),
CharacterState::Glide => states::glide::Data::behavior(&states::glide::Data, &j),
CharacterState::Idle => states::idle::Data.behavior(&j),
CharacterState::Climb => states::climb::Data.behavior(&j),
CharacterState::Glide => states::glide::Data.behavior(&j),
CharacterState::Sit => states::sit::Data::behavior(&states::sit::Data, &j),
CharacterState::BasicBlock => states::basic_block::Data::behavior(&states::basic_block::Data, &j),
CharacterState::Roll (data) => data.behavior(&j),
CharacterState::Wielding (data) => data.behavior(&j),
CharacterState::Equipping (data) => data.behavior(&j),
CharacterState::ChargeAttack (data) => data.behavior(&j),
CharacterState::TripleStrike (data) => data.behavior(&j),
CharacterState::BasicAttack (data) => data.behavior(&j),
CharacterState::BasicBlock => states::basic_block::Data.behavior(&j),
CharacterState::Roll(data) => data.behavior(&j),
CharacterState::Wielding => states::wielding::Data.behavior(&j),
CharacterState::Equipping(data) => data.behavior(&j),
CharacterState::ChargeAttack(data) => data.behavior(&j),
CharacterState::TripleStrike(data) => data.behavior(&j),
CharacterState::BasicAttack(data) => data.behavior(&j),
CharacterState::TimedCombo(data) => data.behavior(&j),
// Do not use default match.

View File

@ -215,7 +215,9 @@ impl<'a> System<'a> for Sys {
loadout = comp::Loadout {
active_item: Some(comp::ItemConfig {
item: assets::load_expect_cloned("common.items.weapons.hammer_1"),
primary_ability: None,
primary_ability: None, /* TODO: when implementing this, make sure
* to adjust the base damage (see todo
* below) */
secondary_ability: None,
block_ability: None,
dodge_ability: None,
@ -228,14 +230,20 @@ impl<'a> System<'a> for Sys {
}
stats.update_max_hp();
stats
.health
.set_to(stats.health.maximum(), comp::HealthSource::Revive);
// TODO: This code sets an appropriate base_damage for the enemy. This doesn't
// work because the damage is now saved in an ability
/*
if let Some(item::ItemKind::Tool(item::ToolData { base_damage, .. })) =
&mut loadout.active_item.map(|i| i.item.kind)
{
*base_damage = stats.level.level() as u32 * 3;
}
*/
server_emitter.emit(ServerEvent::CreateNpc {
pos: Pos(entity.pos),
stats,