Cleaving stance AI

This commit is contained in:
Sam 2022-10-09 03:17:29 -04:00
parent 5358016ba0
commit df9ef691fd
37 changed files with 203 additions and 90 deletions

View File

@ -13,7 +13,7 @@ LeapMelee(
), ),
range: 4.5, range: 4.5,
angle: 30.0, angle: 30.0,
multi_target: true, multi_target: Some(Normal),
), ),
forward_leap_strength: 20.0, forward_leap_strength: 20.0,
vertical_leap_strength: 8.0, vertical_leap_strength: 8.0,

View File

@ -11,7 +11,7 @@ SpinMelee(
), ),
range: 3.5, range: 3.5,
angle: 360.0, angle: 360.0,
multi_target: true, multi_target: Some(Normal),
), ),
energy_cost: 10.0, energy_cost: 10.0,
is_infinite: true, is_infinite: true,

View File

@ -13,7 +13,7 @@ LeapMelee(
), ),
range: 4.5, range: 4.5,
angle: 180.0, angle: 180.0,
multi_target: true, multi_target: Some(Normal),
), ),
forward_leap_strength: 40.0, forward_leap_strength: 40.0,
vertical_leap_strength: 7.5, vertical_leap_strength: 7.5,

View File

@ -12,7 +12,7 @@ BasicMelee(
), ),
range: 4.0, range: 4.0,
angle: 45.0, angle: 45.0,
multi_target: true, multi_target: Some(Normal),
), ),
ori_modifier: 1.0, ori_modifier: 1.0,
) )

View File

@ -12,7 +12,7 @@ BasicMelee(
), ),
range: 4.0, range: 4.0,
angle: 60.0, angle: 60.0,
multi_target: true, multi_target: Some(Normal),
), ),
ori_modifier: 1.0, ori_modifier: 1.0,
) )

View File

@ -10,7 +10,7 @@ SpinMelee(
), ),
range: 16.0, range: 16.0,
angle: 360.0, angle: 360.0,
multi_target: true, multi_target: Some(Normal),
), ),
energy_cost: 0.0, energy_cost: 0.0,
is_infinite: true, is_infinite: true,

View File

@ -21,7 +21,7 @@ DashMelee(
strength: DamageFraction(0.3), strength: DamageFraction(0.3),
chance: 0.25, chance: 0.25,
))), ))),
multi_target: true, multi_target: Some(Normal),
), ),
energy_drain: 0, energy_drain: 0,
forward_speed: 5.0, forward_speed: 5.0,

View File

@ -16,7 +16,7 @@ ChargedMelee(
)), )),
range: 5.0, range: 5.0,
angle: 45.0, angle: 45.0,
multi_target: true, multi_target: Some(Normal),
), ),
charge_duration: 4.5, charge_duration: 4.5,
swing_duration: 0.1, swing_duration: 0.1,

View File

@ -18,7 +18,7 @@ BasicMelee(
strength: Value(0.5), strength: Value(0.5),
chance: 1.0, chance: 1.0,
))), ))),
multi_target: true, multi_target: Some(Normal),
), ),
ori_modifier: 1.0, ori_modifier: 1.0,
) )

View File

@ -16,7 +16,7 @@ ChargedMelee(
)), )),
range: 6.0, range: 6.0,
angle: 90.0, angle: 90.0,
multi_target: true, multi_target: Some(Normal),
), ),
charge_duration: 3.2, charge_duration: 3.2,
swing_duration: 0.7, swing_duration: 0.7,

View File

@ -13,7 +13,7 @@ LeapMelee(
), ),
range: 6.75, range: 6.75,
angle: 180.0, angle: 180.0,
multi_target: true, multi_target: Some(Normal),
), ),
forward_leap_strength: 45.0, forward_leap_strength: 45.0,
vertical_leap_strength: 10.0, vertical_leap_strength: 10.0,

View File

