Adlet hunter AI

This commit is contained in:
Sam 2023-03-21 22:11:48 -04:00
parent 92e28f09fc
commit 680d987e11
43 changed files with 224 additions and 46 deletions

View File

@ -748,23 +748,23 @@
// Adlets
// TODO: Do we want to eventually convert these to simple variants of weapons?
Custom("Adlet Hunter"): (
primary: "common.abilities.adlet.hunter.stab",
secondary: "common.abilities.adlet.hunter.throw",
primary: Simple(None, "common.abilities.adlet.hunter.stab"),
secondary: Simple(None, "common.abilities.adlet.hunter.throw"),
abilities: [],
),
Custom("Adlet Icepicker"): (
primary: "common.abilities.adlet.icepicker.spike",
secondary: "common.abilities.adlet.icepicker.leap",
primary: Simple(None, "common.abilities.adlet.icepicker.spike"),
secondary: Simple(None, "common.abilities.adlet.icepicker.leap"),
abilities: [],
),
Custom("Adlet Tracker"): (
primary: "common.abilities.adlet.tracker.arrow",
secondary: "common.abilities.adlet.tracker.trap",
primary: Simple(None, "common.abilities.adlet.tracker.arrow"),
secondary: Simple(None, "common.abilities.adlet.tracker.trap"),
abilities: [],
),
// Custom("Adlet Alpha"): (
// primary: "common.abilities.adlet.alpha",
// secondary: "common.abilities.adlet.alpha",
// primary: Simple(None, "common.abilities.adlet.alpha"),
// secondary: Simple(None, "common.abilities.adlet.alpha"),
// abilities: [],
// ),
})

View File

@ -12,4 +12,5 @@ BasicRanged(
projectile_speed: 40.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 1.0,
)

View File

