mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
added range and angle calculations for projectile attacks; minor tweak to woodgolem shockwave; use of unwrap_or_default & other clippy things
This commit is contained in:
parent
93b336cd20
commit
bdf1134814
@ -9,7 +9,7 @@ Shockwave(
|
|||||||
shockwave_angle: 90.0,
|
shockwave_angle: 90.0,
|
||||||
shockwave_vertical_angle: 90.0,
|
shockwave_vertical_angle: 90.0,
|
||||||
shockwave_speed: 15.0,
|
shockwave_speed: 15.0,
|
||||||
shockwave_duration: 2.0,
|
shockwave_duration: 1.9,
|
||||||
dodgeable: Jump,
|
dodgeable: Jump,
|
||||||
move_efficiency: 0.0,
|
move_efficiency: 0.0,
|
||||||
damage_kind: Crushing,
|
damage_kind: Crushing,
|
||||||
|
@ -13,6 +13,7 @@ use common::{
|
|||||||
Ability, AbilityInput, Agent, CharacterAbility, CharacterState, ControlAction,
|
Ability, AbilityInput, Agent, CharacterAbility, CharacterState, ControlAction,
|
||||||
ControlEvent, Controller, Fluid, InputKind,
|
ControlEvent, Controller, Fluid, InputKind,
|
||||||
},
|
},
|
||||||
|
consts::GRAVITY,
|
||||||
path::TraversalConfig,
|
path::TraversalConfig,
|
||||||
states::{
|
states::{
|
||||||
self_buff,
|
self_buff,
|
||||||
@ -27,6 +28,18 @@ use rand::{prelude::SliceRandom, Rng};
|
|||||||
use std::{f32::consts::PI, time::Duration};
|
use std::{f32::consts::PI, time::Duration};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
|
// ground-level max range from projectile speed and launch height
|
||||||
|
fn projectile_flat_range(speed: f32, height: f32) -> f32 {
|
||||||
|
let w = speed.powi(2);
|
||||||
|
let u = 0.5 * 2_f32.sqrt() * speed;
|
||||||
|
(0.5 * w + u * (0.5 * w + 2.0 * GRAVITY * height).sqrt()) / GRAVITY
|
||||||
|
}
|
||||||
|
|
||||||
|
// multi-projectile spread (in degrees) based on maximum of linear increase
|
||||||
|
fn projectile_multi_angle(projectile_spread: f32, num_projectiles: u32) -> f32 {
|
||||||
|
(180.0 / PI) * projectile_spread * (num_projectiles - 1) as f32
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> AgentData<'a> {
|
impl<'a> AgentData<'a> {
|
||||||
// Intended for any agent that has one attack, that attack is a melee attack,
|
// Intended for any agent that has one attack, that attack is a melee attack,
|
||||||
// and the agent is able to freely walk around
|
// and the agent is able to freely walk around
|
||||||
@ -4770,7 +4783,6 @@ impl<'a> AgentData<'a> {
|
|||||||
// === setup ===
|
// === setup ===
|
||||||
|
|
||||||
// --- static ---
|
// --- static ---
|
||||||
const MAX_PUMPKIN_RANGE: f32 = 50.0;
|
|
||||||
// behaviour parameters
|
// behaviour parameters
|
||||||
const FIRST_VINE_CREATION_THRESHOLD: f32 = 0.60;
|
const FIRST_VINE_CREATION_THRESHOLD: f32 = 0.60;
|
||||||
const SECOND_VINE_CREATION_THRESHOLD: f32 = 0.30;
|
const SECOND_VINE_CREATION_THRESHOLD: f32 = 0.30;
|
||||||
@ -4782,6 +4794,7 @@ impl<'a> AgentData<'a> {
|
|||||||
const FIREBREATH_TIME_LIMIT: f32 = 4.0;
|
const FIREBREATH_TIME_LIMIT: f32 = 4.0;
|
||||||
const FIREBREATH_SHORT_TIME_LIMIT: f32 = 2.5; // cutoff sooner at close range
|
const FIREBREATH_SHORT_TIME_LIMIT: f32 = 2.5; // cutoff sooner at close range
|
||||||
const FIREBREATH_COOLDOWN: f32 = 3.5;
|
const FIREBREATH_COOLDOWN: f32 = 3.5;
|
||||||
|
const PUMPKIN_RANGE_FACTOR: f32 = 0.75;
|
||||||
const CLOSE_MIXUP_COOLDOWN_SPAN: [f32; 2] = [1.5, 7.0]; // variation in attacks at close range
|
const CLOSE_MIXUP_COOLDOWN_SPAN: [f32; 2] = [1.5, 7.0]; // variation in attacks at close range
|
||||||
const MID_MIXUP_COOLDOWN_SPAN: [f32; 2] = [1.5, 4.5]; // ^ mid
|
const MID_MIXUP_COOLDOWN_SPAN: [f32; 2] = [1.5, 4.5]; // ^ mid
|
||||||
const FAR_PUMPKIN_COOLDOWN_SPAN: [f32; 2] = [3.0, 5.0]; // allows for pathing to player between throws
|
const FAR_PUMPKIN_COOLDOWN_SPAN: [f32; 2] = [3.0, 5.0]; // allows for pathing to player between throws
|
||||||
@ -4826,7 +4839,7 @@ impl<'a> AgentData<'a> {
|
|||||||
let scythe_angle;
|
let scythe_angle;
|
||||||
match self
|
match self
|
||||||
.extract_ability(AbilityInput::Primary)
|
.extract_ability(AbilityInput::Primary)
|
||||||
.unwrap_or(AbilityData::default())
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
AbilityData::BasicMelee { range, angle, .. } => {
|
AbilityData::BasicMelee { range, angle, .. } => {
|
||||||
scythe_range = range;
|
scythe_range = range;
|
||||||
@ -4842,7 +4855,7 @@ impl<'a> AgentData<'a> {
|
|||||||
let firebreath_angle;
|
let firebreath_angle;
|
||||||
match self
|
match self
|
||||||
.extract_ability(AbilityInput::Secondary)
|
.extract_ability(AbilityInput::Secondary)
|
||||||
.unwrap_or(AbilityData::default())
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
AbilityData::BasicBeam { range, angle, .. } => {
|
AbilityData::BasicBeam { range, angle, .. } => {
|
||||||
firebreath_range = range;
|
firebreath_range = range;
|
||||||
@ -4854,21 +4867,17 @@ impl<'a> AgentData<'a> {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let pumpkin_speed;
|
let pumpkin_speed = match self
|
||||||
match self
|
|
||||||
.extract_ability(AbilityInput::Auxiliary(0))
|
.extract_ability(AbilityInput::Auxiliary(0))
|
||||||
.unwrap_or(AbilityData::default())
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
AbilityData::BasicRanged {
|
AbilityData::BasicRanged {
|
||||||
projectile_speed, ..
|
projectile_speed, ..
|
||||||
} => {
|
} => projectile_speed,
|
||||||
pumpkin_speed = projectile_speed;
|
_ => 30.0,
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
pumpkin_speed = 30.0;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
// TODO: calculate ground-level max pumpkin range from projectile speed
|
let pumpkin_max_range =
|
||||||
|
projectile_flat_range(pumpkin_speed, self.body.map_or(5.4, |b| b.height()));
|
||||||
|
|
||||||
// character state info
|
// character state info
|
||||||
let mut is_using_firebreath = false;
|
let mut is_using_firebreath = false;
|
||||||
@ -4999,6 +5008,7 @@ impl<'a> AgentData<'a> {
|
|||||||
// mid range (line of sight not needed for these 'suppressing' attacks)
|
// mid range (line of sight not needed for these 'suppressing' attacks)
|
||||||
} else if attack_data.dist_sqrd < firebreath_range.powi(2) {
|
} else if attack_data.dist_sqrd < firebreath_range.powi(2) {
|
||||||
// if using firebreath, keep going under full time limit
|
// if using firebreath, keep going under full time limit
|
||||||
|
#[allow(clippy::if_same_then_else)]
|
||||||
if is_using_firebreath
|
if is_using_firebreath
|
||||||
&& firebreath_timer < Duration::from_secs_f32(FIREBREATH_TIME_LIMIT)
|
&& firebreath_timer < Duration::from_secs_f32(FIREBREATH_TIME_LIMIT)
|
||||||
{
|
{
|
||||||
@ -5025,7 +5035,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// long range (with line of sight)
|
// long range (with line of sight)
|
||||||
else if attack_data.dist_sqrd < MAX_PUMPKIN_RANGE.powi(2)
|
else if attack_data.dist_sqrd < (pumpkin_max_range * PUMPKIN_RANGE_FACTOR).powi(2)
|
||||||
&& agent.combat_state.timers[ActionStateTimers::FarPumpkin as usize]
|
&& agent.combat_state.timers[ActionStateTimers::FarPumpkin as usize]
|
||||||
> agent.combat_state.counters[ActionStateCounters::FarPumpkinCooldown as usize]
|
> agent.combat_state.counters[ActionStateCounters::FarPumpkinCooldown as usize]
|
||||||
&& line_of_sight_with_target()
|
&& line_of_sight_with_target()
|
||||||
@ -6002,7 +6012,7 @@ impl<'a> AgentData<'a> {
|
|||||||
const SPIN_RANGE_FACTOR: f32 = 0.6;
|
const SPIN_RANGE_FACTOR: f32 = 0.6;
|
||||||
const SPIN_COOLDOWN: f32 = 1.5;
|
const SPIN_COOLDOWN: f32 = 1.5;
|
||||||
const SPIN_RELAX_FACTOR: f32 = 0.2;
|
const SPIN_RELAX_FACTOR: f32 = 0.2;
|
||||||
const SHOCKWAVE_RANGE_FACTOR: f32 = 0.6;
|
const SHOCKWAVE_RANGE_FACTOR: f32 = 0.7;
|
||||||
const SHOCKWAVE_AIM_FACTOR: f32 = 0.4;
|
const SHOCKWAVE_AIM_FACTOR: f32 = 0.4;
|
||||||
const SHOCKWAVE_COOLDOWN: f32 = 5.0;
|
const SHOCKWAVE_COOLDOWN: f32 = 5.0;
|
||||||
const MIXUP_COOLDOWN: f32 = 2.5;
|
const MIXUP_COOLDOWN: f32 = 2.5;
|
||||||
@ -6024,7 +6034,7 @@ impl<'a> AgentData<'a> {
|
|||||||
let strike_angle;
|
let strike_angle;
|
||||||
match self
|
match self
|
||||||
.extract_ability(AbilityInput::Primary)
|
.extract_ability(AbilityInput::Primary)
|
||||||
.unwrap_or(AbilityData::default())
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
AbilityData::BasicMelee { range, angle, .. } => {
|
AbilityData::BasicMelee { range, angle, .. } => {
|
||||||
strike_range = range;
|
strike_range = range;
|
||||||
@ -6036,31 +6046,26 @@ impl<'a> AgentData<'a> {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let spin_range;
|
let spin_range = match self
|
||||||
match self
|
|
||||||
.extract_ability(AbilityInput::Secondary)
|
.extract_ability(AbilityInput::Secondary)
|
||||||
.unwrap_or(AbilityData::default())
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
AbilityData::BasicMelee { range, .. } => {
|
AbilityData::BasicMelee { range, .. } => range,
|
||||||
spin_range = range;
|
_ => 5.0,
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
spin_range = 5.0;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let shockwave_max_range;
|
let shockwave_max_range;
|
||||||
let shockwave_angle;
|
let shockwave_angle;
|
||||||
match self
|
match self
|
||||||
.extract_ability(AbilityInput::Auxiliary(0))
|
.extract_ability(AbilityInput::Auxiliary(0))
|
||||||
.unwrap_or(AbilityData::default())
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
AbilityData::Shockwave { angle, range, .. } => {
|
AbilityData::Shockwave { angle, range, .. } => {
|
||||||
shockwave_max_range = range;
|
shockwave_max_range = range;
|
||||||
shockwave_angle = angle;
|
shockwave_angle = angle;
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
shockwave_max_range = 15.0 * 2.0;
|
shockwave_max_range = 15.0 * 1.9;
|
||||||
shockwave_angle = 90.0;
|
shockwave_angle = 90.0;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -6197,15 +6202,12 @@ impl<'a> AgentData<'a> {
|
|||||||
// === setup ===
|
// === setup ===
|
||||||
|
|
||||||
// --- static ---
|
// --- static ---
|
||||||
// hard-coded attack values
|
|
||||||
const BARRAGE_RANGE: f32 = 25.0; // attack logic assumes this is greater than shockwave_range
|
|
||||||
const BARRAGE_ANGLE: f32 = 20.0;
|
|
||||||
// behaviour parameters
|
// behaviour parameters
|
||||||
const PATH_RANGE_FACTOR: f32 = 0.4;
|
const PATH_RANGE_FACTOR: f32 = 0.4;
|
||||||
const STRIKE_RANGE_FACTOR: f32 = 0.7;
|
const STRIKE_RANGE_FACTOR: f32 = 0.7;
|
||||||
const STRIKE_AIM_FACTOR: f32 = 0.8;
|
const STRIKE_AIM_FACTOR: f32 = 0.8;
|
||||||
const BARRAGE_RANGE_FACTOR: f32 = 0.8;
|
const BARRAGE_RANGE_FACTOR: f32 = 0.8;
|
||||||
const BARRAGE_AIM_FACTOR: f32 = 1.0;
|
const BARRAGE_AIM_FACTOR: f32 = 0.65;
|
||||||
const SHOCKWAVE_RANGE_FACTOR: f32 = 0.75;
|
const SHOCKWAVE_RANGE_FACTOR: f32 = 0.75;
|
||||||
const TOTEM_COOLDOWN: f32 = 25.0;
|
const TOTEM_COOLDOWN: f32 = 25.0;
|
||||||
const HEAVY_ATTACK_COOLDOWN_SPAN: [f32; 2] = [8.0, 13.0];
|
const HEAVY_ATTACK_COOLDOWN_SPAN: [f32; 2] = [8.0, 13.0];
|
||||||
@ -6247,7 +6249,7 @@ impl<'a> AgentData<'a> {
|
|||||||
let strike_angle;
|
let strike_angle;
|
||||||
match self
|
match self
|
||||||
.extract_ability(AbilityInput::Primary)
|
.extract_ability(AbilityInput::Primary)
|
||||||
.unwrap_or(AbilityData::default())
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
AbilityData::BasicMelee { range, angle, .. } => {
|
AbilityData::BasicMelee { range, angle, .. } => {
|
||||||
strike_range = range;
|
strike_range = range;
|
||||||
@ -6264,7 +6266,7 @@ impl<'a> AgentData<'a> {
|
|||||||
let barrage_count;
|
let barrage_count;
|
||||||
match self
|
match self
|
||||||
.extract_ability(AbilityInput::Secondary)
|
.extract_ability(AbilityInput::Secondary)
|
||||||
.unwrap_or(AbilityData::default())
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
AbilityData::BasicRanged {
|
AbilityData::BasicRanged {
|
||||||
projectile_speed,
|
projectile_speed,
|
||||||
@ -6282,21 +6284,16 @@ impl<'a> AgentData<'a> {
|
|||||||
barrage_count = 5;
|
barrage_count = 5;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// TODO: calculate ground-level max barrage range from projectile_speed
|
let barrage_max_range =
|
||||||
// TODO: calculaate approx. aiming angle from projectile_spread and
|
projectile_flat_range(barrage_speed, self.body.map_or(2.0, |b| b.height()));
|
||||||
// num_projectiles
|
let barrange_angle = projectile_multi_angle(barrage_spread, barrage_count);
|
||||||
|
|
||||||
let shockwave_range;
|
let shockwave_range = match self
|
||||||
match self
|
|
||||||
.extract_ability(AbilityInput::Auxiliary(0))
|
.extract_ability(AbilityInput::Auxiliary(0))
|
||||||
.unwrap_or(AbilityData::default())
|
.unwrap_or_default()
|
||||||
{
|
{
|
||||||
AbilityData::Shockwave { range, .. } => {
|
AbilityData::Shockwave { range, .. } => range,
|
||||||
shockwave_range = range;
|
_ => 12.0 * 1.0,
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
shockwave_range = 12.0 * 1.0;
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// re-used checks
|
// re-used checks
|
||||||
@ -6361,14 +6358,16 @@ impl<'a> AgentData<'a> {
|
|||||||
controller.push_basic_input(InputKind::Ability(rng.gen_range(1..=3)));
|
controller.push_basic_input(InputKind::Ability(rng.gen_range(1..=3)));
|
||||||
}
|
}
|
||||||
// on timer and in range, use a heavy attack
|
// on timer and in range, use a heavy attack
|
||||||
|
// assumes: barrange_max_range * BARRAGE_RANGE_FACTOR > shockwave_range *
|
||||||
|
// SHOCKWAVE_RANGE_FACTOR
|
||||||
else if agent.combat_state.counters[ActionStateTimers::HeavyAttack as usize]
|
else if agent.combat_state.counters[ActionStateTimers::HeavyAttack as usize]
|
||||||
> agent.combat_state.counters[ActionStateCounters::HeavyAttackCooldown as usize]
|
> agent.combat_state.counters[ActionStateCounters::HeavyAttackCooldown as usize]
|
||||||
&& attack_data.dist_sqrd < (BARRAGE_RANGE * BARRAGE_RANGE_FACTOR).powi(2)
|
&& attack_data.dist_sqrd < (barrage_max_range * BARRAGE_RANGE_FACTOR).powi(2)
|
||||||
{
|
{
|
||||||
// has line of sight
|
// has line of sight
|
||||||
if line_of_sight_with_target() {
|
if line_of_sight_with_target() {
|
||||||
// out of barrage angle, use shockwave
|
// out of barrage angle, use shockwave
|
||||||
if attack_data.angle > BARRAGE_ANGLE * BARRAGE_AIM_FACTOR {
|
if attack_data.angle > barrange_angle * BARRAGE_AIM_FACTOR {
|
||||||
controller.push_basic_input(InputKind::Ability(0));
|
controller.push_basic_input(InputKind::Ability(0));
|
||||||
}
|
}
|
||||||
// in shockwave range, randomise between barrage and shockwave
|
// in shockwave range, randomise between barrage and shockwave
|
||||||
|
Loading…
Reference in New Issue
Block a user