@ -13,7 +13,7 @@ LeapMelee(
), ),
range: 4.5, range: 4.5,
angle: 180.0, angle: 180.0,
multi_target: true, multi_target: Some(Normal),
), ),
forward_leap_strength: 20.0, forward_leap_strength: 20.0,
vertical_leap_strength: 5.0, vertical_leap_strength: 5.0,

View File

@ -11,7 +11,7 @@ SpinMelee(
), ),
range: 7.5, range: 7.5,
angle: 360.0, angle: 360.0,
multi_target: true, multi_target: Some(Normal),
), ),
energy_cost: 0, energy_cost: 0,
is_infinite: false, is_infinite: false,

View File

@ -12,7 +12,7 @@ BasicMelee(
), ),
range: 5.0, range: 5.0,
angle: 60.0, angle: 60.0,
multi_target: true, multi_target: Some(Normal),
), ),
ori_modifier: 1.0, ori_modifier: 1.0,
) )

View File

@ -15,7 +15,7 @@ DashMelee(
)), )),
range: 5.0, range: 5.0,
angle: 90.0, angle: 90.0,
multi_target: true, multi_target: Some(Normal),
), ),
energy_drain: 0, energy_drain: 0,
forward_speed: 10.0, forward_speed: 10.0,

View File

@ -11,7 +11,7 @@ SpinMelee(
), ),
range: 3.5, range: 3.5,
angle: 360.0, angle: 360.0,
multi_target: true, multi_target: Some(Normal),
), ),
energy_cost: 0, energy_cost: 0,
is_infinite: true, is_infinite: true,

View File

@ -12,7 +12,7 @@ BasicMelee(
), ),
range: 4.0, range: 4.0,
angle: 20.0, angle: 20.0,
multi_target: true, multi_target: Some(Normal),
), ),
ori_modifier: 1.0, ori_modifier: 1.0,
) )

View File

@ -16,7 +16,7 @@ ChargedMelee(
)), )),
range: 3.5, range: 3.5,
angle: 30.0, angle: 30.0,
multi_target: true, multi_target: Some(Normal),
), ),
charge_duration: 1.0, charge_duration: 1.0,
swing_duration: 0.12, swing_duration: 0.12,

View File

@ -13,7 +13,7 @@ LeapMelee(
), ),
range: 4.5, range: 4.5,
angle: 360.0, angle: 360.0,
multi_target: true, multi_target: Some(Normal),
), ),
forward_leap_strength: 20.0, forward_leap_strength: 20.0,
vertical_leap_strength: 8.0, vertical_leap_strength: 8.0,

View File

@ -6,11 +6,11 @@ ComboMelee2(
damage: 6, damage: 6,
poise: 0, poise: 0,
knockback: 0, knockback: 0,
energy_regen: 3, energy_regen: 7,
), ),
range: 3.0, range: 3.0,
angle: 45.0, angle: 45.0,
multi_target: true, multi_target: Some(Normal),
), ),
buildup_duration: 0.3, buildup_duration: 0.3,
swing_duration: 0.1, swing_duration: 0.1,
@ -29,11 +29,11 @@ ComboMelee2(
damage: 8, damage: 8,
poise: 0, poise: 0,
knockback: 0, knockback: 0,
energy_regen: 5, energy_regen: 8,
), ),
range: 3.0, range: 3.0,
angle: 45.0, angle: 45.0,
multi_target: true, multi_target: Some(Normal),
), ),
buildup_duration: 0.3, buildup_duration: 0.3,
swing_duration: 0.15, swing_duration: 0.15,

View File

