mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Reaching stance AI
This commit is contained in:
parent
9b4dcbfdde
commit
eb67cc2cf7
@ -14,7 +14,7 @@ DashMelee(
|
|||||||
energy_regen: 0,
|
energy_regen: 0,
|
||||||
)),
|
)),
|
||||||
range: 4,
|
range: 4,
|
||||||
angle: 45.0,
|
angle: 15.0,
|
||||||
),
|
),
|
||||||
energy_drain: 20,
|
energy_drain: 20,
|
||||||
forward_speed: 3,
|
forward_speed: 3,
|
||||||
|
@ -8,8 +8,8 @@ ComboMelee2(
|
|||||||
knockback: 0,
|
knockback: 0,
|
||||||
energy_regen: 5,
|
energy_regen: 5,
|
||||||
),
|
),
|
||||||
range: 3.0,
|
range: 4.0,
|
||||||
angle: 45.0,
|
angle: 10.0,
|
||||||
),
|
),
|
||||||
buildup_duration: 0.3,
|
buildup_duration: 0.3,
|
||||||
swing_duration: 0.1,
|
swing_duration: 0.1,
|
||||||
@ -25,8 +25,8 @@ ComboMelee2(
|
|||||||
knockback: 0,
|
knockback: 0,
|
||||||
energy_regen: 8,
|
energy_regen: 8,
|
||||||
),
|
),
|
||||||
range: 3.0,
|
range: 5.0,
|
||||||
angle: 45.0,
|
angle: 7.5,
|
||||||
),
|
),
|
||||||
buildup_duration: 0.3,
|
buildup_duration: 0.3,
|
||||||
swing_duration: 0.1,
|
swing_duration: 0.1,
|
||||||
@ -36,7 +36,7 @@ ComboMelee2(
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
is_stance: true,
|
is_stance: true,
|
||||||
energy_cost_per_strike: 15,
|
energy_cost_per_strike: 5,
|
||||||
meta: (
|
meta: (
|
||||||
kind: Some(Sword(Reaching)),
|
kind: Some(Sword(Reaching)),
|
||||||
),
|
),
|
||||||
|
@ -3,13 +3,13 @@ RapidMelee(
|
|||||||
swing_duration: 0.1,
|
swing_duration: 0.1,
|
||||||
recover_duration: 0.5,
|
recover_duration: 0.5,
|
||||||
melee_constructor: (
|
melee_constructor: (
|
||||||
kind: Slash(
|
kind: Stab(
|
||||||
damage: 6,
|
damage: 8,
|
||||||
poise: 0,
|
poise: 0,
|
||||||
knockback: 0,
|
knockback: 0,
|
||||||
energy_regen: 5,
|
energy_regen: 5,
|
||||||
),
|
),
|
||||||
range: 3.5,
|
range: 4.5,
|
||||||
angle: 10.0,
|
angle: 10.0,
|
||||||
),
|
),
|
||||||
energy_cost: 10,
|
energy_cost: 10,
|
||||||
|
@ -25,7 +25,7 @@ ComboMelee2(
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
is_stance: false,
|
is_stance: false,
|
||||||
energy_cost_per_strike: 20,
|
energy_cost_per_strike: 10,
|
||||||
meta: (
|
meta: (
|
||||||
kind: Some(Sword(Reaching)),
|
kind: Some(Sword(Reaching)),
|
||||||
),
|
),
|
||||||
|
@ -503,6 +503,53 @@ impl<'a> AgentData<'a> {
|
|||||||
&& agent_data.energy.current() >= self.energy
|
&& agent_data.energy.current() >= self.energy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
struct DashMeleeData {
|
||||||
|
range: f32,
|
||||||
|
angle: f32,
|
||||||
|
initial_energy: f32,
|
||||||
|
energy_drain: f32,
|
||||||
|
speed: f32,
|
||||||
|
charge_dur: f32,
|
||||||
|
}
|
||||||
|
impl DashMeleeData {
|
||||||
|
// TODO: Maybe figure out better way of pulling in base accel from body and
|
||||||
|
// accounting for friction?
|
||||||
|
const BASE_SPEED: f32 = 3.0;
|
||||||
|
const ORI_RATE: f32 = 30.0;
|
||||||
|
|
||||||
|
fn could_use(&self, attack_data: &AttackData, agent_data: &AgentData) -> bool {
|
||||||
|
let charge_dur = self.charge_dur(agent_data);
|
||||||
|
let charge_dist = charge_dur * self.speed * Self::BASE_SPEED;
|
||||||
|
let attack_dist = charge_dist + self.range;
|
||||||
|
let ori_gap = Self::ORI_RATE * charge_dur;
|
||||||
|
attack_data.dist_sqrd < attack_dist.powi(2)
|
||||||
|
&& attack_data.angle < self.angle + ori_gap
|
||||||
|
&& agent_data.energy.current() > self.initial_energy
|
||||||
|
}
|
||||||
|
|
||||||
|
fn use_desirable(&self, attack_data: &AttackData, agent_data: &AgentData) -> bool {
|
||||||
|
let charge_dist = self.charge_dur(agent_data) * self.speed * Self::BASE_SPEED;
|
||||||
|
attack_data.dist_sqrd / charge_dist.powi(2) > 0.75_f32.powi(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn charge_dur(&self, agent_data: &AgentData) -> f32 {
|
||||||
|
((agent_data.energy.current() - self.initial_energy) / self.energy_drain)
|
||||||
|
.clamp(0.0, self.charge_dur)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
struct RapidMeleeData {
|
||||||
|
range: f32,
|
||||||
|
angle: f32,
|
||||||
|
energy: f32,
|
||||||
|
strikes: u32,
|
||||||
|
}
|
||||||
|
impl RapidMeleeData {
|
||||||
|
fn could_use(&self, attack_data: &AttackData, agent_data: &AgentData) -> bool {
|
||||||
|
attack_data.dist_sqrd < self.range.powi(2)
|
||||||
|
&& attack_data.angle < self.angle
|
||||||
|
&& agent_data.energy.current() > self.energy * self.strikes as f32
|
||||||
|
}
|
||||||
|
}
|
||||||
use ability::SwordStance;
|
use ability::SwordStance;
|
||||||
let stance = |stance| match stance {
|
let stance = |stance| match stance {
|
||||||
1 => SwordStance::Offensive,
|
1 => SwordStance::Offensive,
|
||||||
@ -527,9 +574,8 @@ impl<'a> AgentData<'a> {
|
|||||||
// Hack to make cleaving stance come up less often because agents cannot use it
|
// Hack to make cleaving stance come up less often because agents cannot use it
|
||||||
// effectively due to only considering a single target
|
// effectively due to only considering a single target
|
||||||
// Remove when agents properly consider multiple targets
|
// Remove when agents properly consider multiple targets
|
||||||
// 4 + rng.gen_range(0..13) / 3
|
4 + rng.gen_range(0..13) / 3
|
||||||
// rng.gen_range(4..9)
|
// rng.gen_range(4..9)
|
||||||
6
|
|
||||||
} else if self
|
} else if self
|
||||||
.skill_set
|
.skill_set
|
||||||
.has_skill(Skill::Sword(SwordSkill::OffensiveFinisher))
|
.has_skill(Skill::Sword(SwordSkill::OffensiveFinisher))
|
||||||
@ -732,6 +778,10 @@ impl<'a> AgentData<'a> {
|
|||||||
buff: BuffKind::ProtectingWard,
|
buff: BuffKind::ProtectingWard,
|
||||||
energy: 40.0,
|
energy: 40.0,
|
||||||
};
|
};
|
||||||
|
const MOBILITY_AGILITY: SelfBuffData = SelfBuffData {
|
||||||
|
buff: BuffKind::Hastened,
|
||||||
|
energy: 40.0,
|
||||||
|
};
|
||||||
|
|
||||||
match stance(agent.action_state.int_counter) {
|
match stance(agent.action_state.int_counter) {
|
||||||
SwordStance::Balanced => {
|
SwordStance::Balanced => {
|
||||||
@ -941,10 +991,6 @@ impl<'a> AgentData<'a> {
|
|||||||
angle: 35.0,
|
angle: 35.0,
|
||||||
energy: 10.0,
|
energy: 10.0,
|
||||||
};
|
};
|
||||||
const MOBILITY_AGILITY: SelfBuffData = SelfBuffData {
|
|
||||||
buff: BuffKind::Hastened,
|
|
||||||
energy: 40.0,
|
|
||||||
};
|
|
||||||
const DESIRED_ENERGY: f32 = 50.0;
|
const DESIRED_ENERGY: f32 = 50.0;
|
||||||
|
|
||||||
let mut try_roll = || {
|
let mut try_roll = || {
|
||||||
@ -1452,7 +1498,93 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
SwordStance::Reaching => {
|
SwordStance::Reaching => {
|
||||||
fallback_tactics(agent, controller);
|
const REACHING_COMBO: ComboMeleeData = ComboMeleeData {
|
||||||
|
min_range: 0.0,
|
||||||
|
max_range: 4.5,
|
||||||
|
angle: 6.0,
|
||||||
|
energy: 5.0,
|
||||||
|
};
|
||||||
|
const REACHING_CHARGE: DashMeleeData = DashMeleeData {
|
||||||
|
range: 3.5,
|
||||||
|
angle: 12.5,
|
||||||
|
initial_energy: 10.0,
|
||||||
|
energy_drain: 20.0,
|
||||||
|
speed: 3.0,
|
||||||
|
charge_dur: 1.0,
|
||||||
|
};
|
||||||
|
const REACHING_FLURRY: RapidMeleeData = RapidMeleeData {
|
||||||
|
range: 4.0,
|
||||||
|
angle: 7.5,
|
||||||
|
energy: 10.0,
|
||||||
|
strikes: 6,
|
||||||
|
};
|
||||||
|
const REACHING_SKEWER: ComboMeleeData = ComboMeleeData {
|
||||||
|
min_range: 1.0,
|
||||||
|
max_range: 7.5,
|
||||||
|
angle: 7.5,
|
||||||
|
energy: 10.0,
|
||||||
|
};
|
||||||
|
const DESIRED_ENERGY: f32 = 50.0;
|
||||||
|
|
||||||
|
if self.energy.current() < DESIRED_ENERGY {
|
||||||
|
fallback_tactics(agent, controller);
|
||||||
|
} else if MOBILITY_AGILITY.could_use(self) && MOBILITY_AGILITY.use_desirable(self) {
|
||||||
|
if in_stance(SwordStance::Reaching) {
|
||||||
|
controller.push_basic_input(InputKind::Ability(0));
|
||||||
|
} else {
|
||||||
|
controller.push_basic_input(InputKind::Ability(4));
|
||||||
|
}
|
||||||
|
} else if !in_stance(SwordStance::Reaching) {
|
||||||
|
controller.push_basic_input(InputKind::Ability(0));
|
||||||
|
} else if matches!(self.char_state, CharacterState::DashMelee(s) if s.stage_section != StageSection::Recover)
|
||||||
|
|| (REACHING_CHARGE.could_use(attack_data, self)
|
||||||
|
&& REACHING_CHARGE.use_desirable(attack_data, self))
|
||||||
|
{
|
||||||
|
controller.push_basic_input(InputKind::Ability(1));
|
||||||
|
advance(
|
||||||
|
agent,
|
||||||
|
controller,
|
||||||
|
REACHING_CHARGE.range,
|
||||||
|
REACHING_CHARGE.angle,
|
||||||
|
);
|
||||||
|
} else if REACHING_FLURRY.could_use(attack_data, self)
|
||||||
|
&& matches!(
|
||||||
|
tgt_data.char_state.and_then(|cs| cs.stage_section()),
|
||||||
|
Some(StageSection::Buildup)
|
||||||
|
)
|
||||||
|
&& rng.gen::<f32>() < 0.5
|
||||||
|
{
|
||||||
|
controller.push_basic_input(InputKind::Ability(2));
|
||||||
|
advance(
|
||||||
|
agent,
|
||||||
|
controller,
|
||||||
|
REACHING_FLURRY.range,
|
||||||
|
REACHING_FLURRY.angle,
|
||||||
|
);
|
||||||
|
} else if REACHING_SKEWER.could_use(attack_data, self) && rng.gen::<f32>() < 0.33 {
|
||||||
|
controller.push_basic_input(InputKind::Ability(3));
|
||||||
|
advance(
|
||||||
|
agent,
|
||||||
|
controller,
|
||||||
|
REACHING_SKEWER.max_range,
|
||||||
|
REACHING_SKEWER.angle,
|
||||||
|
);
|
||||||
|
} else if REACHING_COMBO.could_use(attack_data, self) {
|
||||||
|
controller.push_basic_input(InputKind::Primary);
|
||||||
|
advance(
|
||||||
|
agent,
|
||||||
|
controller,
|
||||||
|
REACHING_COMBO.max_range,
|
||||||
|
REACHING_COMBO.angle,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
advance(
|
||||||
|
agent,
|
||||||
|
controller,
|
||||||
|
REACHING_COMBO.max_range,
|
||||||
|
REACHING_COMBO.angle,
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user