@ -12,4 +12,5 @@ BasicRanged(
projectile_speed: 100.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -9,4 +9,5 @@ BasicRanged(
projectile_speed: 10.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -12,4 +12,5 @@ BasicRanged(
projectile_light: None,
projectile_speed: 80.0,
num_projectiles: 5,
move_efficiency: 0.3,
)

View File

@ -12,4 +12,5 @@ BasicRanged(
projectile_speed: 100.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -16,4 +16,5 @@ BasicRanged(
projectile_speed: 260.0,
num_projectiles: 1,
projectile_spread: 0.3,
move_efficiency: 0.3,
)

View File

@ -16,4 +16,5 @@ BasicRanged(
projectile_speed: 70.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -16,4 +16,5 @@ BasicRanged(
projectile_speed: 60.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -16,4 +16,5 @@ BasicRanged(
projectile_speed: 60.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -18,4 +18,5 @@ BasicRanged(
strength: DamageFraction(0.1),
chance: 1.0,
))),
move_efficiency: 0.3,
)

View File

@ -13,4 +13,5 @@ BasicRanged(
projectile_speed: 30.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -16,4 +16,5 @@ BasicRanged(
projectile_speed: 60.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -13,4 +13,5 @@ BasicRanged(
projectile_speed: 20.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -16,4 +16,5 @@ BasicRanged(
projectile_speed: 60.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -16,4 +16,5 @@ BasicRanged(
projectile_speed: 60.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -12,4 +12,5 @@ BasicRanged(
projectile_speed: 25.0,
num_projectiles: 5,
projectile_spread: 0.07,
move_efficiency: 0.3,
)

View File

@ -13,4 +13,5 @@ BasicRanged(
projectile_speed: 30.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -16,4 +16,5 @@ BasicRanged(
projectile_speed: 70.0,
num_projectiles: 3,
projectile_spread: 0.2,
move_efficiency: 0.3,
)

View File

@ -11,5 +11,6 @@ BasicRanged(
projectile_speed: 100.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -16,4 +16,5 @@ BasicRanged(
projectile_speed: 70.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -16,4 +16,5 @@ BasicRanged(
projectile_speed: 60.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -12,4 +12,5 @@ BasicRanged(
projectile_speed: 130.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -16,4 +16,5 @@ BasicRanged(
projectile_speed: 60.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -15,4 +15,5 @@ BasicRanged(
projectile_speed: 60.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -11,4 +11,5 @@ BasicRanged(
projectile_speed: 60.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -11,4 +11,5 @@ BasicRanged(
projectile_speed: 100.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -12,4 +12,5 @@ BasicRanged(
projectile_speed: 80.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -12,4 +12,5 @@ BasicRanged(
projectile_speed: 25,
num_projectiles: 8,
projectile_spread: 0.125,
move_efficiency: 0.3,
)

View File

@ -12,4 +12,5 @@ BasicRanged(
projectile_speed: 60.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -16,4 +16,5 @@ BasicRanged(
projectile_speed: 60.0,
num_projectiles: 1,
projectile_spread: 0.0,
move_efficiency: 0.3,
)

View File

@ -11,6 +11,6 @@
)),
),
meta: [
SkillSetAsset("common.skillset.preset.rank1.fullskill"),
SkillSetAsset("common.skillset.preset.rank1.general"),
],
)

View File

@ -11,6 +11,6 @@
)),
),
meta: [
SkillSetAsset("common.skillset.preset.rank1.fullskill"),
SkillSetAsset("common.skillset.preset.rank1.general"),
],
)

View File

@ -11,6 +11,6 @@
)),
),
meta: [
SkillSetAsset("common.skillset.preset.rank1.fullskill"),
SkillSetAsset("common.skillset.preset.rank1.general"),
],
)

View File

@ -502,6 +502,7 @@ pub enum CharacterAbility {
num_projectiles: u32,
projectile_spread: f32,
damage_effect: Option<CombatEffect>,
move_efficiency: f32,
#[serde(default)]
meta: AbilityMeta,
},
@ -1019,6 +1020,7 @@ impl CharacterAbility {
num_projectiles: _,
projectile_spread: _,
damage_effect: _,
move_efficiency: _,
meta: _,
} => {
*buildup_duration /= stats.speed;
@ -2169,6 +2171,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
num_projectiles,
projectile_spread,
damage_effect,
move_efficiency,
meta: _,
} => CharacterState::BasicRanged(basic_ranged::Data {
static_data: basic_ranged::StaticData {
@ -2182,6 +2185,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
projectile_spread: *projectile_spread,
ability_info,
damage_effect: *damage_effect,
move_efficiency: *move_efficiency,
},
timer: Duration::default(),
stage_section: StageSection::Buildup,

View File

@ -34,8 +34,8 @@ pub struct StaticData {
pub num_projectiles: u32,
/// What key is used to press ability
pub ability_info: AbilityInfo,
///
pub damage_effect: Option<CombatEffect>,
pub move_efficiency: f32,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@ -56,7 +56,7 @@ impl CharacterBehavior for Data {
let mut update = StateUpdate::from(data);
handle_orientation(data, &mut update, 1.0, None);
handle_move(data, &mut update, 0.3);
handle_move(data, &mut update, self.static_data.move_efficiency);
handle_jump(data, output_events, &mut update, 1.0);
match self.stage_section {

View File

@ -1014,6 +1014,9 @@ impl<'a> AgentData<'a> {
"Gnarling Chieftain" => Tactic::GnarlingChieftain,
"Frost Gigas" => Tactic::FrostGigas,
"Boreal Hammer" => Tactic::BorealHammer,
"Adlet Hunter" => Tactic::AdletHunter,
"Adlet Icepicker" => Tactic::AdletIcepicker,
"Adlet Tracker" => Tactic::AdletTracker,
_ => Tactic::SimpleMelee,
},
AbilitySpec::Tool(tool_kind) => tool_tactic(*tool_kind),
@ -1457,6 +1460,20 @@ impl<'a> AgentData<'a> {
tgt_data,
read_data,
),
Tactic::AdletHunter => {
self.handle_adlet_hunter(agent, controller, &attack_data, tgt_data, read_data, rng)
},
Tactic::AdletIcepicker => self.handle_adlet_icepicker(
agent,
controller,
&attack_data,
tgt_data,
read_data,
rng,
),
Tactic::AdletTracker => {
self.handle_adlet_tracker(agent, controller, &attack_data, tgt_data, read_data, rng)
},
}
}

View File

@ -757,41 +757,24 @@ impl<'a> AgentData<'a> {
);
let attack_failed = if attempt_attack {
let contexts = AbilityContext::from(self.stance, Some(self.inventory));
let extract_ability = |input: AbilityInput| {
AbilityData::from_ability(
&self
.active_abilities
.activate_ability(
input,
Some(self.inventory),
self.skill_set,
self.body,
Some(self.char_state),
&contexts,
)
.unwrap_or_default()
.0,
)
};
let primary = extract_ability(AbilityInput::Primary);
let secondary = extract_ability(AbilityInput::Secondary);
let primary = self.extract_ability(AbilityInput::Primary);
let secondary = self.extract_ability(AbilityInput::Secondary);
let abilities = [
extract_ability(AbilityInput::Auxiliary(0)),
extract_ability(AbilityInput::Auxiliary(1)),
extract_ability(AbilityInput::Auxiliary(2)),
extract_ability(AbilityInput::Auxiliary(3)),
extract_ability(AbilityInput::Auxiliary(4)),
self.extract_ability(AbilityInput::Auxiliary(0)),
self.extract_ability(AbilityInput::Auxiliary(1)),
self.extract_ability(AbilityInput::Auxiliary(2)),
self.extract_ability(AbilityInput::Auxiliary(3)),
self.extract_ability(AbilityInput::Auxiliary(4)),
];
let could_use_input = |input, desired_energy| match input {
InputKind::Primary => primary.as_ref().map_or(false, |p| {
p.could_use(attack_data, self, tgt_data, desired_energy)
p.could_use(attack_data, self, tgt_data, read_data, desired_energy)
}),
InputKind::Secondary => secondary.as_ref().map_or(false, |s| {
s.could_use(attack_data, self, tgt_data, desired_energy)
s.could_use(attack_data, self, tgt_data, read_data, desired_energy)
}),
InputKind::Ability(x) => abilities[x].as_ref().map_or(false, |a| {
a.could_use(attack_data, self, tgt_data, desired_energy)
a.could_use(attack_data, self, tgt_data, read_data, desired_energy)
}),
_ => false,
};
@ -4585,4 +4568,68 @@ impl<'a> AgentData<'a> {
);
}
}
pub fn handle_adlet_hunter(
&self,
agent: &mut Agent,
controller: &mut Controller,
attack_data: &AttackData,
tgt_data: &TargetData,
read_data: &ReadData,
rng: &mut impl Rng,
) {
let primary = self.extract_ability(AbilityInput::Primary);
let secondary = self.extract_ability(AbilityInput::Secondary);
let could_use_input = |input| match input {
InputKind::Primary => primary.as_ref().map_or(false, |p| {
p.could_use(attack_data, self, tgt_data, read_data, 0.0)
}),
InputKind::Secondary => secondary.as_ref().map_or(false, |s| {
s.could_use(attack_data, self, tgt_data, read_data, 0.0)
}),
_ => false,
};
let move_forwards = if could_use_input(InputKind::Primary) {
controller.push_basic_input(InputKind::Primary);
false
} else if could_use_input(InputKind::Secondary) && attack_data.dist_sqrd > 8_f32.powi(2) {
controller.push_basic_input(InputKind::Secondary);
true
} else {
true
};
if move_forwards && attack_data.dist_sqrd > 3_f32.powi(2) {
self.path_toward_target(
agent,
controller,
tgt_data.pos.0,
read_data,
Path::Separate,
None,
);
}
}
pub fn handle_adlet_icepicker(
&self,
agent: &mut Agent,
controller: &mut Controller,
attack_data: &AttackData,
tgt_data: &TargetData,
read_data: &ReadData,
rng: &mut impl Rng,
) {
}
pub fn handle_adlet_tracker(
&self,
agent: &mut Agent,
controller: &mut Controller,
attack_data: &AttackData,
tgt_data: &TargetData,
read_data: &ReadData,
rng: &mut impl Rng,
) {
}
}

View File

@ -1,3 +1,4 @@
use crate::util::*;
use common::{
comp::{
ability::CharacterAbility,
@ -9,6 +10,7 @@ use common::{
LightEmitter, LootOwner, Ori, PhysicsState, Poise, Pos, Presence, PresenceKind, Scale,
SkillSet, Stance, Stats, Vel,
},
consts::GRAVITY,
link::Is,
mounting::{Mount, Rider, VolumeRider},
path::TraversalConfig,
@ -171,6 +173,11 @@ pub enum Tactic {
BorealHammer,
Dullahan,
Cyclops,
// Adlets
AdletHunter,
AdletIcepicker,
AdletTracker,
}
#[derive(Copy, Clone)]
@ -331,6 +338,15 @@ pub enum AbilityData {
blocked_attacks: AttackFilters,
angle: f32,
},
BasicRanged {
energy: f32,
projectile_speed: f32,
},
BasicMelee {
energy: f32,
range: f32,
angle: f32,
},
}
impl AbilityData {
@ -453,6 +469,23 @@ impl AbilityData {
angle: *max_angle,
blocked_attacks: *blocked_attacks,
},
BasicRanged {
energy_cost,
projectile_speed,
..
} => Self::BasicRanged {
energy: *energy_cost,
projectile_speed: *projectile_speed,
},
BasicMelee {
energy_cost,
melee_constructor,
..
} => Self::BasicMelee {
energy: *energy_cost,
range: melee_constructor.range,
angle: melee_constructor.angle,
},
_ => return None,
};
Some(inner)
@ -463,6 +496,7 @@ impl AbilityData {
attack_data: &AttackData,
agent_data: &AgentData,
tgt_data: &TargetData,
read_data: &ReadData,
desired_energy: f32,
) -> bool {
let melee_check = |range: f32, angle, forced_movement: Option<ForcedMovement>| {
@ -487,6 +521,22 @@ impl AbilityData {
.and_then(|cs| cs.attack_kind())
.map_or(false, |ak| attacks.applies(ak))
};
let ranged_check = |proj_speed| {
let max_horiz_dist: f32 = {
let flight_time = proj_speed * 2_f32.sqrt() / GRAVITY;
proj_speed * 2_f32.sqrt() / 2.0 * flight_time
};
attack_data.dist_sqrd < max_horiz_dist.powi(2)
&& entities_have_line_of_sight(
agent_data.pos,
agent_data.body,
agent_data.scale,
tgt_data.pos,
tgt_data.body,
tgt_data.scale,
read_data,
)
};
use AbilityData::*;
match self {
ComboMelee {
@ -587,6 +637,15 @@ impl AbilityData {
.and_then(|cs| cs.stage_section())
.map_or(false, |ss| !matches!(ss, StageSection::Recover))
},
BasicRanged {
energy,
projectile_speed,
} => ranged_check(*projectile_speed) && energy_check(*energy),
BasicMelee {
energy,
range,
angle,
} => melee_check(*range, *angle, None) && energy_check(*energy),
}
}
}

View File

@ -1,8 +1,11 @@
use crate::data::{ActionMode, AgentData, AttackData, Path, ReadData, TargetData};
use crate::data::{AbilityData, ActionMode, AgentData, AttackData, Path, ReadData, TargetData};
use common::{
comp::{
agent::Psyche, buff::BuffKind, inventory::item::ItemTag, item::ItemDesc, Agent, Alignment,
Body, Controller, InputKind, Pos, Scale,
ability::AbilityInput,
agent::Psyche,
buff::BuffKind,
item::{tool::AbilityContext, ItemDesc, ItemTag},
Agent, Alignment, Body, Controller, InputKind, Pos, Scale,
},
consts::GRAVITY,
terrain::Block,
@ -205,6 +208,24 @@ impl<'a> AgentData<'a> {
.get(*self.entity)
.map_or(false, |b| b.kinds.contains_key(&buff))
}
pub fn extract_ability(&self, input: AbilityInput) -> Option<AbilityData> {
let context = AbilityContext::from(self.stance, Some(self.inventory));
AbilityData::from_ability(
&self
.active_abilities
.activate_ability(
input,
Some(self.inventory),
self.skill_set,
self.body,
Some(self.char_state),
&context,
)
.unwrap_or_default()
.0,
)
}
}
// Probably works best for melee (or maybe only for melee considering its

View File

@ -113,7 +113,7 @@ impl Animation for AlphaAnimation {
next.tail.orientation = Quaternion::rotation_x(0.05 * fastalt * speednormcancel)
* Quaternion::rotation_z(fast * 0.15 * speednormcancel);
},
Some(ToolKind::Axe) | Some(ToolKind::Hammer) => {
Some(ToolKind::Axe) | Some(ToolKind::Hammer) | Some(ToolKind::Pick) => {
next.head.orientation = Quaternion::rotation_z(move1abs * 0.3 + move2abs * -0.6);
next.control_l.position = Vec3::new(2.0 - s_a.grip.0 * 2.0, 1.0, 3.0);
next.control_r.position = Vec3::new(

View File

@ -39,7 +39,7 @@ impl Animation for LeapAnimation {
_ => (0.0, 0.0, 0.0, 0.0),
};
if let Some(ToolKind::Hammer) = active_tool_kind {
if let Some(ToolKind::Hammer | ToolKind::Pick) = active_tool_kind {
next.hand_l.position = Vec3::new(s_a.grip.0 * 2.0, 0.0, s_a.grip.2);
next.hand_r.position = Vec3::new(-s_a.grip.0 * 2.0, 0.0, s_a.grip.2);
next.hand_l.orientation = Quaternion::rotation_x(0.0);

View File

@ -167,7 +167,7 @@ impl Animation for WieldAnimation {
* Quaternion::rotation_y(-0.2 * speednorm)
* Quaternion::rotation_z(0.5);
},
Some(ToolKind::Axe) | Some(ToolKind::Hammer) => {
Some(ToolKind::Axe) | Some(ToolKind::Hammer | ToolKind::Pick) => {
next.control_l.position = Vec3::new(2.0 - s_a.grip.0 * 2.0, 1.0, 3.0);
next.control_r.position =
Vec3::new(9.0 + s_a.grip.0 * 2.0, -1.0, -2.0 + speednorm * -3.0);