mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Unskilled sword AI
This commit is contained in:
parent
387ea16598
commit
c4154b0160
@ -517,61 +517,61 @@ impl<'a> AgentData<'a> {
|
||||
tactics.push(tactic);
|
||||
}
|
||||
};
|
||||
try_tactic(
|
||||
SwordSkill::HeavyFortitude,
|
||||
SwordTactics::HeavyAdvanced,
|
||||
&mut tactics,
|
||||
);
|
||||
try_tactic(
|
||||
SwordSkill::AgileDancingEdge,
|
||||
SwordTactics::AgileAdvanced,
|
||||
&mut tactics,
|
||||
);
|
||||
try_tactic(
|
||||
SwordSkill::DefensiveStalwartSword,
|
||||
SwordTactics::DefensiveAdvanced,
|
||||
&mut tactics,
|
||||
);
|
||||
try_tactic(
|
||||
SwordSkill::CripplingEviscerate,
|
||||
SwordTactics::CripplingAdvanced,
|
||||
&mut tactics,
|
||||
);
|
||||
try_tactic(
|
||||
SwordSkill::CleavingBladeFever,
|
||||
SwordTactics::CleavingAdvanced,
|
||||
&mut tactics,
|
||||
);
|
||||
if tactics.is_empty() {
|
||||
try_tactic(
|
||||
SwordSkill::HeavyWindmillSlash,
|
||||
SwordTactics::HeavySimple,
|
||||
&mut tactics,
|
||||
);
|
||||
try_tactic(
|
||||
SwordSkill::AgileQuickDraw,
|
||||
SwordTactics::AgileSimple,
|
||||
&mut tactics,
|
||||
);
|
||||
try_tactic(
|
||||
SwordSkill::DefensiveDisengage,
|
||||
SwordTactics::DefensiveSimple,
|
||||
&mut tactics,
|
||||
);
|
||||
try_tactic(
|
||||
SwordSkill::CripplingGouge,
|
||||
SwordTactics::CripplingSimple,
|
||||
&mut tactics,
|
||||
);
|
||||
try_tactic(
|
||||
SwordSkill::CleavingWhirlwindSlice,
|
||||
SwordTactics::CleavingSimple,
|
||||
&mut tactics,
|
||||
);
|
||||
}
|
||||
if tactics.is_empty() {
|
||||
try_tactic(SwordSkill::CrescentSlash, SwordTactics::Basic, &mut tactics);
|
||||
}
|
||||
// try_tactic(
|
||||
// SwordSkill::HeavyFortitude,
|
||||
// SwordTactics::HeavyAdvanced,
|
||||
// &mut tactics,
|
||||
// );
|
||||
// try_tactic(
|
||||
// SwordSkill::AgileDancingEdge,
|
||||
// SwordTactics::AgileAdvanced,
|
||||
// &mut tactics,
|
||||
// );
|
||||
// try_tactic(
|
||||
// SwordSkill::DefensiveStalwartSword,
|
||||
// SwordTactics::DefensiveAdvanced,
|
||||
// &mut tactics,
|
||||
// );
|
||||
// try_tactic(
|
||||
// SwordSkill::CripplingEviscerate,
|
||||
// SwordTactics::CripplingAdvanced,
|
||||
// &mut tactics,
|
||||
// );
|
||||
// try_tactic(
|
||||
// SwordSkill::CleavingBladeFever,
|
||||
// SwordTactics::CleavingAdvanced,
|
||||
// &mut tactics,
|
||||
// );
|
||||
// if tactics.is_empty() {
|
||||
// try_tactic(
|
||||
// SwordSkill::HeavyWindmillSlash,
|
||||
// SwordTactics::HeavySimple,
|
||||
// &mut tactics,
|
||||
// );
|
||||
// try_tactic(
|
||||
// SwordSkill::AgileQuickDraw,
|
||||
// SwordTactics::AgileSimple,
|
||||
// &mut tactics,
|
||||
// );
|
||||
// try_tactic(
|
||||
// SwordSkill::DefensiveDisengage,
|
||||
// SwordTactics::DefensiveSimple,
|
||||
// &mut tactics,
|
||||
// );
|
||||
// try_tactic(
|
||||
// SwordSkill::CripplingGouge,
|
||||
// SwordTactics::CripplingSimple,
|
||||
// &mut tactics,
|
||||
// );
|
||||
// try_tactic(
|
||||
// SwordSkill::CleavingWhirlwindSlice,
|
||||
// SwordTactics::CleavingSimple,
|
||||
// &mut tactics,
|
||||
// );
|
||||
// }
|
||||
// if tactics.is_empty() {
|
||||
// try_tactic(SwordSkill::CrescentSlash, SwordTactics::Basic, &mut tactics);
|
||||
// }
|
||||
if tactics.is_empty() {
|
||||
tactics.push(SwordTactics::Unskilled);
|
||||
}
|
||||
@ -753,10 +753,10 @@ impl<'a> AgentData<'a> {
|
||||
|
||||
if let Some(health) = self.health {
|
||||
agent.action_state.int_counters[IntCounters::ActionMode as usize] =
|
||||
if health.fraction() < 0.25 {
|
||||
if health.fraction() < 0.2 {
|
||||
agent.action_state.positions[Positions::GuardedCover as usize] = None;
|
||||
ActionMode::Fleeing as u8
|
||||
} else if health.fraction() < 0.75 {
|
||||
} else if health.fraction() < 0.9 {
|
||||
agent.action_state.positions[Positions::Flee as usize] = None;
|
||||
ActionMode::Guarded as u8
|
||||
} else {
|
||||
@ -769,6 +769,7 @@ impl<'a> AgentData<'a> {
|
||||
enum IntCounters {
|
||||
Tactics = 0,
|
||||
ActionMode = 1,
|
||||
NextInput = 2,
|
||||
}
|
||||
|
||||
enum Timers {
|
||||
@ -779,6 +780,7 @@ impl<'a> AgentData<'a> {
|
||||
enum Conditions {
|
||||
GuardedAttack = 0,
|
||||
RollingBreakThrough = 1,
|
||||
TacticMisc = 2,
|
||||
}
|
||||
|
||||
enum FloatCounters {
|
||||
@ -990,7 +992,7 @@ impl<'a> AgentData<'a> {
|
||||
- 1.0;
|
||||
agent.action_state.conditions
|
||||
[Conditions::RollingBreakThrough as usize] = true;
|
||||
Some(self.pos.0 - rand_dir * actual_dist)
|
||||
Some(self.pos.0 - rand_dir * dist)
|
||||
} else {
|
||||
Some(self.pos.0 + rand_dir * actual_dist)
|
||||
}
|
||||
@ -1027,23 +1029,85 @@ impl<'a> AgentData<'a> {
|
||||
extract_ability(AbilityInput::Auxiliary(3)),
|
||||
extract_ability(AbilityInput::Auxiliary(4)),
|
||||
];
|
||||
fn input_from_u8(x: u8) -> Option<InputKind> {
|
||||
let input = match x {
|
||||
x @ 0..5 => InputKind::Ability(x as usize),
|
||||
6 => InputKind::Primary,
|
||||
7 => InputKind::Secondary,
|
||||
_ => return None,
|
||||
};
|
||||
Some(input)
|
||||
}
|
||||
fn input_to_u8(input: InputKind) -> u8 {
|
||||
match input {
|
||||
InputKind::Ability(x) => x as u8,
|
||||
InputKind::Primary => 6,
|
||||
InputKind::Secondary => 7,
|
||||
_ => 255,
|
||||
}
|
||||
}
|
||||
let could_use_input = |input| match input {
|
||||
InputKind::Primary => primary.map_or(false, |p| p.could_use(attack_data, self)),
|
||||
InputKind::Secondary => secondary.map_or(false, |s| s.could_use(attack_data, self)),
|
||||
InputKind::Ability(x) => abilities[x]
|
||||
.as_ref()
|
||||
.map_or(false, |a| a.could_use(attack_data, self)),
|
||||
_ => false,
|
||||
};
|
||||
match SwordTactics::from_u8(
|
||||
agent.action_state.int_counters[IntCounters::Tactics as usize],
|
||||
) {
|
||||
SwordTactics::Unskilled => {},
|
||||
SwordTactics::Basic => {},
|
||||
SwordTactics::HeavySimple => {},
|
||||
SwordTactics::AgileSimple => {},
|
||||
SwordTactics::DefensiveSimple => {},
|
||||
SwordTactics::CripplingSimple => {},
|
||||
SwordTactics::CleavingSimple => {},
|
||||
SwordTactics::HeavyAdvanced => {},
|
||||
SwordTactics::AgileAdvanced => {},
|
||||
SwordTactics::DefensiveAdvanced => {},
|
||||
SwordTactics::CripplingAdvanced => {},
|
||||
SwordTactics::CleavingAdvanced => {},
|
||||
SwordTactics::Unskilled => {
|
||||
let current_input = self.char_state.ability_info().map(|ai| ai.input);
|
||||
let mut next_input = None;
|
||||
if let Some(input) = current_input {
|
||||
if let input = InputKind::Secondary {
|
||||
let charging = matches!(
|
||||
self.char_state.stage_section(),
|
||||
Some(StageSection::Charge)
|
||||
);
|
||||
let charged = self
|
||||
.char_state
|
||||
.durations()
|
||||
.and_then(|durs| durs.charge)
|
||||
.zip(self.char_state.timer())
|
||||
.map_or(false, |(dur, timer)| timer > dur);
|
||||
if !(charging && charged) {
|
||||
next_input = Some(InputKind::Secondary);
|
||||
}
|
||||
} else {
|
||||
next_input = Some(input);
|
||||
}
|
||||
} else {
|
||||
if rng.gen_bool(0.5) {
|
||||
next_input = Some(InputKind::Primary);
|
||||
} else {
|
||||
next_input = Some(InputKind::Secondary);
|
||||
}
|
||||
};
|
||||
if let Some(input) = next_input {
|
||||
if could_use_input(input) {
|
||||
controller.push_basic_input(input);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
},
|
||||
SwordTactics::Basic => true,
|
||||
SwordTactics::HeavySimple => true,
|
||||
SwordTactics::AgileSimple => true,
|
||||
SwordTactics::DefensiveSimple => true,
|
||||
SwordTactics::CripplingSimple => true,
|
||||
SwordTactics::CleavingSimple => true,
|
||||
SwordTactics::HeavyAdvanced => true,
|
||||
SwordTactics::AgileAdvanced => true,
|
||||
SwordTactics::DefensiveAdvanced => true,
|
||||
SwordTactics::CripplingAdvanced => true,
|
||||
SwordTactics::CleavingAdvanced => true,
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
@ -230,6 +230,13 @@ pub enum AbilityData {
|
||||
strikes: u32,
|
||||
combo: u32,
|
||||
},
|
||||
ChargedMelee {
|
||||
range: f32,
|
||||
angle: f32,
|
||||
initial_energy: f32,
|
||||
energy_drain: f32,
|
||||
charge_dur: f32,
|
||||
},
|
||||
}
|
||||
|
||||
impl AbilityData {
|
||||
@ -310,6 +317,19 @@ impl AbilityData {
|
||||
strikes: max_strikes.unwrap_or(100),
|
||||
combo: *minimum_combo,
|
||||
},
|
||||
ChargedMelee {
|
||||
energy_cost,
|
||||
energy_drain,
|
||||
charge_duration,
|
||||
melee_constructor,
|
||||
..
|
||||
} => Self::ChargedMelee {
|
||||
initial_energy: *energy_cost,
|
||||
energy_drain: *energy_drain,
|
||||
charge_dur: *charge_duration,
|
||||
range: melee_constructor.range,
|
||||
angle: melee_constructor.angle,
|
||||
},
|
||||
_ => return None,
|
||||
};
|
||||
Some(inner)
|
||||
@ -379,6 +399,16 @@ impl AbilityData {
|
||||
&& energy_check(*energy_per_strike * *strikes as f32)
|
||||
&& combo_check(*combo)
|
||||
},
|
||||
ChargedMelee {
|
||||
range,
|
||||
angle,
|
||||
initial_energy,
|
||||
energy_drain,
|
||||
charge_dur,
|
||||
} => {
|
||||
melee_check(*range, *angle)
|
||||
&& energy_check(*initial_energy + *energy_drain * *charge_dur)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
#![feature(exclusive_range_pattern)]
|
||||
|
||||
#[cfg(all(feature = "be-dyn-lib", feature = "use-dyn-lib"))]
|
||||
compile_error!("Can't use both \"be-dyn-lib\" and \"use-dyn-lib\" features at once");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user