mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'sam/mindflayer-balancing' into 'master'
Mindflayer balance tweaks. See merge request veloren/veloren!2031
This commit is contained in:
commit
12ec46c572
@ -1,5 +1,5 @@
|
|||||||
Blink(
|
Blink(
|
||||||
buildup_duration: 0.5,
|
buildup_duration: 0.75,
|
||||||
recover_duration: 0.25,
|
recover_duration: 0.25,
|
||||||
max_range: 100.0,
|
max_range: 100.0,
|
||||||
)
|
)
|
@ -2,10 +2,10 @@ SpinMelee(
|
|||||||
buildup_duration: 0.5,
|
buildup_duration: 0.5,
|
||||||
swing_duration: 0.2,
|
swing_duration: 0.2,
|
||||||
recover_duration: 0.6,
|
recover_duration: 0.6,
|
||||||
base_damage: 70.0,
|
base_damage: 80.0,
|
||||||
base_poise_damage: 0.0,
|
base_poise_damage: 1.0,
|
||||||
knockback: ( strength: 8.0, direction: Towards),
|
knockback: ( strength: 7.0, direction: Towards),
|
||||||
range: 17.5,
|
range: 16.0,
|
||||||
damage_effect: Some(Lifesteal(1.0)),
|
damage_effect: Some(Lifesteal(1.0)),
|
||||||
energy_cost: 0.0,
|
energy_cost: 0.0,
|
||||||
is_infinite: true,
|
is_infinite: true,
|
||||||
|
@ -1364,7 +1364,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
specifier: *specifier,
|
specifier: *specifier,
|
||||||
},
|
},
|
||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
spins_remaining: *num_spins - 1,
|
consecutive_spins: 1,
|
||||||
stage_section: StageSection::Buildup,
|
stage_section: StageSection::Buildup,
|
||||||
exhausted: false,
|
exhausted: false,
|
||||||
}),
|
}),
|
||||||
|
@ -60,8 +60,8 @@ pub struct Data {
|
|||||||
pub static_data: StaticData,
|
pub static_data: StaticData,
|
||||||
/// Timer for each stage
|
/// Timer for each stage
|
||||||
pub timer: Duration,
|
pub timer: Duration,
|
||||||
/// How many spins it can do before ending
|
/// How many spins it has done
|
||||||
pub spins_remaining: u32,
|
pub consecutive_spins: u32,
|
||||||
/// What section the character stage is in
|
/// What section the character stage is in
|
||||||
pub stage_section: StageSection,
|
pub stage_section: StageSection,
|
||||||
/// Whether the state can deal damage
|
/// Whether the state can deal damage
|
||||||
@ -187,18 +187,13 @@ impl CharacterBehavior for Data {
|
|||||||
..*self
|
..*self
|
||||||
});
|
});
|
||||||
} else if update.energy.current() as f32 >= self.static_data.energy_cost
|
} 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
|
|| (self.static_data.is_infinite
|
||||||
&& input_is_pressed(data, self.static_data.ability_info.input)))
|
&& 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 {
|
update.character = CharacterState::SpinMelee(Data {
|
||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
spins_remaining: new_spins_remaining,
|
consecutive_spins: self.consecutive_spins + 1,
|
||||||
exhausted: false,
|
exhausted: false,
|
||||||
..*self
|
..*self
|
||||||
});
|
});
|
||||||
|
@ -22,6 +22,7 @@ use common::{
|
|||||||
path::TraversalConfig,
|
path::TraversalConfig,
|
||||||
resources::{DeltaTime, Time, TimeOfDay},
|
resources::{DeltaTime, Time, TimeOfDay},
|
||||||
rtsim::{Memory, MemoryItem, RtSimEntity, RtSimEvent},
|
rtsim::{Memory, MemoryItem, RtSimEntity, RtSimEvent},
|
||||||
|
states::utils::StageSection,
|
||||||
terrain::{Block, TerrainGrid},
|
terrain::{Block, TerrainGrid},
|
||||||
time::DayPeriod,
|
time::DayPeriod,
|
||||||
trade::{TradeAction, TradePhase, TradeResult},
|
trade::{TradeAction, TradePhase, TradeResult},
|
||||||
@ -39,7 +40,7 @@ use specs::{
|
|||||||
Entities, Entity as EcsEntity, Join, ParJoin, Read, ReadExpect, ReadStorage, SystemData, World,
|
Entities, Entity as EcsEntity, Join, ParJoin, Read, ReadExpect, ReadStorage, SystemData, World,
|
||||||
Write, WriteExpect, WriteStorage,
|
Write, WriteExpect, WriteStorage,
|
||||||
};
|
};
|
||||||
use std::{f32::consts::PI, sync::Arc};
|
use std::{f32::consts::PI, sync::Arc, time::Duration};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
struct AgentData<'a> {
|
struct AgentData<'a> {
|
||||||
@ -2370,7 +2371,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Tactic::Mindflayer => {
|
Tactic::Mindflayer => {
|
||||||
const MINDFLAYER_ATTACK_DIST: f32 = 17.5;
|
const MINDFLAYER_ATTACK_DIST: f32 = 16.0;
|
||||||
const MINION_SUMMON_THRESHOLD: f32 = 0.20;
|
const MINION_SUMMON_THRESHOLD: f32 = 0.20;
|
||||||
let health_fraction = self.health.map_or(0.5, |h| h.fraction());
|
let health_fraction = self.health.map_or(0.5, |h| h.fraction());
|
||||||
// Extreme hack to set action_timer at start of combat
|
// Extreme hack to set action_timer at start of combat
|
||||||
@ -2382,10 +2383,11 @@ impl<'a> AgentData<'a> {
|
|||||||
let mindflayer_is_far = dist_sqrd > MINDFLAYER_ATTACK_DIST.powi(2);
|
let mindflayer_is_far = dist_sqrd > MINDFLAYER_ATTACK_DIST.powi(2);
|
||||||
if agent.action_timer > health_fraction {
|
if agent.action_timer > health_fraction {
|
||||||
// Summon minions at particular thresholds of health
|
// Summon minions at particular thresholds of health
|
||||||
if !self.char_state.is_attack() {
|
controller
|
||||||
controller
|
.actions
|
||||||
.actions
|
.push(ControlAction::basic_input(InputKind::Ability(1)));
|
||||||
.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;
|
agent.action_timer -= MINION_SUMMON_THRESHOLD;
|
||||||
}
|
}
|
||||||
} else if mindflayer_is_far {
|
} else if mindflayer_is_far {
|
||||||
@ -2401,13 +2403,16 @@ impl<'a> AgentData<'a> {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// If close to target, use either primary or secondary ability
|
// If close to target, use either primary or secondary ability
|
||||||
if matches!(self.char_state, CharacterState::BasicBeam(_)) {
|
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
|
{
|
||||||
|
// If already using primary, keep using primary until 10 consecutive seconds
|
||||||
controller
|
controller
|
||||||
.actions
|
.actions
|
||||||
.push(ControlAction::basic_input(InputKind::Primary));
|
.push(ControlAction::basic_input(InputKind::Primary));
|
||||||
} else if matches!(self.char_state, CharacterState::SpinMelee(_)) {
|
} 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
|
{
|
||||||
|
// If already using secondary, keep using secondary until 10 consecutive
|
||||||
|
// seconds
|
||||||
controller
|
controller
|
||||||
.actions
|
.actions
|
||||||
.push(ControlAction::basic_input(InputKind::Secondary));
|
.push(ControlAction::basic_input(InputKind::Secondary));
|
||||||
@ -2423,6 +2428,23 @@ impl<'a> AgentData<'a> {
|
|||||||
.push(ControlAction::basic_input(InputKind::Secondary));
|
.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;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -548,6 +548,7 @@ impl Floor {
|
|||||||
.map(|density| dynamic_rng.gen_range(0..density.recip() as usize) == 0)
|
.map(|density| dynamic_rng.gen_range(0..density.recip() as usize) == 0)
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
&& !tile_is_pillar
|
&& !tile_is_pillar
|
||||||
|
&& !(room.boss && room.difficulty == 5)
|
||||||
{
|
{
|
||||||
// Bad
|
// Bad
|
||||||
let chosen = match room.difficulty {
|
let chosen = match room.difficulty {
|
||||||
@ -833,7 +834,7 @@ impl Floor {
|
|||||||
"common.loot_tables.loot_table_miniboss",
|
"common.loot_tables.loot_table_miniboss",
|
||||||
),
|
),
|
||||||
5 => Lottery::<String>::load_expect(
|
5 => Lottery::<String>::load_expect(
|
||||||
match dynamic_rng.gen_range(0..4) {
|
match dynamic_rng.gen_range(0..3) {
|
||||||
0 => "common.loot_tables.mindflayer",
|
0 => "common.loot_tables.mindflayer",
|
||||||
_ => "common.loot_tables.loot_table_miniboss",
|
_ => "common.loot_tables.loot_table_miniboss",
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user