mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Deadwood ai
This commit is contained in:
parent
cb48dd0a75
commit
f1801560fa
@ -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",
|
||||
|
28
assets/common/abilities/custom/deadwood/dash.ron
Normal file
28
assets/common/abilities/custom/deadwood/dash.ron
Normal 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,
|
||||
)
|
14
assets/common/abilities/custom/deadwood/lifestealbeam.ron
Normal file
14
assets/common/abilities/custom/deadwood/lifestealbeam.ron
Normal 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,
|
||||
)
|
@ -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,
|
||||
),
|
||||
)
|
||||
|
@ -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,
|
||||
),
|
||||
)
|
||||
|
@ -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: [],
|
||||
)
|
@ -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: [],
|
||||
)
|
||||
|
@ -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: [],
|
||||
)
|
||||
|
21
assets/common/items/npc_weapons/unique/deadwood.ron
Normal file
21
assets/common/items/npc_weapons/unique/deadwood.ron
Normal 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")),
|
||||
)
|
@ -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;
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,6 +114,7 @@ pub enum Tactic {
|
||||
Yeti,
|
||||
Harvester,
|
||||
StoneGolem,
|
||||
Deadwood,
|
||||
}
|
||||
|
||||
#[derive(SystemData)]
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user