Split staff into 3 abilities

This commit is contained in:
timokoesters 2020-03-24 13:59:53 +01:00
parent 7a4f0fa9ac
commit 99e7e1f785
16 changed files with 89 additions and 40 deletions

View File

@ -83,8 +83,9 @@ impl CharacterAbility {
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
pub struct ItemConfig {
pub item: Item,
pub primary_ability: Option<CharacterAbility>,
pub secondary_ability: Option<CharacterAbility>,
pub ability1: Option<CharacterAbility>,
pub ability2: Option<CharacterAbility>,
pub ability3: Option<CharacterAbility>,
pub block_ability: Option<CharacterAbility>,
pub dodge_ability: Option<CharacterAbility>,
}

View File

@ -114,6 +114,7 @@ impl Default for Input {
pub struct ControllerInputs {
pub primary: Input,
pub secondary: Input,
pub ability3: Input,
pub sit: Input,
pub jump: Input,
pub roll: Input,
@ -141,6 +142,7 @@ impl ControllerInputs {
pub fn tick(&mut self, dt: Duration) {
self.primary.tick(dt);
self.secondary.tick(dt);
self.ability3.tick(dt);
self.sit.tick(dt);
self.jump.tick(dt);
self.roll.tick(dt);
@ -153,6 +155,10 @@ impl ControllerInputs {
self.swap_loadout.tick(dt);
self.charge.tick(dt);
}
pub fn holding_ability_key(&self) -> bool {
self.primary.is_pressed() || self.secondary.is_pressed() || self.ability3.is_pressed()
}
}
impl Controller {

View File

@ -121,10 +121,28 @@ impl ToolData {
BasicMelee {
buildup_duration: Duration::from_millis(0),
recover_duration: Duration::from_millis(300),
base_damage: 3,
base_damage: 1,
range: 10.0,
max_angle: 45.0,
},
BasicRanged {
projectile: Projectile {
hit_ground: vec![projectile::Effect::Vanish],
hit_wall: vec![projectile::Effect::Vanish],
hit_entity: vec![
projectile::Effect::Damage(HealthChange {
// TODO: This should not be fixed (?)
amount: -2,
cause: HealthSource::Projectile { owner: None },
}),
projectile::Effect::Vanish,
],
time_left: Duration::from_secs(20),
owner: None,
},
projectile_body: Body::Object(object::Body::BoltFire),
recover_duration: Duration::from_millis(500),
},
CastFireball {
projectile: Projectile {
hit_ground: vec![

View File

@ -31,12 +31,7 @@ impl Inventory {
pub fn len(&self) -> usize { self.slots.len() }
pub fn recount_items(&mut self) {
self.amount = 0;
for item in self.slots.iter() {
if let Some(item) = item {
self.amount += 1;
}
}
self.amount = self.slots.iter().filter(|i| i.is_some()).count() as u32;
}
/// Adds a new item to the first fitting group of the inventory or starts a

View File

@ -27,9 +27,7 @@ impl CharacterBehavior for Data {
handle_move(data, &mut update);
handle_jump(data, &mut update);
if !self.exhausted
&& (data.inputs.primary.is_pressed() | data.inputs.secondary.is_pressed())
{
if !self.exhausted && data.inputs.holding_ability_key() {
// Prepare (draw the bow)
update.character = CharacterState::BasicRanged(Data {
prepare_timer: self.prepare_timer + Duration::from_secs_f32(data.dt.0),

View File

@ -27,10 +27,8 @@ impl CharacterBehavior for Data {
handle_move(data, &mut update);
handle_jump(data, &mut update);
if !self.exhausted
&& (data.inputs.primary.is_pressed() | data.inputs.secondary.is_pressed())
{
// Prepare (draw the bow)
if !self.exhausted && data.inputs.holding_ability_key() {
// Prepare
update.character = CharacterState::CastFireball(Data {
prepare_timer: self.prepare_timer + Duration::from_secs_f32(data.dt.0),
recover_duration: self.recover_duration,

View File

@ -170,15 +170,14 @@ pub fn handle_jump(data: &JoinData, update: &mut StateUpdate) {
}
}
/// If `inputs.primary` is pressed and in `Wielding` state,
/// will attempt to go into `loadout.active_item.primary_ability`
pub fn handle_primary_input(data: &JoinData, update: &mut StateUpdate) {
/// Will attempt to go into `loadout.active_item.ability1`
pub fn handle_ability1_input(data: &JoinData, update: &mut StateUpdate) {
if data.inputs.primary.is_pressed() {
if let Some(ability) = data
.loadout
.active_item
.as_ref()
.and_then(|i| i.primary_ability.as_ref())
.and_then(|i| i.ability1.as_ref())
.filter(|ability| ability.requirements_paid(data, update))
{
update.character = ability.into();
@ -186,15 +185,29 @@ pub fn handle_primary_input(data: &JoinData, update: &mut StateUpdate) {
}
}
/// If `inputs.secondary` is pressed and in `Wielding` state,
/// will attempt to go into `loadout.active_item.secondary_ability`
pub fn handle_secondary_input(data: &JoinData, update: &mut StateUpdate) {
/// Will attempt to go into `loadout.active_item.ability2`
pub fn handle_ability2_input(data: &JoinData, update: &mut StateUpdate) {
if data.inputs.secondary.is_pressed() {
if let Some(ability) = data
.loadout
.active_item
.as_ref()
.and_then(|i| i.secondary_ability.as_ref())
.and_then(|i| i.ability2.as_ref())
.filter(|ability| ability.requirements_paid(data, update))
{
update.character = ability.into();
}
}
}
/// Will attempt to go into `loadout.active_item.ability3`
pub fn handle_ability3_input(data: &JoinData, update: &mut StateUpdate) {
if data.inputs.ability3.is_pressed() {
if let Some(ability) = data
.loadout
.active_item
.as_ref()
.and_then(|i| i.ability3.as_ref())
.filter(|ability| ability.requirements_paid(data, update))
{
update.character = ability.into();

View File

@ -17,8 +17,9 @@ impl CharacterBehavior for Data {
handle_glide(&data, &mut update);
handle_unwield(&data, &mut update);
handle_swap_loadout(&data, &mut update);
handle_primary_input(&data, &mut update);
handle_secondary_input(&data, &mut update);
handle_ability1_input(&data, &mut update);
handle_ability2_input(&data, &mut update);
handle_ability3_input(&data, &mut update);
handle_dodge_input(&data, &mut update);
update

View File

@ -86,10 +86,13 @@ pub fn handle_possess(server: &Server, possessor_uid: Uid, possesse_uid: Uid) {
let item = assets::load_expect_cloned::<comp::Item>("common.items.debug.possess");
if let comp::ItemKind::Tool(tool) = item.kind {
let mut abilities = tool.get_abilities();
let mut ability_drain = abilities.drain(..);
loadout.active_item = Some(comp::ItemConfig {
item,
primary_ability: tool.get_abilities().get(0).cloned(),
secondary_ability: None,
ability1: ability_drain.next(),
ability2: ability_drain.next(),
ability3: ability_drain.next(),
block_ability: None,
dodge_ability: None,
});

View File

@ -111,8 +111,9 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
let mut ability_drain = abilities.drain(..);
let active_item = comp::ItemConfig {
item,
primary_ability: ability_drain.next(),
secondary_ability: ability_drain.next(),
ability1: ability_drain.next(),
ability2: ability_drain.next(),
ability3: ability_drain.next(),
block_ability: Some(comp::CharacterAbility::BasicBlock),
dodge_ability: Some(comp::CharacterAbility::Roll),
};

View File

@ -169,8 +169,9 @@ impl StateExt for State {
comp::Loadout {
active_item: main.map(|item| comp::ItemConfig {
item,
primary_ability: ability_drain.next(),
secondary_ability: ability_drain.next(),
ability1: ability_drain.next(),
ability2: ability_drain.next(),
ability3: ability_drain.next(),
block_ability: Some(comp::CharacterAbility::BasicBlock),
dodge_ability: Some(comp::CharacterAbility::Roll),
}),

View File

@ -196,8 +196,9 @@ impl<'a> System<'a> for Sys {
main.map(|item| comp::ItemConfig {
item,
primary_ability: ability_drain.next(),
secondary_ability: ability_drain.next(),
ability1: ability_drain.next(),
ability2: ability_drain.next(),
ability3: ability_drain.next(),
block_ability: None,
dodge_ability: Some(comp::CharacterAbility::Roll),
})
@ -205,14 +206,15 @@ impl<'a> System<'a> for Sys {
Some(ItemConfig {
// We need the empty item so npcs can attack
item: Item::empty(),
primary_ability: Some(CharacterAbility::BasicMelee {
ability1: Some(CharacterAbility::BasicMelee {
buildup_duration: Duration::from_millis(0),
recover_duration: Duration::from_millis(300),
base_damage: 2,
range: 3.5,
max_angle: 60.0,
}),
secondary_ability: None,
ability2: None,
ability3: None,
block_ability: None,
dodge_ability: None,
})
@ -300,14 +302,15 @@ impl<'a> System<'a> for Sys {
item: assets::load_expect_cloned(
"common.items.weapons.zweihander_sword_0",
),
primary_ability: Some(CharacterAbility::BasicMelee {
ability1: Some(CharacterAbility::BasicMelee {
buildup_duration: Duration::from_millis(800),
recover_duration: Duration::from_millis(200),
base_damage: 13,
range: 3.5,
max_angle: 60.0,
}),
secondary_ability: None,
ability2: None,
ability3: None,
block_ability: None,
dodge_ability: None,
}),

View File

@ -339,8 +339,9 @@ impl CharSelectionUi {
Mode::Create { loadout, tool, .. } => {
loadout.active_item = tool.map(|tool| comp::ItemConfig {
item: (*load_expect::<comp::Item>(tool)).clone(),
primary_ability: None,
secondary_ability: None,
ability1: None,
ability2: None,
ability3: None,
block_ability: None,
dodge_ability: None,
});

View File

@ -275,6 +275,10 @@ impl PlayState for SessionState {
}
}
},
Event::InputUpdate(GameInput::Ability3, state) => {
self.inputs.ability3.set_state(state);
},
Event::InputUpdate(GameInput::Roll, state) => {
let client = self.client.borrow();
if client

View File

@ -18,6 +18,7 @@ use std::{fs, io::prelude::*, path::PathBuf};
pub struct ControlSettings {
pub primary: KeyMouse,
pub secondary: KeyMouse,
pub ability3: KeyMouse,
pub toggle_cursor: KeyMouse,
pub escape: KeyMouse,
pub enter: KeyMouse,
@ -69,6 +70,7 @@ impl Default for ControlSettings {
Self {
primary: KeyMouse::Mouse(MouseButton::Left),
secondary: KeyMouse::Mouse(MouseButton::Right),
ability3: KeyMouse::Key(VirtualKeyCode::Key1),
toggle_cursor: KeyMouse::Key(VirtualKeyCode::Tab),
escape: KeyMouse::Key(VirtualKeyCode::Escape),
enter: KeyMouse::Key(VirtualKeyCode::Return),

View File

@ -16,6 +16,7 @@ use vek::*;
pub enum GameInput {
Primary,
Secondary,
Ability3,
ToggleCursor,
MoveForward,
MoveBack,
@ -360,6 +361,9 @@ impl Window {
map.entry(settings.controls.secondary)
.or_default()
.push(GameInput::Secondary);
map.entry(settings.controls.ability3)
.or_default()
.push(GameInput::Ability3);
map.entry(settings.controls.toggle_cursor)
.or_default()
.push(GameInput::ToggleCursor);