Merge branch 'aweinstock/mindflayerfixes-202105' into 'master'

Mindflayer AI improvments

See merge request veloren/veloren!2285
This commit is contained in:
Samuel Keiffer 2021-05-10 02:54:21 +00:00
commit a86c3af42b
10 changed files with 107 additions and 19 deletions

View File

@ -125,6 +125,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Wolf AI will no longer circle into walls and will instead use the power of raycasts to stop early
- Squirrels are no longer immune to arrows at some angles.
- /spawn command's auto-complete now works for species names
- Mindflayer AI now correctly summons husks at certain HP thresholds.
## [0.9.0] - 2021-03-20

View File

@ -204,6 +204,7 @@
secondary: "common.abilities.custom.mindflayer.necroticvortex",
abilities: [
(None, "common.abilities.custom.mindflayer.dimensionaldoor"),
(None, "common.abilities.custom.mindflayer.necroticsphere"),
(None, "common.abilities.custom.mindflayer.summonminions"),
],
),

View File

@ -0,0 +1,12 @@
BasicRanged(
energy_cost: 0,
buildup_duration: 0.75,
recover_duration: 0.4,
projectile: NecroticSphere(
damage: 300.0,
radius: 5.0,
),
projectile_body: Object(FireworkPurple),
projectile_speed: 100.0,
)

View File

@ -8,9 +8,5 @@ BasicRanged(
energy_regen: 50,
),
projectile_body: Object(BoltFire),
/*projectile_light: Some(LightEmitter {
col: (1.0, 0.75, 0.11).into(),
..Default::default()
}),*/
projectile_speed: 60.0,
)

View File

@ -281,6 +281,7 @@ pub struct ActionState {
pub timer: f32,
pub counter: f32,
pub condition: bool,
pub int_counter: u8,
}
impl Agent {

View File

@ -54,6 +54,10 @@ pub enum ProjectileConstructor {
damage: f32,
radius: f32,
},
NecroticSphere {
damage: f32,
radius: f32,
},
Possess,
}
@ -168,6 +172,32 @@ impl ProjectileConstructor {
ignore_group: true,
}
},
NecroticSphere { damage, radius } => {
let damage = AttackDamage::new(
Damage {
source: DamageSource::Explosion,
kind: DamageKind::Energy,
value: damage,
},
Some(GroupTarget::OutOfGroup),
);
let attack = Attack::default()
.with_damage(damage)
.with_crit(crit_chance, crit_mult)
.with_combo_increment();
let explosion = Explosion {
effects: vec![RadiusEffect::Attack(attack)],
radius,
reagent: Some(Reagent::Purple),
};
Projectile {
hit_solid: vec![Effect::Explode(explosion.clone()), Effect::Vanish],
hit_entity: vec![Effect::Explode(explosion), Effect::Vanish],
time_left: Duration::from_secs(10),
owner,
ignore_group: true,
}
},
Possess => Projectile {
hit_solid: vec![Effect::Stick],
hit_entity: vec![Effect::Stick, Effect::Possess],
@ -207,6 +237,14 @@ impl ProjectileConstructor {
*damage *= power;
*radius *= range;
},
NecroticSphere {
ref mut damage,
ref mut radius,
..
} => {
*damage *= power;
*radius *= range;
},
Possess => {},
}
self

View File

@ -581,9 +581,9 @@ fn handle_ability(data: &JoinData, update: &mut StateUpdate, input: InputKind) {
InputKind::Primary => Some(abilities.primary.clone()),
InputKind::Secondary => Some(abilities.secondary.clone()),
InputKind::Ability(0) => abilities.abilities.get(0).cloned().and_then(unlocked),
InputKind::Ability(_) => abilities
InputKind::Ability(i) => abilities
.abilities
.get(skill_index)
.get(if i < 2 { skill_index } else { i })
.cloned()
.and_then(unlocked),
InputKind::Roll | InputKind::Jump | InputKind::Fly | InputKind::Block => None,

View File

@ -22,6 +22,8 @@ common-net = { package = "veloren-common-net", path = "../common/net" }
world = { package = "veloren-world", path = "../world" }
network = { package = "veloren-network", path = "../network", features = ["metrics", "compression"], default-features = false }
# inline_tweak = "1.0.8"
specs = { git = "https://github.com/amethyst/specs.git", features = ["shred-derive"], rev = "5a9b71035007be0e3574f35184acac1cd4530496" }
specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", rev = "b65fb220e94f5d3c9bc30074a076149763795556" }

View File

@ -2997,8 +2997,9 @@ impl<'a> AgentData<'a> {
const MINDFLAYER_ATTACK_DIST: f32 = 16.0;
const MINION_SUMMON_THRESHOLD: f32 = 0.20;
let health_fraction = self.health.map_or(0.5, |h| h.fraction());
// Sets counter at start of combat
if agent.action_state.condition {
// Sets counter at start of combat, using `condition` to keep track of whether
// it was already intitialized
if !agent.action_state.condition {
agent.action_state.counter = 1.0 - MINION_SUMMON_THRESHOLD;
agent.action_state.condition = true;
}
@ -3007,22 +3008,41 @@ impl<'a> AgentData<'a> {
// Summon minions at particular thresholds of health
controller
.actions
.push(ControlAction::basic_input(InputKind::Ability(1)));
.push(ControlAction::basic_input(InputKind::Ability(2)));
if matches!(self.char_state, CharacterState::BasicSummon(c) if matches!(c.stage_section, StageSection::Recover))
{
agent.action_state.counter -= MINION_SUMMON_THRESHOLD;
}
} else if mindflayer_is_far {
// If too far from target, blink to them.
controller.actions.push(ControlAction::StartInput {
input: InputKind::Ability(0),
target_entity: agent
.target
.as_ref()
.and_then(|t| read_data.uids.get(t.target))
.copied(),
select_pos: None,
});
// If too far from target, throw a random number of necrotic spheres at them and
// then blink to them.
let num_fireballs = &mut agent.action_state.int_counter;
if *num_fireballs == 0 {
controller.actions.push(ControlAction::StartInput {
input: InputKind::Ability(0),
target_entity: agent
.target
.as_ref()
.and_then(|t| read_data.uids.get(t.target))
.copied(),
select_pos: None,
});
if matches!(self.char_state, CharacterState::Blink(_)) {
*num_fireballs = rand::random::<u8>() % 4;
}
} else if matches!(self.char_state, CharacterState::Wielding) {
*num_fireballs -= 1;
controller.actions.push(ControlAction::StartInput {
input: InputKind::Ability(1),
target_entity: agent
.target
.as_ref()
.and_then(|t| read_data.uids.get(t.target))
.copied(),
select_pos: None,
});
}
} else {
// If close to target, use either primary or secondary ability
if matches!(self.char_state, CharacterState::BasicBeam(c) if c.timer < Duration::from_secs(10) && !matches!(c.stage_section, StageSection::Recover))

View File

@ -117,6 +117,23 @@ impl ParticleMgr {
},
);
},
Some(Reagent::Purple) => {
self.particles.resize_with(
self.particles.len() + (75.0 * power.abs()) as usize,
|| {
Particle::new_directed(
Duration::from_millis(500),
time,
ParticleMode::CultistFlame,
*pos,
*pos + Vec3::<f32>::zero()
.map(|_| rng.gen_range(-1.0..1.0))
.normalized()
* *radius,
)
},
);
},
_ => {},
}
} else {