mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Balancing, make fireball not holdable, arrow knockback
This commit is contained in:
parent
8010e5afb4
commit
2b68adff51
@ -21,6 +21,7 @@ pub enum CharacterAbility {
|
||||
},
|
||||
BasicRanged {
|
||||
energy_cost: u32,
|
||||
holdable: bool,
|
||||
prepare_duration: Duration,
|
||||
recover_duration: Duration,
|
||||
projectile: Projectile,
|
||||
@ -60,7 +61,7 @@ impl CharacterAbility {
|
||||
&& data.vel.0.xy().magnitude_squared() > 0.5
|
||||
&& update
|
||||
.energy
|
||||
.try_change_by(-150, EnergySource::Ability)
|
||||
.try_change_by(-220, EnergySource::Ability)
|
||||
.is_ok()
|
||||
},
|
||||
CharacterAbility::DashMelee { .. } => update
|
||||
@ -122,6 +123,7 @@ impl From<&CharacterAbility> for CharacterState {
|
||||
max_angle: *max_angle,
|
||||
}),
|
||||
CharacterAbility::BasicRanged {
|
||||
holdable,
|
||||
prepare_duration,
|
||||
recover_duration,
|
||||
projectile,
|
||||
@ -132,6 +134,7 @@ impl From<&CharacterAbility> for CharacterState {
|
||||
} => CharacterState::BasicRanged(basic_ranged::Data {
|
||||
exhausted: false,
|
||||
prepare_timer: Duration::default(),
|
||||
holdable: *holdable,
|
||||
prepare_duration: *prepare_duration,
|
||||
recover_duration: *recover_duration,
|
||||
projectile: projectile.clone(),
|
||||
|
@ -73,7 +73,7 @@ impl ToolData {
|
||||
Sword(_) => vec![TripleStrike { base_damage: 5 }, DashMelee {
|
||||
buildup_duration: Duration::from_millis(500),
|
||||
recover_duration: Duration::from_millis(500),
|
||||
base_damage: 20,
|
||||
base_damage: 10,
|
||||
}],
|
||||
Axe(_) => vec![BasicMelee {
|
||||
energy_cost: 0,
|
||||
@ -93,17 +93,19 @@ impl ToolData {
|
||||
}],
|
||||
Bow(_) => vec![BasicRanged {
|
||||
energy_cost: 0,
|
||||
holdable: true,
|
||||
prepare_duration: Duration::from_millis(100),
|
||||
recover_duration: Duration::from_millis(300),
|
||||
recover_duration: Duration::from_millis(500),
|
||||
projectile: Projectile {
|
||||
hit_ground: vec![projectile::Effect::Stick],
|
||||
hit_wall: vec![projectile::Effect::Stick],
|
||||
hit_entity: vec![
|
||||
projectile::Effect::Damage(HealthChange {
|
||||
// TODO: This should not be fixed (?)
|
||||
amount: -3,
|
||||
amount: -5,
|
||||
cause: HealthSource::Projectile { owner: None },
|
||||
}),
|
||||
projectile::Effect::Knockback(10.0),
|
||||
projectile::Effect::Vanish,
|
||||
],
|
||||
time_left: Duration::from_secs(15),
|
||||
@ -132,15 +134,16 @@ impl ToolData {
|
||||
},
|
||||
BasicRanged {
|
||||
energy_cost: 0,
|
||||
prepare_duration: Duration::from_millis(300),
|
||||
recover_duration: Duration::from_millis(100),
|
||||
holdable: false,
|
||||
prepare_duration: Duration::from_millis(0),
|
||||
recover_duration: Duration::from_millis(200),
|
||||
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,
|
||||
amount: -1,
|
||||
cause: HealthSource::Projectile { owner: None },
|
||||
}),
|
||||
projectile::Effect::Vanish,
|
||||
@ -158,6 +161,7 @@ impl ToolData {
|
||||
},
|
||||
BasicRanged {
|
||||
energy_cost: 400,
|
||||
holdable: false,
|
||||
prepare_duration: Duration::from_millis(800),
|
||||
recover_duration: Duration::from_millis(300),
|
||||
projectile: Projectile {
|
||||
@ -217,7 +221,8 @@ impl ToolData {
|
||||
],
|
||||
Possess => vec![BasicRanged {
|
||||
energy_cost: 0,
|
||||
prepare_duration: Duration::from_millis(300),
|
||||
holdable: false,
|
||||
prepare_duration: Duration::from_millis(0),
|
||||
recover_duration: Duration::from_millis(300),
|
||||
projectile: Projectile {
|
||||
hit_ground: vec![projectile::Effect::Stick],
|
||||
|
@ -6,6 +6,7 @@ use std::time::Duration;
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Effect {
|
||||
Damage(comp::HealthChange),
|
||||
Knockback(f32),
|
||||
Explode { power: f32 },
|
||||
Vanish,
|
||||
Stick,
|
||||
|
@ -8,6 +8,8 @@ use std::time::Duration;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Data {
|
||||
/// Can you hold the abilty beyond the prepare duration
|
||||
pub holdable: bool,
|
||||
/// How long we have to prepare the weapon
|
||||
pub prepare_duration: Duration,
|
||||
/// How long we prepared the weapon already
|
||||
@ -26,15 +28,16 @@ impl CharacterBehavior for Data {
|
||||
fn behavior(&self, data: &JoinData) -> StateUpdate {
|
||||
let mut update = StateUpdate::from(data);
|
||||
|
||||
handle_move(data, &mut update, 0.5);
|
||||
handle_move(data, &mut update, 0.2);
|
||||
handle_jump(data, &mut update);
|
||||
|
||||
if self.prepare_timer < self.prepare_duration
|
||||
|| !self.exhausted && data.inputs.holding_ability_key()
|
||||
|| self.holdable && !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),
|
||||
holdable: self.holdable,
|
||||
prepare_duration: self.prepare_duration,
|
||||
recover_duration: self.recover_duration,
|
||||
projectile: self.projectile.clone(),
|
||||
@ -58,6 +61,7 @@ impl CharacterBehavior for Data {
|
||||
|
||||
update.character = CharacterState::BasicRanged(Data {
|
||||
prepare_timer: self.prepare_timer,
|
||||
holdable: self.holdable,
|
||||
prepare_duration: self.prepare_duration,
|
||||
recover_duration: self.recover_duration,
|
||||
projectile: self.projectile.clone(),
|
||||
@ -70,6 +74,7 @@ impl CharacterBehavior for Data {
|
||||
// Recovery
|
||||
update.character = CharacterState::BasicRanged(Data {
|
||||
prepare_timer: self.prepare_timer,
|
||||
holdable: self.holdable,
|
||||
prepare_duration: self.prepare_duration,
|
||||
recover_duration: self
|
||||
.recover_duration
|
||||
|
@ -4,10 +4,10 @@ use crate::{
|
||||
sys::character_behavior::{CharacterBehavior, JoinData},
|
||||
};
|
||||
use std::time::Duration;
|
||||
use vek::vec::{Vec2, Vec3};
|
||||
use vek::vec::Vec3;
|
||||
|
||||
// In millis
|
||||
const STAGE_DURATION: u64 = 500;
|
||||
const STAGE_DURATION: u64 = 700;
|
||||
|
||||
const INITIAL_ACCEL: f32 = 90.0;
|
||||
const BASE_SPEED: f32 = 25.0;
|
||||
|
@ -10,6 +10,7 @@ use vek::vec::Vec2;
|
||||
pub const MOVEMENT_THRESHOLD_VEL: f32 = 3.0;
|
||||
const BASE_HUMANOID_ACCEL: f32 = 100.0;
|
||||
const BASE_HUMANOID_SPEED: f32 = 150.0;
|
||||
const NPC_HUMANOID_SPEED: f32 = 150.0;
|
||||
const BASE_HUMANOID_AIR_ACCEL: f32 = 15.0;
|
||||
const BASE_HUMANOID_AIR_SPEED: f32 = 8.0;
|
||||
const BASE_HUMANOID_WATER_ACCEL: f32 = 70.0;
|
||||
@ -39,7 +40,14 @@ pub fn handle_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
|
||||
/// Updates components to move player as if theyre on ground or in air
|
||||
fn basic_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
|
||||
let (accel, speed): (f32, f32) = if data.physics.on_ground {
|
||||
(BASE_HUMANOID_ACCEL, BASE_HUMANOID_SPEED)
|
||||
(
|
||||
BASE_HUMANOID_ACCEL,
|
||||
if data.agent.is_some() {
|
||||
NPC_HUMANOID_SPEED
|
||||
} else {
|
||||
BASE_HUMANOID_SPEED
|
||||
},
|
||||
)
|
||||
} else {
|
||||
(BASE_HUMANOID_AIR_ACCEL, BASE_HUMANOID_AIR_SPEED)
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
comp::{
|
||||
Attacking, Body, CharacterState, ControlAction, Controller, ControllerInputs, Energy,
|
||||
Loadout, Mounting, Ori, PhysicsState, Pos, StateUpdate, Stats, Vel,
|
||||
Agent, Attacking, Body, CharacterState, ControlAction, Controller, ControllerInputs,
|
||||
Energy, Loadout, Mounting, Ori, PhysicsState, Pos, StateUpdate, Stats, Vel,
|
||||
},
|
||||
event::{EventBus, LocalEvent, ServerEvent},
|
||||
state::DeltaTime,
|
||||
@ -46,6 +46,7 @@ pub struct JoinData<'a> {
|
||||
pub body: &'a Body,
|
||||
pub physics: &'a PhysicsState,
|
||||
pub attacking: Option<&'a Attacking>,
|
||||
pub agent: Option<&'a Agent>,
|
||||
pub updater: &'a LazyUpdate,
|
||||
}
|
||||
|
||||
@ -63,6 +64,7 @@ pub type JoinTuple<'a> = (
|
||||
&'a Body,
|
||||
&'a PhysicsState,
|
||||
Option<&'a Attacking>,
|
||||
Option<&'a Agent>,
|
||||
);
|
||||
|
||||
fn incorporate_update(tuple: &mut JoinTuple, state_update: StateUpdate) {
|
||||
@ -91,6 +93,7 @@ impl<'a> JoinData<'a> {
|
||||
body: j.10,
|
||||
physics: j.11,
|
||||
attacking: j.12,
|
||||
agent: j.13,
|
||||
updater,
|
||||
dt,
|
||||
}
|
||||
@ -121,6 +124,7 @@ impl<'a> System<'a> for Sys {
|
||||
ReadStorage<'a, Body>,
|
||||
ReadStorage<'a, PhysicsState>,
|
||||
ReadStorage<'a, Attacking>,
|
||||
ReadStorage<'a, Agent>,
|
||||
ReadStorage<'a, Uid>,
|
||||
ReadStorage<'a, Mounting>,
|
||||
);
|
||||
@ -145,6 +149,7 @@ impl<'a> System<'a> for Sys {
|
||||
bodies,
|
||||
physics_states,
|
||||
attacking_storage,
|
||||
agent_storage,
|
||||
uids,
|
||||
mountings,
|
||||
): Self::SystemData,
|
||||
@ -166,6 +171,7 @@ impl<'a> System<'a> for Sys {
|
||||
&bodies,
|
||||
&physics_states,
|
||||
attacking_storage.maybe(),
|
||||
agent_storage.maybe(),
|
||||
)
|
||||
.join();
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
comp::{
|
||||
Agent, Attacking, Body, CharacterState, Controller, HealthChange, HealthSource, Ori, Pos,
|
||||
Scale, Stats,
|
||||
Agent, Attacking, Body, CharacterState, HealthChange, HealthSource, Ori, Pos, Scale, Stats,
|
||||
},
|
||||
event::{EventBus, LocalEvent, ServerEvent},
|
||||
sync::Uid,
|
||||
@ -25,7 +24,6 @@ impl<'a> System<'a> for Sys {
|
||||
ReadStorage<'a, Ori>,
|
||||
ReadStorage<'a, Scale>,
|
||||
ReadStorage<'a, Agent>,
|
||||
ReadStorage<'a, Controller>,
|
||||
ReadStorage<'a, Body>,
|
||||
ReadStorage<'a, Stats>,
|
||||
WriteStorage<'a, Attacking>,
|
||||
@ -43,7 +41,6 @@ impl<'a> System<'a> for Sys {
|
||||
orientations,
|
||||
scales,
|
||||
agents,
|
||||
controllers,
|
||||
bodies,
|
||||
stats,
|
||||
mut attacking_storage,
|
||||
@ -53,15 +50,12 @@ impl<'a> System<'a> for Sys {
|
||||
let mut server_emitter = server_bus.emitter();
|
||||
let mut local_emitter = local_bus.emitter();
|
||||
// Attacks
|
||||
for (entity, uid, pos, ori, scale_maybe, agent_maybe, _, _attacker_stats, attack) in (
|
||||
for (entity, uid, pos, ori, scale_maybe, attack) in (
|
||||
&entities,
|
||||
&uids,
|
||||
&positions,
|
||||
&orientations,
|
||||
scales.maybe(),
|
||||
agents.maybe(),
|
||||
&controllers,
|
||||
&stats,
|
||||
&mut attacking_storage,
|
||||
)
|
||||
.join()
|
||||
|
@ -1,10 +1,12 @@
|
||||
use crate::{
|
||||
comp::{projectile, HealthSource, Ori, PhysicsState, Pos, Projectile, Vel},
|
||||
event::{EventBus, ServerEvent},
|
||||
event::{EventBus, LocalEvent, ServerEvent},
|
||||
state::DeltaTime,
|
||||
sync::UidAllocator,
|
||||
};
|
||||
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
|
||||
use specs::{saveload::MarkerAllocator, Entities, Join, Read, ReadStorage, System, WriteStorage};
|
||||
use std::time::Duration;
|
||||
use vek::*;
|
||||
|
||||
/// This system is responsible for handling projectile effect triggers
|
||||
pub struct Sys;
|
||||
@ -12,6 +14,8 @@ impl<'a> System<'a> for Sys {
|
||||
type SystemData = (
|
||||
Entities<'a>,
|
||||
Read<'a, DeltaTime>,
|
||||
Read<'a, UidAllocator>,
|
||||
Read<'a, EventBus<LocalEvent>>,
|
||||
Read<'a, EventBus<ServerEvent>>,
|
||||
ReadStorage<'a, Pos>,
|
||||
ReadStorage<'a, PhysicsState>,
|
||||
@ -25,6 +29,8 @@ impl<'a> System<'a> for Sys {
|
||||
(
|
||||
entities,
|
||||
dt,
|
||||
uid_allocator,
|
||||
local_bus,
|
||||
server_bus,
|
||||
positions,
|
||||
physics_states,
|
||||
@ -33,6 +39,7 @@ impl<'a> System<'a> for Sys {
|
||||
mut projectiles,
|
||||
): Self::SystemData,
|
||||
) {
|
||||
let mut local_emitter = local_bus.emitter();
|
||||
let mut server_emitter = server_bus.emitter();
|
||||
|
||||
// Attacks
|
||||
@ -90,6 +97,17 @@ impl<'a> System<'a> for Sys {
|
||||
projectile::Effect::Damage(change) => {
|
||||
server_emitter.emit(ServerEvent::Damage { uid: other, change })
|
||||
},
|
||||
projectile::Effect::Knockback(knockback) => {
|
||||
if let Some(entity) =
|
||||
uid_allocator.retrieve_entity_internal(other.into())
|
||||
{
|
||||
local_emitter.emit(LocalEvent::ApplyForce {
|
||||
entity,
|
||||
dir: Vec3::slerp(ori.0, Vec3::new(0.0, 0.0, 1.0), 0.5),
|
||||
force: knockback,
|
||||
});
|
||||
}
|
||||
},
|
||||
projectile::Effect::Explode { power } => {
|
||||
server_emitter.emit(ServerEvent::Explosion {
|
||||
pos: pos.0,
|
||||
|
Loading…
Reference in New Issue
Block a user