mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Addressed second round of feedback.
This commit is contained in:
parent
b06ab250cc
commit
fe70b7fbce
@ -94,19 +94,19 @@
|
||||
],
|
||||
threshold: 0.5,
|
||||
),
|
||||
Attack(ComboMelee(1), Sword): (
|
||||
Attack(ComboMelee(Swing, 1), Sword): (
|
||||
files: [
|
||||
"voxygen.audio.sfx.abilities.swing_sword",
|
||||
],
|
||||
threshold: 0.7,
|
||||
),
|
||||
Attack(ComboMelee(2), Sword): (
|
||||
Attack(ComboMelee(Swing, 2), Sword): (
|
||||
files: [
|
||||
"voxygen.audio.sfx.abilities.separated_second_swing",
|
||||
],
|
||||
threshold: 0.7,
|
||||
),
|
||||
Attack(ComboMelee(3), Sword): (
|
||||
Attack(ComboMelee(Swing, 3), Sword): (
|
||||
files: [
|
||||
"voxygen.audio.sfx.abilities.separated_third_swing",
|
||||
],
|
||||
|
@ -20,7 +20,7 @@ pub enum CharacterAbilityType {
|
||||
ChargedRanged,
|
||||
DashMelee,
|
||||
BasicBlock,
|
||||
ComboMelee(u32),
|
||||
ComboMelee(StageSection, u32),
|
||||
LeapMelee,
|
||||
SpinMelee,
|
||||
GroundShockwave,
|
||||
@ -35,7 +35,7 @@ impl From<&CharacterState> for CharacterAbilityType {
|
||||
CharacterState::DashMelee(_) => Self::DashMelee,
|
||||
CharacterState::BasicBlock => Self::BasicBlock,
|
||||
CharacterState::LeapMelee(_) => Self::LeapMelee,
|
||||
CharacterState::ComboMelee(data) => Self::ComboMelee(data.stage),
|
||||
CharacterState::ComboMelee(data) => Self::ComboMelee(data.stage_section, data.stage),
|
||||
CharacterState::SpinMelee(_) => Self::SpinMelee,
|
||||
CharacterState::ChargedRanged(_) => Self::ChargedRanged,
|
||||
CharacterState::GroundShockwave(_) => Self::ChargedRanged,
|
||||
|
@ -124,7 +124,7 @@ impl Tool {
|
||||
base_damage: (100.0 * self.base_power()) as u32,
|
||||
max_damage: (120.0 * self.base_power()) as u32,
|
||||
damage_increase: (10.0 * self.base_power()) as u32,
|
||||
knockback: 8.0,
|
||||
knockback: 10.0,
|
||||
range: 4.0,
|
||||
angle: 30.0,
|
||||
base_buildup_duration: Duration::from_millis(500),
|
||||
@ -137,7 +137,7 @@ impl Tool {
|
||||
base_damage: (80.0 * self.base_power()) as u32,
|
||||
max_damage: (110.0 * self.base_power()) as u32,
|
||||
damage_increase: (15.0 * self.base_power()) as u32,
|
||||
knockback: 5.0,
|
||||
knockback: 12.0,
|
||||
range: 3.5,
|
||||
angle: 180.0,
|
||||
base_buildup_duration: Duration::from_millis(400),
|
||||
@ -170,8 +170,8 @@ impl Tool {
|
||||
energy_cost: 200,
|
||||
base_damage: (120.0 * self.base_power()) as u32,
|
||||
max_damage: (260.0 * self.base_power()) as u32,
|
||||
base_knockback: 5.0,
|
||||
max_knockback: 10.0,
|
||||
base_knockback: 10.0,
|
||||
max_knockback: 20.0,
|
||||
range: 5.0,
|
||||
angle: 45.0,
|
||||
energy_drain: 500,
|
||||
@ -190,6 +190,7 @@ impl Tool {
|
||||
buildup_duration: Duration::from_millis(700),
|
||||
recover_duration: Duration::from_millis(300),
|
||||
base_healthchange: (-120.0 * self.base_power()) as i32,
|
||||
knockback: 0.0,
|
||||
range: 3.5,
|
||||
max_angle: 20.0,
|
||||
},
|
||||
@ -272,6 +273,7 @@ impl Tool {
|
||||
buildup_duration: Duration::from_millis(100),
|
||||
recover_duration: Duration::from_millis(400),
|
||||
base_healthchange: (-50.0 * self.base_power()) as i32,
|
||||
knockback: 0.0,
|
||||
range: 3.5,
|
||||
max_angle: 20.0,
|
||||
}],
|
||||
|
@ -66,7 +66,7 @@ impl LoadoutBuilder {
|
||||
}
|
||||
|
||||
/// Builds loadout of creature when spawned
|
||||
pub fn build_loadout(body: Body, alignment: Alignment, mut main_tool: Option<Item>) -> Self {
|
||||
pub fn build_loadout(body: Body, alignment: Alignment, mut main_tool: Option<Item>, is_giant: bool) -> Self {
|
||||
#![allow(clippy::single_match)] // For when this is done to more than just golems.
|
||||
match body {
|
||||
Body::Golem(golem) => match golem.species {
|
||||
@ -76,6 +76,11 @@ impl LoadoutBuilder {
|
||||
));
|
||||
},
|
||||
},
|
||||
Body::Humanoid(_) => if is_giant {
|
||||
main_tool = Some(Item::new_from_asset_expect(
|
||||
"common.items.npc_weapons.sword.zweihander_sword_0",
|
||||
));
|
||||
},
|
||||
_ => {},
|
||||
};
|
||||
|
||||
@ -112,37 +117,27 @@ impl LoadoutBuilder {
|
||||
};
|
||||
|
||||
let loadout = match body {
|
||||
Body::Humanoid(_) => match alignment {
|
||||
Alignment::Npc => Loadout {
|
||||
Body::Humanoid(_) => match is_giant {
|
||||
true => Loadout {
|
||||
active_item,
|
||||
second_item: None,
|
||||
shoulder: None,
|
||||
shoulder: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.shoulder.plate_0",
|
||||
)),
|
||||
chest: Some(Item::new_from_asset_expect(
|
||||
match rand::thread_rng().gen_range(0, 10) {
|
||||
0 => "common.items.armor.chest.worker_green_0",
|
||||
1 => "common.items.armor.chest.worker_green_1",
|
||||
2 => "common.items.armor.chest.worker_red_0",
|
||||
3 => "common.items.armor.chest.worker_red_1",
|
||||
4 => "common.items.armor.chest.worker_purple_0",
|
||||
5 => "common.items.armor.chest.worker_purple_1",
|
||||
6 => "common.items.armor.chest.worker_yellow_0",
|
||||
7 => "common.items.armor.chest.worker_yellow_1",
|
||||
8 => "common.items.armor.chest.worker_orange_0",
|
||||
_ => "common.items.armor.chest.worker_orange_1",
|
||||
},
|
||||
"common.items.armor.chest.plate_green_0",
|
||||
)),
|
||||
belt: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.belt.leather_0",
|
||||
"common.items.armor.belt.plate_0",
|
||||
)),
|
||||
hand: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.hand.plate_0",
|
||||
)),
|
||||
hand: None,
|
||||
pants: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.pants.worker_blue_0",
|
||||
"common.items.armor.pants.plate_green_0",
|
||||
)),
|
||||
foot: Some(Item::new_from_asset_expect(
|
||||
match rand::thread_rng().gen_range(0, 2) {
|
||||
0 => "common.items.armor.foot.leather_0",
|
||||
_ => "common.items.armor.starter.sandals_0",
|
||||
},
|
||||
"common.items.armor.foot.plate_0",
|
||||
)),
|
||||
back: None,
|
||||
ring: None,
|
||||
@ -152,38 +147,79 @@ impl LoadoutBuilder {
|
||||
head: None,
|
||||
tabard: None,
|
||||
},
|
||||
Alignment::Enemy => Loadout {
|
||||
active_item,
|
||||
second_item: None,
|
||||
shoulder: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.shoulder.cultist_shoulder_purple",
|
||||
)),
|
||||
chest: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.chest.cultist_chest_purple",
|
||||
)),
|
||||
belt: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.belt.cultist_belt",
|
||||
)),
|
||||
hand: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.hand.cultist_hands_purple",
|
||||
)),
|
||||
pants: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.pants.cultist_legs_purple",
|
||||
)),
|
||||
foot: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.foot.cultist_boots",
|
||||
)),
|
||||
back: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.back.dungeon_purple-0",
|
||||
)),
|
||||
ring: None,
|
||||
neck: None,
|
||||
lantern: Some(Item::new_from_asset_expect("common.items.lantern.black_0")),
|
||||
glider: None,
|
||||
head: None,
|
||||
tabard: None,
|
||||
},
|
||||
_ => LoadoutBuilder::animal(body).build(),
|
||||
false => match alignment {
|
||||
Alignment::Npc => Loadout {
|
||||
active_item,
|
||||
second_item: None,
|
||||
shoulder: None,
|
||||
chest: Some(Item::new_from_asset_expect(
|
||||
match rand::thread_rng().gen_range(0, 10) {
|
||||
0 => "common.items.armor.chest.worker_green_0",
|
||||
1 => "common.items.armor.chest.worker_green_1",
|
||||
2 => "common.items.armor.chest.worker_red_0",
|
||||
3 => "common.items.armor.chest.worker_red_1",
|
||||
4 => "common.items.armor.chest.worker_purple_0",
|
||||
5 => "common.items.armor.chest.worker_purple_1",
|
||||
6 => "common.items.armor.chest.worker_yellow_0",
|
||||
7 => "common.items.armor.chest.worker_yellow_1",
|
||||
8 => "common.items.armor.chest.worker_orange_0",
|
||||
_ => "common.items.armor.chest.worker_orange_1",
|
||||
},
|
||||
)),
|
||||
belt: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.belt.leather_0",
|
||||
)),
|
||||
hand: None,
|
||||
pants: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.pants.worker_blue_0",
|
||||
)),
|
||||
foot: Some(Item::new_from_asset_expect(
|
||||
match rand::thread_rng().gen_range(0, 2) {
|
||||
0 => "common.items.armor.foot.leather_0",
|
||||
_ => "common.items.armor.starter.sandals_0",
|
||||
},
|
||||
)),
|
||||
back: None,
|
||||
ring: None,
|
||||
neck: None,
|
||||
lantern: None,
|
||||
glider: None,
|
||||
head: None,
|
||||
tabard: None,
|
||||
},
|
||||
Alignment::Enemy => Loadout {
|
||||
active_item,
|
||||
second_item: None,
|
||||
shoulder: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.shoulder.cultist_shoulder_purple",
|
||||
)),
|
||||
chest: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.chest.cultist_chest_purple",
|
||||
)),
|
||||
belt: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.belt.cultist_belt",
|
||||
)),
|
||||
hand: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.hand.cultist_hands_purple",
|
||||
)),
|
||||
pants: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.pants.cultist_legs_purple",
|
||||
)),
|
||||
foot: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.foot.cultist_boots",
|
||||
)),
|
||||
back: Some(Item::new_from_asset_expect(
|
||||
"common.items.armor.back.dungeon_purple-0",
|
||||
)),
|
||||
ring: None,
|
||||
neck: None,
|
||||
lantern: Some(Item::new_from_asset_expect("common.items.lantern.black_0")),
|
||||
glider: None,
|
||||
head: None,
|
||||
tabard: None,
|
||||
},
|
||||
_ => LoadoutBuilder::animal(body).build(),
|
||||
}
|
||||
},
|
||||
Body::Golem(golem) => match golem.species {
|
||||
golem::Species::StoneGolem => Loadout {
|
||||
|
@ -77,13 +77,13 @@ impl CharacterBehavior for Data {
|
||||
|
||||
// Allows for other states to interrupt this state
|
||||
if self.is_interruptible && !data.inputs.primary.is_pressed() {
|
||||
if data.inputs.roll.is_pressed() {
|
||||
handle_dodge_input(data, &mut update);
|
||||
return update;
|
||||
}
|
||||
if data.inputs.secondary.is_pressed() {
|
||||
handle_ability2_input(data, &mut update);
|
||||
return update;
|
||||
handle_dodge_input(data, &mut update);
|
||||
handle_ability2_input(data, &mut update);
|
||||
match update.character {
|
||||
CharacterState::ComboMelee(_) => {},
|
||||
_ => {
|
||||
return update;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,13 +64,13 @@ impl CharacterBehavior for Data {
|
||||
|
||||
// Allows for other states to interrupt this state
|
||||
if self.static_data.is_interruptible && !data.inputs.secondary.is_pressed() {
|
||||
if data.inputs.roll.is_pressed() {
|
||||
handle_dodge_input(data, &mut update);
|
||||
return update;
|
||||
}
|
||||
if data.inputs.primary.is_pressed() {
|
||||
handle_ability1_input(data, &mut update);
|
||||
return update;
|
||||
handle_dodge_input(data, &mut update);
|
||||
handle_ability1_input(data, &mut update);
|
||||
match update.character {
|
||||
CharacterState::DashMelee(_) => {},
|
||||
_ => {
|
||||
return update;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,7 +350,7 @@ pub fn unwrap_tool_data<'a>(data: &'a JoinData) -> Option<&'a Tool> {
|
||||
/// Determines what portion a state is in. Used in all attacks (eventually). Is
|
||||
/// used to control aspects of animation code, as well as logic within the
|
||||
/// character states.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||
pub enum StageSection {
|
||||
Buildup,
|
||||
Swing,
|
||||
|
@ -153,10 +153,11 @@ impl<'a> System<'a> for Sys {
|
||||
});
|
||||
}
|
||||
if attack.knockback != 0.0 && damage.healthchange != 0.0 {
|
||||
let kb_dir = Dir::new((pos_b.0 - pos.0).try_normalized().unwrap_or(*ori.0));
|
||||
server_emitter.emit(ServerEvent::Knockback {
|
||||
entity: b,
|
||||
impulse: attack.knockback
|
||||
* *Dir::slerp(ori.0, Dir::new(Vec3::new(0.0, 0.0, 1.0)), 0.5),
|
||||
* *Dir::slerp(kb_dir, Dir::new(Vec3::new(0.0, 0.0, 1.0)), 0.5),
|
||||
});
|
||||
}
|
||||
attack.hit_count += 1;
|
||||
|
@ -621,7 +621,7 @@ fn handle_spawn(
|
||||
.create_npc(
|
||||
pos,
|
||||
comp::Stats::new(get_npc_name(id).into(), body),
|
||||
LoadoutBuilder::build_loadout(body, alignment, None).build(),
|
||||
LoadoutBuilder::build_loadout(body, alignment, None, false).build(),
|
||||
body,
|
||||
)
|
||||
.with(comp::Vel(vel))
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::SysTimer;
|
||||
use crate::{chunk_generator::ChunkGenerator, client::Client, Tick};
|
||||
use common::{
|
||||
comp::{self, bird_medium, Alignment, CharacterAbility, Player, Pos},
|
||||
comp::{self, bird_medium, Alignment, Player, Pos},
|
||||
event::{EventBus, ServerEvent},
|
||||
generation::get_npc_name,
|
||||
msg::ServerMsg,
|
||||
@ -13,7 +13,7 @@ use common::{
|
||||
};
|
||||
use rand::Rng;
|
||||
use specs::{Join, Read, ReadStorage, System, Write, WriteExpect, WriteStorage};
|
||||
use std::{sync::Arc, time::Duration};
|
||||
use std::sync::Arc;
|
||||
use vek::*;
|
||||
|
||||
/// This system will handle loading generated chunks and unloading
|
||||
@ -115,18 +115,12 @@ impl<'a> System<'a> for Sys {
|
||||
let mut body = entity.body;
|
||||
let name = entity.name.unwrap_or_else(|| "Unnamed".to_string());
|
||||
let alignment = entity.alignment;
|
||||
let mut main_tool = entity.main_tool;
|
||||
let main_tool = entity.main_tool;
|
||||
let mut stats = comp::Stats::new(name, body);
|
||||
// let damage = stats.level.level() as i32; TODO: Make NPC base damage
|
||||
// non-linearly depend on their level
|
||||
|
||||
if entity.is_giant {
|
||||
main_tool = Some(comp::Item::new_from_asset_expect(
|
||||
"common.items.npc_weapons.sword.zweihander_sword_0",
|
||||
));
|
||||
}
|
||||
|
||||
let mut loadout = LoadoutBuilder::build_loadout(body, alignment, main_tool).build();
|
||||
let loadout = LoadoutBuilder::build_loadout(body, alignment, main_tool, entity.is_giant).build();
|
||||
|
||||
let mut scale = entity.scale;
|
||||
|
||||
@ -157,36 +151,6 @@ impl<'a> System<'a> for Sys {
|
||||
body,
|
||||
);
|
||||
}
|
||||
loadout = comp::Loadout {
|
||||
active_item,
|
||||
second_item: None,
|
||||
shoulder: Some(comp::Item::new_from_asset_expect(
|
||||
"common.items.armor.shoulder.plate_0",
|
||||
)),
|
||||
chest: Some(comp::Item::new_from_asset_expect(
|
||||
"common.items.armor.chest.plate_green_0",
|
||||
)),
|
||||
belt: Some(comp::Item::new_from_asset_expect(
|
||||
"common.items.armor.belt.plate_0",
|
||||
)),
|
||||
hand: Some(comp::Item::new_from_asset_expect(
|
||||
"common.items.armor.hand.plate_0",
|
||||
)),
|
||||
pants: Some(comp::Item::new_from_asset_expect(
|
||||
"common.items.armor.pants.plate_green_0",
|
||||
)),
|
||||
foot: Some(comp::Item::new_from_asset_expect(
|
||||
"common.items.armor.foot.plate_0",
|
||||
)),
|
||||
back: None,
|
||||
ring: None,
|
||||
neck: None,
|
||||
lantern: None,
|
||||
glider: None,
|
||||
head: None,
|
||||
tabard: None,
|
||||
};
|
||||
|
||||
stats.level.set_level(rand::thread_rng().gen_range(30, 35));
|
||||
scale = 2.0 + rand::random::<f32>();
|
||||
}
|
||||
|
@ -113,15 +113,26 @@ fn matches_ability_stage() {
|
||||
});
|
||||
|
||||
let result = CombatEventMapper::map_event(
|
||||
&CharacterState::TripleStrike(states::triple_strike::Data {
|
||||
base_damage: 10,
|
||||
stage: states::triple_strike::Stage::First,
|
||||
stage_time_active: Duration::default(),
|
||||
stage_exhausted: false,
|
||||
initialized: true,
|
||||
transition_style: states::triple_strike::TransitionStyle::Hold(
|
||||
states::triple_strike::HoldingState::Released,
|
||||
),
|
||||
&CharacterState::ComboMelee(states::combo_melee::Data {
|
||||
stage_data: vec![combo_melee::Stage {
|
||||
stage: 1,
|
||||
base_damage: 100,
|
||||
max_damage: 120,
|
||||
damage_increase: 10,
|
||||
knockback: 10.0,
|
||||
range: 4.0,
|
||||
angle: 30.0,
|
||||
base_buildup_duration: Duration::from_millis(500),
|
||||
base_swing_duration: Duration::from_millis(200),
|
||||
base_recover_duration: Duration::from_millis(400),
|
||||
forward_movement: 0.5,
|
||||
}],
|
||||
initial_energy_gain: 0,
|
||||
max_energy_gain: 100,
|
||||
energy_increase: 20,
|
||||
speed_increase: 0.05,
|
||||
max_speed_increase: 1.8,
|
||||
is_interruptible: true,
|
||||
}),
|
||||
&PreviousEntityState {
|
||||
event: SfxEvent::Idle,
|
||||
@ -134,7 +145,7 @@ fn matches_ability_stage() {
|
||||
assert_eq!(
|
||||
result,
|
||||
SfxEvent::Attack(
|
||||
CharacterAbilityType::TripleStrike(states::triple_strike::Stage::First),
|
||||
CharacterAbilityType::ComboMelee(states::utils::StageSection::Swing, 1),
|
||||
ToolCategory::Sword
|
||||
)
|
||||
);
|
||||
@ -154,15 +165,26 @@ fn ignores_different_ability_stage() {
|
||||
});
|
||||
|
||||
let result = CombatEventMapper::map_event(
|
||||
&CharacterState::TripleStrike(states::triple_strike::Data {
|
||||
base_damage: 10,
|
||||
stage: states::triple_strike::Stage::Second,
|
||||
stage_time_active: Duration::default(),
|
||||
stage_exhausted: false,
|
||||
initialized: true,
|
||||
transition_style: states::triple_strike::TransitionStyle::Hold(
|
||||
states::triple_strike::HoldingState::Released,
|
||||
),
|
||||
&CharacterState::ComboMelee(states::combo_melee::Data {
|
||||
stage_data: vec![combo_melee::Stage {
|
||||
stage: 1,
|
||||
base_damage: 100,
|
||||
max_damage: 120,
|
||||
damage_increase: 10,
|
||||
knockback: 10.0,
|
||||
range: 4.0,
|
||||
angle: 30.0,
|
||||
base_buildup_duration: Duration::from_millis(500),
|
||||
base_swing_duration: Duration::from_millis(200),
|
||||
base_recover_duration: Duration::from_millis(400),
|
||||
forward_movement: 0.5,
|
||||
}],
|
||||
initial_energy_gain: 0,
|
||||
max_energy_gain: 100,
|
||||
energy_increase: 20,
|
||||
speed_increase: 0.05,
|
||||
max_speed_increase: 1.8,
|
||||
is_interruptible: true,
|
||||
}),
|
||||
&PreviousEntityState {
|
||||
event: SfxEvent::Idle,
|
||||
@ -175,7 +197,7 @@ fn ignores_different_ability_stage() {
|
||||
assert_ne!(
|
||||
result,
|
||||
SfxEvent::Attack(
|
||||
CharacterAbilityType::TripleStrike(states::triple_strike::Stage::First),
|
||||
CharacterAbilityType::ComboMelee(states::utils::StageSection::Swing, 1),
|
||||
ToolCategory::Sword
|
||||
)
|
||||
);
|
||||
|
@ -71,11 +71,10 @@
|
||||
//! ],
|
||||
//! threshold: 1.2,
|
||||
//! ),
|
||||
//! // A multi-stage attack ability which depends on the weapon (To do: update example)
|
||||
//! Attack(TripleStrike(First), Sword): (
|
||||
//! // A multi-stage attack ability which depends on the weapon
|
||||
//! Attack(ComboMelee(Swing, 1), Sword): (
|
||||
//! files: [
|
||||
//! "voxygen.audio.sfx.weapon.sword_03",
|
||||
//! "voxygen.audio.sfx.weapon.sword_04",
|
||||
//! "voxygen.audio.sfx.abilities.swing_sword",
|
||||
//! ],
|
||||
//! threshold: 0.5,
|
||||
//! ),
|
||||
|
Loading…
Reference in New Issue
Block a user