From 71ba9b6a5411f969af3d2eb15f493c60299a7d56 Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 29 Mar 2021 10:44:46 -0400 Subject: [PATCH 1/2] Mindflayer balance tweaks. --- .../unique/mindflayer/dimensionaldoor.ron | 2 +- .../unique/mindflayer/necroticvortex.ron | 8 ++-- common/src/comp/ability.rs | 2 +- common/src/states/spin_melee.rs | 13 ++---- server/src/sys/agent.rs | 42 ++++++++++++++----- world/src/site/dungeon/mod.rs | 3 +- 6 files changed, 44 insertions(+), 26 deletions(-) diff --git a/assets/common/abilities/unique/mindflayer/dimensionaldoor.ron b/assets/common/abilities/unique/mindflayer/dimensionaldoor.ron index 6fefdb4a2d..385b8486ac 100644 --- a/assets/common/abilities/unique/mindflayer/dimensionaldoor.ron +++ b/assets/common/abilities/unique/mindflayer/dimensionaldoor.ron @@ -1,5 +1,5 @@ Blink( - buildup_duration: 0.5, + buildup_duration: 0.75, recover_duration: 0.25, max_range: 100.0, ) \ No newline at end of file diff --git a/assets/common/abilities/unique/mindflayer/necroticvortex.ron b/assets/common/abilities/unique/mindflayer/necroticvortex.ron index 6587188b25..3b9e308d96 100644 --- a/assets/common/abilities/unique/mindflayer/necroticvortex.ron +++ b/assets/common/abilities/unique/mindflayer/necroticvortex.ron @@ -2,10 +2,10 @@ SpinMelee( buildup_duration: 0.5, swing_duration: 0.2, recover_duration: 0.6, - base_damage: 70.0, - base_poise_damage: 0.0, - knockback: ( strength: 8.0, direction: Towards), - range: 17.5, + base_damage: 80.0, + base_poise_damage: 1.0, + knockback: ( strength: 7.0, direction: Towards), + range: 16.0, damage_effect: Some(Lifesteal(1.0)), energy_cost: 0.0, is_infinite: true, diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index 27d89ccac5..c1c76c51e9 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -1364,7 +1364,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState { specifier: *specifier, }, timer: Duration::default(), - spins_remaining: *num_spins - 1, + consecutive_spins: 1, stage_section: StageSection::Buildup, exhausted: false, }), diff --git a/common/src/states/spin_melee.rs b/common/src/states/spin_melee.rs index 8ea32ea7e1..232a84b1b1 100644 --- a/common/src/states/spin_melee.rs +++ b/common/src/states/spin_melee.rs @@ -60,8 +60,8 @@ pub struct Data { pub static_data: StaticData, /// Timer for each stage pub timer: Duration, - /// How many spins it can do before ending - pub spins_remaining: u32, + /// How many spins it has done + pub consecutive_spins: u32, /// What section the character stage is in pub stage_section: StageSection, /// Whether the state can deal damage @@ -187,18 +187,13 @@ impl CharacterBehavior for Data { ..*self }); } else if update.energy.current() as f32 >= self.static_data.energy_cost - && (self.spins_remaining != 0 + && (self.consecutive_spins < self.static_data.num_spins || (self.static_data.is_infinite && input_is_pressed(data, self.static_data.ability_info.input))) { - let new_spins_remaining = if self.static_data.is_infinite { - self.spins_remaining - } else { - self.spins_remaining - 1 - }; update.character = CharacterState::SpinMelee(Data { timer: Duration::default(), - spins_remaining: new_spins_remaining, + consecutive_spins: self.consecutive_spins + 1, exhausted: false, ..*self }); diff --git a/server/src/sys/agent.rs b/server/src/sys/agent.rs index 47c84f8624..2d9cee2090 100644 --- a/server/src/sys/agent.rs +++ b/server/src/sys/agent.rs @@ -20,6 +20,7 @@ use common::{ path::TraversalConfig, resources::{DeltaTime, Time, TimeOfDay}, rtsim::{Memory, MemoryItem, RtSimEntity, RtSimEvent}, + states::utils::StageSection, terrain::{Block, TerrainGrid}, time::DayPeriod, trade::{TradeAction, TradePhase, TradeResult}, @@ -37,7 +38,7 @@ use specs::{ Entities, Entity as EcsEntity, Join, ParJoin, Read, ReadExpect, ReadStorage, SystemData, World, Write, WriteExpect, WriteStorage, }; -use std::{f32::consts::PI, sync::Arc}; +use std::{f32::consts::PI, sync::Arc, time::Duration}; use vek::*; struct AgentData<'a> { @@ -2202,7 +2203,7 @@ impl<'a> AgentData<'a> { } }, Tactic::Mindflayer => { - const MINDFLAYER_ATTACK_DIST: f32 = 17.5; + const MINDFLAYER_ATTACK_DIST: f32 = 16.0; const MINION_SUMMON_THRESHOLD: f32 = 0.20; let health_fraction = self.health.map_or(0.5, |h| h.fraction()); // Extreme hack to set action_timer at start of combat @@ -2214,10 +2215,11 @@ impl<'a> AgentData<'a> { let mindflayer_is_far = dist_sqrd > MINDFLAYER_ATTACK_DIST.powi(2); if agent.action_timer > health_fraction { // Summon minions at particular thresholds of health - if !self.char_state.is_attack() { - controller - .actions - .push(ControlAction::basic_input(InputKind::Ability(1))); + controller + .actions + .push(ControlAction::basic_input(InputKind::Ability(1))); + if matches!(self.char_state, CharacterState::BasicSummon(c) if matches!(c.stage_section, StageSection::Recover)) + { agent.action_timer -= MINION_SUMMON_THRESHOLD; } } else if mindflayer_is_far { @@ -2233,13 +2235,16 @@ impl<'a> AgentData<'a> { }); } else { // If close to target, use either primary or secondary ability - if matches!(self.char_state, CharacterState::BasicBeam(_)) { - // If already using primary, keep using primary + if matches!(self.char_state, CharacterState::BasicBeam(c) if c.timer < Duration::from_secs(10) && !matches!(c.stage_section, StageSection::Recover)) + { + // If already using primary, keep using primary until 10 consecutive seconds controller .actions .push(ControlAction::basic_input(InputKind::Primary)); - } else if matches!(self.char_state, CharacterState::SpinMelee(_)) { - // If already using secondary, keep using secondary + } else if matches!(self.char_state, CharacterState::SpinMelee(c) if c.consecutive_spins < 50 && !matches!(c.stage_section, StageSection::Recover)) + { + // If already using secondary, keep using secondary until 10 consecutive + // seconds controller .actions .push(ControlAction::basic_input(InputKind::Secondary)); @@ -2255,6 +2260,23 @@ impl<'a> AgentData<'a> { .push(ControlAction::basic_input(InputKind::Secondary)); } } + + // Move towards target + if let Some((bearing, speed)) = agent.chaser.chase( + &*terrain, + self.pos.0, + self.vel.0, + tgt_pos.0, + TraversalConfig { + min_tgt_dist: 1.25, + ..self.traversal_config + }, + ) { + controller.inputs.move_dir = + bearing.xy().try_normalized().unwrap_or_else(Vec2::zero) * speed; + self.jump_if(controller, bearing.z > 1.5); + controller.inputs.move_z = bearing.z; + } }, } } diff --git a/world/src/site/dungeon/mod.rs b/world/src/site/dungeon/mod.rs index 7b8ddd6b0d..5ca43e0842 100644 --- a/world/src/site/dungeon/mod.rs +++ b/world/src/site/dungeon/mod.rs @@ -548,6 +548,7 @@ impl Floor { .map(|density| dynamic_rng.gen_range(0..density.recip() as usize) == 0) .unwrap_or(false) && !tile_is_pillar + && (!room.boss || room.difficulty != 5) { // Bad let chosen = match room.difficulty { @@ -833,7 +834,7 @@ impl Floor { "common.loot_tables.loot_table_miniboss", ), 5 => Lottery::::load_expect( - match dynamic_rng.gen_range(0..4) { + match dynamic_rng.gen_range(0..3) { 0 => "common.loot_tables.mindflayer", _ => "common.loot_tables.loot_table_miniboss", }, From 92973a470c8655f4eb46a72ba2ad0b75879d4b5d Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 29 Mar 2021 13:05:04 -0400 Subject: [PATCH 2/2] Made entity spawn room check more intuitive to understand --- world/src/site/dungeon/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/src/site/dungeon/mod.rs b/world/src/site/dungeon/mod.rs index 5ca43e0842..c05e5107d9 100644 --- a/world/src/site/dungeon/mod.rs +++ b/world/src/site/dungeon/mod.rs @@ -548,7 +548,7 @@ impl Floor { .map(|density| dynamic_rng.gen_range(0..density.recip() as usize) == 0) .unwrap_or(false) && !tile_is_pillar - && (!room.boss || room.difficulty != 5) + && !(room.boss && room.difficulty == 5) { // Bad let chosen = match room.difficulty {