Wood golem attacks and ai

This commit is contained in:
Sam 2022-02-02 20:45:43 -05:00
parent e044bf5091
commit fcb0f8d8f0
28 changed files with 184 additions and 1 deletions

View File

@ -89,6 +89,13 @@
secondary: "common.abilities.custom.mandragora.scream", secondary: "common.abilities.custom.mandragora.scream",
abilities: [], abilities: [],
), ),
Custom("Wood Golem"): (
primary: "common.abilities.custom.woodgolem.strike",
secondary: "common.abilities.custom.woodgolem.spin",
abilities: [
(None, "common.abilities.custom.woodgolem.shockwave")
],
),
Custom("Sword Simple"): ( Custom("Sword Simple"): (
primary: "common.abilities.swordsimple.doublestrike", primary: "common.abilities.swordsimple.doublestrike",
secondary: "common.abilities.swordsimple.dash", secondary: "common.abilities.swordsimple.dash",

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 5.0, range: 5.0,
angle: 120.0, angle: 120.0,
), ),
ori_modifier: 1.0,
) )

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 4.0, range: 4.0,
angle: 45.0, angle: 45.0,
), ),
ori_modifier: 1.0,
) )

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 4.0, range: 4.0,
angle: 60.0, angle: 60.0,
), ),
ori_modifier: 1.0,
) )

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 3, range: 3,
angle: 30, angle: 30,
), ),
ori_modifier: 1.0,
) )

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 5.0, range: 5.0,
angle: 60.0, angle: 60.0,
), ),
ori_modifier: 1.0,
) )

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 0.8, range: 0.8,
angle: 50.0, angle: 50.0,
), ),
ori_modifier: 1.0,
) )

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 5.0, range: 5.0,
angle: 60.0, angle: 60.0,
), ),
ori_modifier: 1.0,
) )

View File

@ -0,0 +1,17 @@
Shockwave(
energy_cost: 0,
buildup_duration: 1.5,
swing_duration: 0.12,
recover_duration: 1.2,
damage: 20.0,
poise_damage: 30,
knockback: (strength: 30.0, direction: TowardsUp),
shockwave_angle: 90.0,
shockwave_vertical_angle: 90.0,
shockwave_speed: 15.0,
shockwave_duration: 2.0,
requires_ground: true,
move_efficiency: 0.0,
damage_kind: Crushing,
specifier: Ground,
)

View File

@ -0,0 +1,22 @@
SpinMelee(
buildup_duration: 0.1,
swing_duration: 0.3,
recover_duration: 0.1,
melee_constructor: (
kind: Bash(
damage: 15.0,
poise: 30.0,
knockback: 20.0,
energy_regen: 0.0,
),
range: 7.5,
angle: 360.0,
),
energy_cost: 0,
is_infinite: false,
movement_behavior: Stationary,
is_interruptible: false,
forward_speed: 0.0,
num_spins: 1,
specifier: None,
)

View File

@ -0,0 +1,17 @@
BasicMelee(
energy_cost: 0,
buildup_duration: 0.8,
swing_duration: 0.1,
recover_duration: 0.5,
melee_constructor: (
kind: Bash(
damage: 10.0,
poise: 25.0,
knockback: 15.0,
energy_regen: 0.0,
),
range: 4.0,
angle: 45.0,
),
ori_modifier: 0.4,
)

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 4.0, range: 4.0,
angle: 20.0, angle: 20.0,
), ),
ori_modifier: 1.0,
) )

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 3.5, range: 3.5,
angle: 20.0, angle: 20.0,
), ),
ori_modifier: 1.0,
) )

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 3.5, range: 3.5,
angle: 15.0, angle: 15.0,
), ),
ori_modifier: 1.0,
) )

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 3.5, range: 3.5,
angle: 20.0, angle: 20.0,
), ),
ori_modifier: 1.0,
) )

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 3, range: 3,
angle: 30, angle: 30,
), ),
ori_modifier: 1.0,
) )

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 2, range: 2,
angle: 15, angle: 15,
), ),
ori_modifier: 1.0,
) )

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 4.5, range: 4.5,
angle: 20.0, angle: 20.0,
), ),
ori_modifier: 1.0,
) )

View File

@ -13,4 +13,5 @@ BasicMelee(
range: 3.0, range: 3.0,
angle: 90.0, angle: 90.0,
), ),
ori_modifier: 1.0,
) )