@ -1,6 +1,6 @@
DiveMelee( DiveMelee(
energy_cost: 20, energy_cost: 20,
vertical_speed: 15, vertical_speed: 10,
movement_duration: 5, movement_duration: 5,
swing_duration: 0.1, swing_duration: 0.1,
recover_duration: 0.3, recover_duration: 0.3,
@ -19,7 +19,7 @@ DiveMelee(
)), )),
range: 6.0, range: 6.0,
angle: 15.0, angle: 15.0,
multi_target: true, multi_target: Some(Normal),
), ),
meta: ( meta: (
kind: Some(Sword(Cleaving)), kind: Some(Sword(Cleaving)),

View File

@ -12,7 +12,7 @@ FinisherMelee(
), ),
range: 3.0, range: 3.0,
angle: 15.0, angle: 15.0,
damage_effect: Some(ResetMelee), multi_target: Some(Scaling(0.5)),
), ),
scaling: Some(( scaling: Some((
target: Buff, target: Buff,

View File

@ -10,7 +10,7 @@ ComboMelee2(
), ),
range: 6.0, range: 6.0,
angle: 360.0, angle: 360.0,
multi_target: true, multi_target: Some(Normal),
), ),
buildup_duration: 0.1, buildup_duration: 0.1,
swing_duration: 0.3, swing_duration: 0.3,

View File

@ -10,7 +10,7 @@ ComboMelee2(
), ),
range: 8.0, range: 8.0,
angle: 10.0, angle: 10.0,
multi_target: true, multi_target: Some(Normal),
), ),
buildup_duration: 0.3, buildup_duration: 0.3,
swing_duration: 0.1, swing_duration: 0.1,

View File

@ -430,18 +430,6 @@ impl Attack {
}); });
} }
}, },
CombatEffect::ResetMelee => {
if let Some(attacker_entity) = attacker.map(|a| a.entity) {
if target
.health
.map_or(false, |h| accumulated_damage > h.current())
{
emit(ServerEvent::ResetMelee {
entity: attacker_entity,
});
}
}
},
CombatEffect::BuildupsVulnerable => { CombatEffect::BuildupsVulnerable => {
if target.char_state.map_or(false, |cs| { if target.char_state.map_or(false, |cs| {
matches!(cs.stage_section(), Some(StageSection::Buildup)) matches!(cs.stage_section(), Some(StageSection::Buildup))
@ -604,18 +592,6 @@ impl Attack {
}); });
} }
}, },
CombatEffect::ResetMelee => {
if let Some(attacker_entity) = attacker.map(|a| a.entity) {
if target
.health
.map_or(false, |h| accumulated_damage > h.current())
{
emit(ServerEvent::ResetMelee {
entity: attacker_entity,
});
}
}
},
// Only has an effect when attached to a damage // Only has an effect when attached to a damage
CombatEffect::BuildupsVulnerable => {}, CombatEffect::BuildupsVulnerable => {},
} }
@ -749,8 +725,6 @@ pub enum CombatEffect {
Lifesteal(f32), Lifesteal(f32),
Poise(f32), Poise(f32),
Combo(i32), Combo(i32),
// If the attack kills the target, reset the melee attack
ResetMelee,
// If the attack hits the target while they are in the buildup portion of a character state, // If the attack hits the target while they are in the buildup portion of a character state,
// deal double damage Only has an effect when attached to a damage, otherwise does nothing // deal double damage Only has an effect when attached to a damage, otherwise does nothing
// if only attached to the attack TODO: Maybe try to make it do something if tied to // if only attached to the attack TODO: Maybe try to make it do something if tied to

View File

@ -732,7 +732,7 @@ impl Default for CharacterAbility {
scaled: None, scaled: None,
range: 3.5, range: 3.5,
angle: 15.0, angle: 15.0,
multi_target: false, multi_target: None,
damage_effect: None, damage_effect: None,
}, },
ori_modifier: 1.0, ori_modifier: 1.0,

View File

@ -1,6 +1,6 @@
use crate::DamageSource;
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
use crate::{comp, consts::HP_PER_LEVEL}; use crate::{comp, consts::HP_PER_LEVEL};
use crate::{uid::Uid, DamageSource};
use hashbrown::HashMap; use hashbrown::HashMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::convert::TryFrom; use std::convert::TryFrom;
@ -193,6 +193,12 @@ impl Health {
.map(|(damage_contrib, (damage, _))| (damage_contrib, damage)) .map(|(damage_contrib, (damage, _))| (damage_contrib, damage))
} }
pub fn recent_damagers(&self) -> impl Iterator<Item = (Uid, Time)> + '_ {
self.damage_contributors
.iter()
.map(|(contrib, (_, time))| (contrib.uid(), *time))
}
pub fn should_die(&self) -> bool { self.current == 0 } pub fn should_die(&self) -> bool { self.current == 0 }
pub fn kill(&mut self) { self.current = 0; } pub fn kill(&mut self) { self.current = 0; }

