Deadwood ai

This commit is contained in:
Sam 2022-01-30 18:04:09 -05:00
parent cb48dd0a75
commit f1801560fa
16 changed files with 159 additions and 64 deletions

View File

@ -79,6 +79,11 @@
secondary: "common.abilities.gnarling.blowgun.dart",
abilities: [],
),
Custom("Deadwood"): (
primary: "common.abilities.custom.deadwood.lifestealbeam",
secondary: "common.abilities.custom.deadwood.dash",
abilities: [],
),
Custom("Sword Simple"): (
primary: "common.abilities.swordsimple.doublestrike",
secondary: "common.abilities.swordsimple.dash",

View File

@ -0,0 +1,28 @@
DashMelee(
energy_cost: 0,
melee_constructor: (
kind: Bash(
damage: 8.0,
poise: 25.0,
knockback: 4.0,
energy_regen: 0.0,
),
scaled: Some(Bash(
damage: 15.0,
poise: 0.0,
knockback: 17.0,
energy_regen: 0.0,
)),
range: 4,
angle: 45.0,
),
energy_drain: 0,
forward_speed: 3,
buildup_duration: 0.5,
charge_duration: 1.0,
swing_duration: 0.1,
recover_duration: 1.0,
ori_modifier: 0.1,
charge_through: true,
is_interruptible: false,
)

View File

@ -0,0 +1,14 @@
BasicBeam(
buildup_duration: 0.25,
recover_duration: 0.25,
beam_duration: 1,
damage: 3.0,
tick_rate: 2.0,
range: 25.0,
max_angle: 1.0,
damage_effect: Some(Lifesteal(0.15)),
energy_regen: 2.5,
energy_drain: 0,
ori_rate: 0.3,
specifier: LifestealBeam,
)

View File

@ -3,16 +3,14 @@ BasicMelee(
buildup_duration: 0.2,
swing_duration: 0.05,
recover_duration: 0.3,
base_damage: 6,
base_poise_damage: 5,
knockback: ( strength: 0, direction: Away),
range: 3,
max_angle: 30,
damage_effect: Some(Buff((
kind: Bleeding,
dur_secs: 10,
strength: DamageFraction(0.1),
chance: 0.1,
))),
damage_kind: Slashing,
melee_constructor: (
kind: Slash(
damage: 6,
poise: 5,
knockback: 0,
energy_regen: 0,
),
range: 3,
angle: 30,
),
)

View File

@ -3,16 +3,14 @@ BasicMelee(
buildup_duration: 0.1,
swing_duration: 0.05,
recover_duration: 0.25,
base_damage: 4,
base_poise_damage: 0,
knockback: ( strength: 0, direction: Away),
range: 2,
max_angle: 15,
damage_effect: Some(Buff((
kind: Bleeding,
dur_secs: 10,
strength: DamageFraction(0.2),
chance: 0.3,
))),
damage_kind: Piercing,
melee_constructor: (
kind: Stab(
damage: 4,
poise: 0,
knockback: 0,
energy_regen: 0,
),
range: 2,
angle: 15,
),
)

View File

@ -1,8 +0,0 @@
(
name: Name("Deadwood"),
body: RandomWith("deadwood"),
alignment: Alignment(Enemy),
loadout: FromBody,
loot: LootTable("common.loot_tables.dungeon.tier-0.miniboss"),
meta: [],
)

View File

@ -2,12 +2,7 @@ EntityConfig (
name: Name("Mandragora"),
body: RandomWith("mandragora"),
alignment: Alignment(Enemy),
loadout: Asset(Loadout("common.loadout.dungeon.gnarling.mandragora")),
loot: LootTable("common.loot_tables.dungeon.tier-0.miniboss"),
hands: Uninit,
meta: [
LoadoutAsset("common.loadout.dungeon.gnarling.mandragora"),
],
meta: [],
)

View File

@ -2,10 +2,7 @@ EntityConfig (
name: Name("Wooden Golem"),
body: RandomWith("woodgolem"),
alignment: Alignment(Enemy),
loadout: FromBody,
loot: LootTable("common.loot_tables.dungeon.tier-0.miniboss"),
hands: Uninit,
meta: [],
)

View File

@ -0,0 +1,21 @@
ItemDef(
name: "Deadwood",
description: "testing123",
kind: Tool((
kind: Natural,
hands: Two,
stats: Direct((
equip_time_secs: 0.01,
power: 1.0,
effect_power: 1.0,
speed: 1.0,
crit_chance: 0.1,
range: 1.0,
energy_efficiency: 1.0,
buff_strength: 1.0,
)),
)),
quality: Low,
tags: [],
ability_spec: Some(Custom("Deadwood")),
)

View File

@ -398,7 +398,7 @@ void main() {
attr = Attr(
spiral_motion(inst_dir, 0.3 * (floor(2 * rand0 + 0.5) - 0.5) * min(linear_scale(10), 1), lifetime / inst_lifespan, 10.0, inst_time),
vec3((1.7 - 0.7 * abs(floor(2 * rand0 - 0.5) + 0.5)) * (1.5 + 0.5 * sin(tick.x * 10 - lifetime * 4))),
vec4(vec3(red_col + purple_col * 0.6, green_col + purple_col * 0.35, purple_col), 1),
vec4(vec3(purple_col, green_col, 0.75 * purple_col), 1),
spin_in_axis(inst_dir, tick.z)
);
break;

View File

@ -241,7 +241,7 @@ fn default_main_tool(body: &Body) -> Item {
"common.items.npc_weapons.unique.quadlowbreathe",
)),
quadruped_low::Species::Deadwood => Some(Item::new_from_asset_expect(
"common.items.npc_weapons.unique.quadlowbeam",
"common.items.npc_weapons.unique.deadwood",
)),
quadruped_low::Species::Basilisk => Some(Item::new_from_asset_expect(
"common.items.npc_weapons.unique.basilisk",

View File

@ -1747,6 +1747,7 @@ impl<'a> AgentData<'a> {
"Harvester" => Tactic::Harvester,
"Gnarling Dagger" => Tactic::SimpleBackstab,
"Gnarling Blowgun" => Tactic::ElevatedRanged,
"Deadwood" => Tactic::Deadwood,
_ => Tactic::SimpleMelee,
},
AbilitySpec::Tool(tool_kind) => tool_tactic(*tool_kind),
@ -2124,6 +2125,9 @@ impl<'a> AgentData<'a> {
Tactic::ElevatedRanged => {
self.handle_elevated_ranged(agent, controller, &attack_data, tgt_data, read_data)
},
Tactic::Deadwood => {
self.handle_deadwood(agent, controller, &attack_data, tgt_data, read_data)
},
}
}

View File

@ -2103,4 +2103,45 @@ impl<'a> AgentData<'a> {
// Always attempt to path towards target
self.path_toward_target(agent, controller, tgt_data, read_data, false, false, None);
}
pub fn handle_deadwood(
&self,
agent: &mut Agent,
controller: &mut Controller,
attack_data: &AttackData,
tgt_data: &TargetData,
read_data: &ReadData,
) {
const BEAM_RANGE: f32 = 20.0;
const BEAM_TIME: Duration = Duration::from_secs(3);
// action_state.condition controls whether or not deadwood should beam or dash
if matches!(self.char_state, CharacterState::DashMelee(s) if s.stage_section != StageSection::Recover)
{
// If already dashing, keep dashing and have move_dir set to forward
controller.push_basic_input(InputKind::Secondary);
controller.inputs.move_dir = self.ori.look_vec().xy();
} else if attack_data.in_min_range() && attack_data.angle < 10.0 {
// If near target, dash at them and through them to get away
controller.push_basic_input(InputKind::Secondary);
} else if matches!(self.char_state, CharacterState::BasicBeam(s) if s.stage_section != StageSection::Recover && s.timer < BEAM_TIME)
{
// If already beaming, keep beaming if not beaming for over 5 seconds
controller.push_basic_input(InputKind::Primary);
} else if attack_data.dist_sqrd < BEAM_RANGE.powi(2) {
// Else if in beam range, beam them
if attack_data.angle < 5.0 {
controller.push_basic_input(InputKind::Primary);
} else {
// If not in angle, apply slight movement so deadwood orients itself correctly
controller.inputs.move_dir = (tgt_data.pos.0 - self.pos.0)
.xy()
.try_normalized()
.unwrap_or_else(Vec2::zero)
* 0.01;
}
} else {
// Otherwise too far, move towards target
self.path_toward_target(agent, controller, tgt_data, read_data, false, false, None);
}
}
}

View File

@ -114,6 +114,7 @@ pub enum Tactic {
Yeti,
Harvester,
StoneGolem,
Deadwood,
}
#[derive(SystemData)]

View File

@ -285,7 +285,6 @@ impl Room {
if tile_pos == miniboss_spawn_tile && tile_wcenter.xy() == wpos2d {
let entities = match self.difficulty {
0 => mini_boss_0(dynamic_rng, tile_wcenter),
1 => mini_boss_1(dynamic_rng, tile_wcenter),
2 => mini_boss_2(dynamic_rng, tile_wcenter),
3 => mini_boss_3(dynamic_rng, tile_wcenter),
@ -319,7 +318,6 @@ impl Room {
if tile_pos == boss_spawn_tile && wpos2d == tile_wcenter.xy() {
let entities = match self.difficulty {
0 => boss_0(dynamic_rng, tile_wcenter),
1 => boss_1(dynamic_rng, tile_wcenter),
2 => boss_2(dynamic_rng, tile_wcenter),
3 => boss_3(dynamic_rng, tile_wcenter),
@ -772,13 +770,6 @@ fn turret_5(dynamic_rng: &mut impl Rng, pos: Vec3<f32>) -> EntityInfo {
EntityInfo::at(pos).with_asset_expect("common.entity.dungeon.tier-5.turret", dynamic_rng)
}
fn boss_0(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_asset_expect("common.entity.dungeon.tier-0.boss", dynamic_rng),
]
}
fn boss_1(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
@ -823,13 +814,6 @@ fn boss_fallback(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<Ent
]
}
fn mini_boss_0(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
vec![
EntityInfo::at(tile_wcenter.map(|e| e as f32))
.with_asset_expect("common.entity.dungeon.tier-0.miniboss", dynamic_rng),
]
}
fn mini_boss_1(dynamic_rng: &mut impl Rng, tile_wcenter: Vec3<i32>) -> Vec<EntityInfo> {
let mut entities = Vec::new();
entities.resize_with(8, || {
@ -1440,7 +1424,6 @@ mod tests {
fn test_creating_bosses() {
let mut dynamic_rng = rand::thread_rng();
let tile_wcenter = Vec3::new(0, 0, 0);
boss_0(&mut dynamic_rng, tile_wcenter);
boss_1(&mut dynamic_rng, tile_wcenter);
boss_2(&mut dynamic_rng, tile_wcenter);
boss_3(&mut dynamic_rng, tile_wcenter);
@ -1467,7 +1450,6 @@ mod tests {
fn test_creating_minibosses() {
let mut dynamic_rng = rand::thread_rng();
let tile_wcenter = Vec3::new(0, 0, 0);
mini_boss_0(&mut dynamic_rng, tile_wcenter);
mini_boss_1(&mut dynamic_rng, tile_wcenter);
mini_boss_2(&mut dynamic_rng, tile_wcenter);
mini_boss_3(&mut dynamic_rng, tile_wcenter);

View File

@ -2177,7 +2177,7 @@ fn gnarling_chieftain<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
fn deadwood<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
EntityInfo::at(pos.map(|x| x as f32))
.with_asset_expect("common.entity.dungeon.gnarling.deadwood", rng)
.with_asset_expect("common.entity.wild.aggressive.deadwood", rng)
}
fn mandragora<R: Rng>(pos: Vec3<i32>, rng: &mut R) -> EntityInfo {
@ -2304,3 +2304,22 @@ where
Some((branches, terminals))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_creating_entities() {
let pos = Vec3::zero();
gnarling_mugger(pos);
gnarling_stalker(pos);
gnarling_logger(pos);
gnarling_chieftain(pos);
deadwood(pos);
mandragora(pos);
wood_golem(pos);
harvester_boss(pos);
}
}