View File

@ -0,0 +1,13 @@
ItemDef(
name: "Wood Golem Armor",
description: "Yeet",
kind: Armor((
kind: Chest("Wood Golem"),
stats: (
protection: Some(Normal(60.0)),
poise_resilience: Some(Normal(60.0)),
),
)),
quality: Common,
tags: [],
)

View File

@ -0,0 +1,21 @@
ItemDef(
name: "Wood Golem Fists",
description: "Yeet",
kind: Tool((
kind: Natural,
hands: Two,
stats: Direct((
equip_time_secs: 0.001,
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("Wood Golem")),
)

View File

@ -394,6 +394,7 @@ pub enum CharacterAbility {
swing_duration: f32, swing_duration: f32,
recover_duration: f32, recover_duration: f32,
melee_constructor: MeleeConstructor, melee_constructor: MeleeConstructor,
ori_modifier: f32,
}, },
BasicRanged { BasicRanged {
energy_cost: f32, energy_cost: f32,
@ -610,6 +611,7 @@ impl Default for CharacterAbility {
angle: 15.0, angle: 15.0,
damage_effect: None, damage_effect: None,
}, },
ori_modifier: 1.0,
} }
} }
} }
@ -697,6 +699,7 @@ impl CharacterAbility {
ref mut swing_duration, ref mut swing_duration,
ref mut recover_duration, ref mut recover_duration,
ref mut melee_constructor, ref mut melee_constructor,
ori_modifier: _,
} => { } => {
*buildup_duration /= stats.speed; *buildup_duration /= stats.speed;
*swing_duration /= stats.speed; *swing_duration /= stats.speed;
@ -1696,6 +1699,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
swing_duration, swing_duration,
recover_duration, recover_duration,
melee_constructor, melee_constructor,
ori_modifier,
energy_cost: _, energy_cost: _,
} => CharacterState::BasicMelee(basic_melee::Data { } => CharacterState::BasicMelee(basic_melee::Data {
static_data: basic_melee::StaticData { static_data: basic_melee::StaticData {
@ -1703,6 +1707,7 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
swing_duration: Duration::from_secs_f32(*swing_duration), swing_duration: Duration::from_secs_f32(*swing_duration),
recover_duration: Duration::from_secs_f32(*recover_duration), recover_duration: Duration::from_secs_f32(*recover_duration),
melee_constructor: *melee_constructor, melee_constructor: *melee_constructor,
ori_modifier: *ori_modifier,
ability_info, ability_info,
}, },
timer: Duration::default(), timer: Duration::default(),

View File

@ -180,6 +180,9 @@ fn default_main_tool(body: &Body) -> Item {
golem::Species::ClayGolem => Some(Item::new_from_asset_expect( golem::Species::ClayGolem => Some(Item::new_from_asset_expect(
"common.items.npc_weapons.unique.clay_golem_fist", "common.items.npc_weapons.unique.clay_golem_fist",
)), )),
golem::Species::WoodGolem => Some(Item::new_from_asset_expect(
"common.items.npc_weapons.unique.wood_golem_fist",
)),
_ => None, _ => None,
}, },
Body::QuadrupedMedium(quadruped_medium) => match quadruped_medium.species { Body::QuadrupedMedium(quadruped_medium) => match quadruped_medium.species {
@ -465,6 +468,7 @@ impl LoadoutBuilder {
}, },
Body::Golem(body) => match body.species { Body::Golem(body) => match body.species {
golem::Species::ClayGolem => Some("common.items.npc_armor.golem.claygolem"), golem::Species::ClayGolem => Some("common.items.npc_armor.golem.claygolem"),
golem::Species::WoodGolem => Some("common.items.npc_armor.golem.woodgolem"),
_ => None, _ => None,
}, },
Body::QuadrupedLow(body) => match body.species { Body::QuadrupedLow(body) => match body.species {

View File

@ -23,6 +23,8 @@ pub struct StaticData {
pub recover_duration: Duration, pub recover_duration: Duration,
/// Used to construct the Melee attack /// Used to construct the Melee attack
pub melee_constructor: MeleeConstructor, pub melee_constructor: MeleeConstructor,
/// Adjusts turning rate during the attack
pub ori_modifier: f32,
/// What key is used to press ability /// What key is used to press ability
pub ability_info: AbilityInfo, pub ability_info: AbilityInfo,
} }
@ -44,7 +46,7 @@ impl CharacterBehavior for Data {
fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate { fn behavior(&self, data: &JoinData, output_events: &mut OutputEvents) -> StateUpdate {
let mut update = StateUpdate::from(data); let mut update = StateUpdate::from(data);
handle_orientation(data, &mut update, 1.0, None); handle_orientation(data, &mut update, self.static_data.ori_modifier, None);
handle_move(data, &mut update, 0.7); handle_move(data, &mut update, 0.7);
handle_jump(data, output_events, &mut update, 1.0); handle_jump(data, output_events, &mut update, 1.0);

View File

@ -1749,6 +1749,7 @@ impl<'a> AgentData<'a> {
"Gnarling Blowgun" => Tactic::ElevatedRanged, "Gnarling Blowgun" => Tactic::ElevatedRanged,
"Deadwood" => Tactic::Deadwood, "Deadwood" => Tactic::Deadwood,
"Mandragora" => Tactic::Mandragora, "Mandragora" => Tactic::Mandragora,
"Wood Golem" => Tactic::WoodGolem,
_ => Tactic::SimpleMelee, _ => Tactic::SimpleMelee,
}, },
AbilitySpec::Tool(tool_kind) => tool_tactic(*tool_kind), AbilitySpec::Tool(tool_kind) => tool_tactic(*tool_kind),
@ -2132,6 +2133,9 @@ impl<'a> AgentData<'a> {
Tactic::Mandragora => { Tactic::Mandragora => {
self.handle_mandragora(agent, controller, &attack_data, tgt_data, read_data) self.handle_mandragora(agent, controller, &attack_data, tgt_data, read_data)
}, },
Tactic::WoodGolem => {
self.handle_wood_golem(agent, controller, &attack_data, tgt_data, read_data)
},
} }
} }

View File

@ -2192,4 +2192,58 @@ impl<'a> AgentData<'a> {
} }
} }
} }
pub fn handle_wood_golem(
&self,
agent: &mut Agent,
controller: &mut Controller,
attack_data: &AttackData,
tgt_data: &TargetData,
read_data: &ReadData,
) {
const SHOCKWAVE_RANGE: f32 = 25.0;
const SHOCKWAVE_WAIT_TIME: f32 = 7.5;
const SPIN_WAIT_TIME: f32 = 3.0;
// After spinning, reset timer
if matches!(self.char_state, CharacterState::SpinMelee(s) if s.stage_section == StageSection::Recover)
{
agent.action_state.timer = 0.0;
}
if attack_data.in_min_range() {
// If in minimum range
if agent.action_state.timer > SPIN_WAIT_TIME {
// If it's been too long since able to hit target, spin
controller.push_basic_input(InputKind::Secondary);
} else if attack_data.angle < 30.0 {
// Else if in angle to strike, strike
controller.push_basic_input(InputKind::Primary);
} else {
// Else increment spin timer
agent.action_state.timer += read_data.dt.0;
// If not in angle, apply slight movement so golem 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 {
// Else if too far for melee
if attack_data.dist_sqrd < SHOCKWAVE_RANGE.powi(2) && attack_data.angle < 45.0 {
// Shockwave if close enough and haven't shockwaved too recently
if agent.action_state.counter > SHOCKWAVE_WAIT_TIME {
controller.push_basic_input(InputKind::Ability(0));
}
if matches!(self.char_state, CharacterState::Shockwave(_)) {
agent.action_state.counter = 0.0;
} else {
agent.action_state.counter += read_data.dt.0;
}
}
// And always try to path towards target
self.path_toward_target(agent, controller, tgt_data, read_data, false, false, None);
}
}
} }

View File

@ -116,6 +116,7 @@ pub enum Tactic {
StoneGolem, StoneGolem,
Deadwood, Deadwood,
Mandragora, Mandragora,
WoodGolem,
} }
#[derive(SystemData)] #[derive(SystemData)]

View File

@ -87,6 +87,7 @@ fn maps_basic_melee() {
angle: 15.0, angle: 15.0,
damage_effect: None, damage_effect: None,
}, },
ori_modifier: 1.0,
ability_info: empty_ability_info(), ability_info: empty_ability_info(),
}, },
timer: Duration::default(), timer: Duration::default(),