From 2b68adff515d797e5ea5b694a0639b371f8a75eb Mon Sep 17 00:00:00 2001 From: timokoesters Date: Thu, 26 Mar 2020 22:52:44 +0100 Subject: [PATCH] Balancing, make fireball not holdable, arrow knockback --- common/src/comp/ability.rs | 5 ++++- common/src/comp/inventory/item.rs | 19 ++++++++++++------- common/src/comp/projectile.rs | 1 + common/src/states/basic_ranged.rs | 9 +++++++-- common/src/states/triple_strike.rs | 4 ++-- common/src/states/utils.rs | 10 +++++++++- common/src/sys/character_behavior.rs | 10 ++++++++-- common/src/sys/combat.rs | 10 ++-------- common/src/sys/projectile.rs | 22 ++++++++++++++++++++-- 9 files changed, 65 insertions(+), 25 deletions(-) diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index e561bdbcbe..a8c2f604c2 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -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(), diff --git a/common/src/comp/inventory/item.rs b/common/src/comp/inventory/item.rs index 90ce466ef8..27ced5f27b 100644 --- a/common/src/comp/inventory/item.rs +++ b/common/src/comp/inventory/item.rs @@ -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], diff --git a/common/src/comp/projectile.rs b/common/src/comp/projectile.rs index 6f1982be33..a4dda1ac7c 100644 --- a/common/src/comp/projectile.rs +++ b/common/src/comp/projectile.rs @@ -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, diff --git a/common/src/states/basic_ranged.rs b/common/src/states/basic_ranged.rs index 9a73bd45ab..81f1485baf 100644 --- a/common/src/states/basic_ranged.rs +++ b/common/src/states/basic_ranged.rs @@ -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 diff --git a/common/src/states/triple_strike.rs b/common/src/states/triple_strike.rs index d39f55416b..43bbcfb0ba 100644 --- a/common/src/states/triple_strike.rs +++ b/common/src/states/triple_strike.rs @@ -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; diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index f44b413b13..4c635cd68e 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -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) }; diff --git a/common/src/sys/character_behavior.rs b/common/src/sys/character_behavior.rs index 729e4be506..e46fd63242 100644 --- a/common/src/sys/character_behavior.rs +++ b/common/src/sys/character_behavior.rs @@ -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(); diff --git a/common/src/sys/combat.rs b/common/src/sys/combat.rs index c9c33ac8c9..bf8abe1639 100644 --- a/common/src/sys/combat.rs +++ b/common/src/sys/combat.rs @@ -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() diff --git a/common/src/sys/projectile.rs b/common/src/sys/projectile.rs index e09050cc0f..3f0ee14a04 100644 --- a/common/src/sys/projectile.rs +++ b/common/src/sys/projectile.rs @@ -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>, Read<'a, EventBus>, 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,