View File

@ -20,10 +20,16 @@ pub struct Melee {
pub max_angle: f32, pub max_angle: f32,
pub applied: bool, pub applied: bool,
pub hit_count: u32, pub hit_count: u32,
pub multi_target: bool, pub multi_target: Option<MultiTarget>,
pub break_block: Option<(Vec3<i32>, Option<ToolKind>)>, pub break_block: Option<(Vec3<i32>, Option<ToolKind>)>,
} }
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum MultiTarget {
Normal,
Scaling(f32),
}
impl Melee { impl Melee {
#[must_use] #[must_use]
pub fn with_block_breaking( pub fn with_block_breaking(
@ -47,8 +53,7 @@ pub struct MeleeConstructor {
pub scaled: Option<MeleeConstructorKind>, pub scaled: Option<MeleeConstructorKind>,
pub range: f32, pub range: f32,
pub angle: f32, pub angle: f32,
#[serde(default)] pub multi_target: Option<MultiTarget>,
pub multi_target: bool,
pub damage_effect: Option<CombatEffect>, pub damage_effect: Option<CombatEffect>,
} }

View File

@ -226,9 +226,6 @@ pub enum ServerEvent {
entity: EcsEntity, entity: EcsEntity,
update: comp::MapMarkerChange, update: comp::MapMarkerChange,
}, },
ResetMelee {
entity: EcsEntity,
},
} }
pub struct EventBus<E> { pub struct EventBus<E> {

View File

@ -2,7 +2,7 @@ use crate::{
combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement}, combat::{Attack, AttackDamage, AttackEffect, CombatBuff, CombatEffect, CombatRequirement},
comp::{ comp::{
character_state::OutputEvents, character_state::OutputEvents,
tool::{Stats, ToolKind}, tool::{Stats, ToolKind}, melee::MultiTarget,
CharacterState, Melee, StateUpdate, CharacterState, Melee, StateUpdate,
}, },
states::{ states::{
@ -279,7 +279,7 @@ impl CharacterBehavior for Data {
hit_count: 0, hit_count: 0,
// TODO: Evaluate if we want to leave this true. State will be removed at // TODO: Evaluate if we want to leave this true. State will be removed at
// some point anyways and this does preserve behavior // some point anyways and this does preserve behavior
multi_target: true, multi_target: Some(MultiTarget::Normal),
break_block: data break_block: data
.inputs .inputs
.break_block_pos .break_block_pos

View File

@ -278,7 +278,7 @@ fn create_test_melee(static_data: StaticData) -> Melee {
scaled: None, scaled: None,
range: static_data.melee_constructor.range, range: static_data.melee_constructor.range,
angle: static_data.melee_constructor.angle, angle: static_data.melee_constructor.angle,
multi_target: false, multi_target: None,
damage_effect: None, damage_effect: None,
}; };
melee.create_melee((0.0, 0.0), 0.0) melee.create_melee((0.0, 0.0), 0.0)

View File

@ -74,6 +74,8 @@ impl CharacterBehavior for Data {
let crit_data = get_crit_data(data, self.static_data.ability_info); let crit_data = get_crit_data(data, self.static_data.ability_info);
let buff_strength = get_buff_strength(data, self.static_data.ability_info); let buff_strength = get_buff_strength(data, self.static_data.ability_info);
let scaling = self.max_vertical_speed / self.static_data.vertical_speed; let scaling = self.max_vertical_speed / self.static_data.vertical_speed;
// TODO: Remove when server authoritative physics
let scaling = scaling.max(2.0);
data.updater.insert( data.updater.insert(
data.entity, data.entity,

View File

@ -2,6 +2,7 @@ use common::{
combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo}, combat::{self, AttackOptions, AttackSource, AttackerInfo, TargetInfo},
comp::{ comp::{
agent::{Sound, SoundKind}, agent::{Sound, SoundKind},
melee::MultiTarget,
Alignment, Body, CharacterState, Combo, Energy, Group, Health, Inventory, Melee, Ori, Alignment, Body, CharacterState, Combo, Energy, Group, Health, Inventory, Melee, Ori,
Player, Pos, Scale, Stats, Player, Pos, Scale, Stats,
}, },
@ -116,7 +117,7 @@ impl<'a> System<'a> for Sys {
{ {
// Unless the melee attack can hit multiple targets, stop the attack if it has // Unless the melee attack can hit multiple targets, stop the attack if it has
// already hit 1 target // already hit 1 target
if !melee_attack.multi_target && melee_attack.hit_count > 0 { if melee_attack.multi_target.is_none() && melee_attack.hit_count > 0 {
break; break;
} }
@ -197,12 +198,19 @@ impl<'a> System<'a> for Sys {
target_group, target_group,
}; };
let strength =
if let Some(MultiTarget::Scaling(scaling)) = melee_attack.multi_target {
1.0 + melee_attack.hit_count as f32 * scaling
} else {
1.0
};
let is_applied = melee_attack.attack.apply_attack( let is_applied = melee_attack.attack.apply_attack(
attacker_info, attacker_info,
target_info, target_info,
dir, dir,
attack_options, attack_options,
1.0, strength,
AttackSource::Melee, AttackSource::Melee,
*read_data.time, *read_data.time,
|e| server_emitter.emit(e), |e| server_emitter.emit(e),

View File

@ -18,6 +18,7 @@ use common::{
vol::ReadVol, vol::ReadVol,
}; };
use rand::Rng; use rand::Rng;
use specs::saveload::MarkerAllocator;
use std::{f32::consts::PI, time::Duration}; use std::{f32::consts::PI, time::Duration};
use vek::*; use vek::*;
@ -474,16 +475,31 @@ impl<'a> AgentData<'a> {
.map_or(false, |buffs| !buffs.contains(self.buff)) .map_or(false, |buffs| !buffs.contains(self.buff))
} }
} }
struct DiveMeleeData {
range: f32,
angle: f32,
energy: f32,
}
impl DiveMeleeData {
fn npc_should_use_hack(&self, agent_data: &AgentData, tgt_data: &TargetData) -> bool {
let dist_sqrd_2d = agent_data.pos.0.xy().distance_squared(tgt_data.pos.0.xy());
agent_data.energy.current() > self.energy
&& agent_data.physics_state.on_ground.is_some()
&& agent_data.pos.0.z >= tgt_data.pos.0.z
&& dist_sqrd_2d > (self.range / 2.0).powi(2)
&& dist_sqrd_2d < (self.range + 5.0).powi(2)
}
}
use ability::SwordStance; use ability::SwordStance;
let stance = |stance| match stance { let stance = |stance| match stance {
1 => SwordStance::Offensive, 1 => SwordStance::Offensive,
2 => SwordStance::Defensive, 2 => SwordStance::Defensive,
3 => SwordStance::Mobility, 3 => SwordStance::Mobility,
4 => SwordStance::Crippling, 4 => SwordStance::Crippling,
5 => SwordStance::Cleaving, 5 => SwordStance::Parrying,
6 => SwordStance::Parrying, 6 => SwordStance::Heavy,
7 => SwordStance::Heavy, 7 => SwordStance::Reaching,
8 => SwordStance::Reaching, 8 => SwordStance::Cleaving,
_ => SwordStance::Balanced, _ => SwordStance::Balanced,
}; };
if !agent.action_state.initialized { if !agent.action_state.initialized {
@ -495,8 +511,12 @@ impl<'a> AgentData<'a> {
.skill_set .skill_set
.has_skill(Skill::Sword(SwordSkill::CripplingFinisher)) .has_skill(Skill::Sword(SwordSkill::CripplingFinisher))
{ {
// Hack to make cleaving stance come up less often because agents cannot use it
// effectively due to only considering a single target
// Remove when agents properly consider multiple targets
// 4 + rng.gen_range(0..13) / 3
// rng.gen_range(4..9) // rng.gen_range(4..9)
4 5
} else if self } else if self
.skill_set .skill_set
.has_skill(Skill::Sword(SwordSkill::OffensiveFinisher)) .has_skill(Skill::Sword(SwordSkill::OffensiveFinisher))
@ -569,8 +589,8 @@ impl<'a> AgentData<'a> {
set_sword_ability(2, 10); set_sword_ability(2, 10);
// Cleaving dive // Cleaving dive
set_sword_ability(3, 11); set_sword_ability(3, 11);
// Offensive finisher // Offensive advance
set_sword_ability(4, 2); set_sword_ability(4, 3);
}, },
SwordStance::Parrying => { SwordStance::Parrying => {
// Parrying combo // Parrying combo
@ -1021,8 +1041,6 @@ impl<'a> AgentData<'a> {
if self.energy.current() < DESIRED_ENERGY { if self.energy.current() < DESIRED_ENERGY {
fallback_tactics(agent, controller); fallback_tactics(agent, controller);
} else if !in_stance(SwordStance::Crippling) { } else if !in_stance(SwordStance::Crippling) {
// controller.push_basic_input(InputKind::Jump);
// agent.action_state.initialized = false;
controller.push_basic_input(InputKind::Ability(0)); controller.push_basic_input(InputKind::Ability(0));
} else if CRIPPLING_FINISHER.could_use(attack_data, self) } else if CRIPPLING_FINISHER.could_use(attack_data, self)
&& CRIPPLING_FINISHER.use_desirable(tgt_data, self) && CRIPPLING_FINISHER.use_desirable(tgt_data, self)
@ -1080,7 +1098,121 @@ impl<'a> AgentData<'a> {
} }
}, },
SwordStance::Cleaving => { SwordStance::Cleaving => {
fallback_tactics(agent, controller); // TODO: Rewrite cleaving stance tactics when agents can consider multiple
// targets at once. Remove hack to make cleaving AI appear less frequently above
// when doing so.
const CLEAVING_COMBO: ComboMeleeData = ComboMeleeData {
min_range: 0.0,
max_range: 2.5,
angle: 35.0,
energy: 10.0,
};
const CLEAVING_FINISHER: FinisherMeleeData = FinisherMeleeData {
range: 2.0,
angle: 10.0,
energy: 40.0,
combo: 10,
};
const CLEAVING_SPIN: ComboMeleeData = ComboMeleeData {
min_range: 0.0,
max_range: 5.0,
angle: 360.0,
energy: 15.0,
};
const CLEAVING_DIVE: DiveMeleeData = DiveMeleeData {
range: 5.0,
angle: 10.0,
energy: 20.0,
};
const DESIRED_ENERGY: f32 = 50.0;
// TODO: Remove when agents actually have multiple targets
// Hacky check for multiple nearby melee range targets
let are_nearby_targets = || {
if let Some(health) = self.health {
health
.recent_damagers()
.filter(|(_, time)| read_data.time.0 - time.0 < 5.0)
.filter_map(|(uid, _)| {
read_data.uid_allocator.retrieve_entity_internal(uid.0)
})
.filter(|e| {
read_data.positions.get(*e).map_or(false, |pos| {
pos.0.distance_squared(self.pos.0) < 10_f32.powi(2)
})
})
.count()
> 1
} else {
false
}
};
if matches!(self.char_state, CharacterState::Roll(_)) {
agent.action_state.condition = true;
}
if agent.action_state.condition {
if self.physics_state.on_ground.is_some() {
controller.push_basic_input(InputKind::Jump);
} else {
controller.push_basic_input(InputKind::Ability(3));
}
agent.action_state.timer += read_data.dt.0;
if agent.action_state.timer > 2.0 {
agent.action_state.timer = 0.0;
agent.action_state.condition = false;
}
advance(agent, controller, CLEAVING_DIVE.range, CLEAVING_DIVE.angle);
} else if self.energy.current() < DESIRED_ENERGY {
fallback_tactics(agent, controller);
} else if !in_stance(SwordStance::Cleaving) {
controller.push_basic_input(InputKind::Ability(0));
} else if CLEAVING_FINISHER.could_use(attack_data, self)
&& CLEAVING_FINISHER.use_desirable(tgt_data, self)
{
controller.push_basic_input(InputKind::Ability(1));
advance(
agent,
controller,
CLEAVING_FINISHER.range,
CLEAVING_FINISHER.angle,
);
} else if CLEAVING_SPIN.could_use(attack_data, self) && are_nearby_targets() {
controller.push_basic_input(InputKind::Ability(2));
advance(
agent,
controller,
CLEAVING_SPIN.max_range,
CLEAVING_SPIN.angle,
);
} else if CLEAVING_DIVE.npc_should_use_hack(self, tgt_data) {
controller.push_basic_input(InputKind::Roll);
advance(agent, controller, CLEAVING_DIVE.range, CLEAVING_DIVE.angle);
} else if CLEAVING_COMBO.could_use(attack_data, self) {
controller.push_basic_input(InputKind::Primary);
advance(
agent,
controller,
CLEAVING_COMBO.max_range,
CLEAVING_COMBO.angle,
);
} else if OFFENSIVE_ADVANCE.could_use(attack_data, self) {
controller.push_basic_input(InputKind::Ability(4));
advance(
agent,
controller,
OFFENSIVE_ADVANCE.max_range,
OFFENSIVE_ADVANCE.angle,
);
} else {
advance(
agent,
controller,
CLEAVING_COMBO.max_range,
CLEAVING_COMBO.angle,
);
}
}, },
SwordStance::Parrying => { SwordStance::Parrying => {
fallback_tactics(agent, controller); fallback_tactics(agent, controller);

View File

@ -1417,12 +1417,3 @@ pub fn handle_update_map_marker(
} }
} }
} }
pub fn handle_reset_melee(server: &Server, entity: EcsEntity) {
let ecs = &server.state.ecs();
if let Some(mut melee) = ecs.write_storage::<comp::Melee>().get_mut(entity) {
melee.applied = false;
melee.hit_count = 0;
}
}

View File

@ -13,8 +13,7 @@ use entity_manipulation::{
handle_aura, handle_bonk, handle_buff, handle_change_ability, handle_combo_change, handle_aura, handle_bonk, handle_buff, handle_change_ability, handle_combo_change,
handle_delete, handle_destroy, handle_energy_change, handle_entity_attacked_hook, handle_delete, handle_destroy, handle_energy_change, handle_entity_attacked_hook,
handle_explosion, handle_health_change, handle_knockback, handle_land_on_ground, handle_explosion, handle_health_change, handle_knockback, handle_land_on_ground,
handle_parry_hook, handle_poise, handle_reset_melee, handle_respawn, handle_teleport_to, handle_parry_hook, handle_poise, handle_respawn, handle_teleport_to, handle_update_map_marker,
handle_update_map_marker,
}; };
use group_manip::handle_group; use group_manip::handle_group;
use information::handle_site_info; use information::handle_site_info;
@ -287,7 +286,6 @@ impl Server {
ServerEvent::UpdateMapMarker { entity, update } => { ServerEvent::UpdateMapMarker { entity, update } => {
handle_update_map_marker(self, entity, update) handle_update_map_marker(self, entity, update)
}, },
ServerEvent::ResetMelee { entity } => handle_reset_melee(self, entity),
} }
} }

View File

@ -86,7 +86,7 @@ fn maps_basic_melee() {
range: 3.5, range: 3.5,
angle: 15.0, angle: 15.0,
damage_effect: None, damage_effect: None,
multi_target: false, multi_target: None,
}, },
ori_modifier: 1.0, ori_modifier: 1.0,
ability_info: empty_ability_info(), ability_info: empty_ability_info(),