mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add a purple fireball to mindflayer and have it shoot it a few times before teleporting, and fix mindflayer AI's husk summons.
This commit is contained in:
parent
9168ddac75
commit
1dfcdce1c0
43
Cargo.lock
generated
43
Cargo.lock
generated
@ -2399,6 +2399,15 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inline_tweak"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7033e97b20277cc0d043226d1940fa7719ff08d2305d1fc7421e53066d00eb4b"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inotify"
|
name = "inotify"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@ -5514,6 +5523,7 @@ name = "veloren-common"
|
|||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"approx 0.4.0",
|
"approx 0.4.0",
|
||||||
|
"assets_manager",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"criterion",
|
"criterion",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
@ -5522,6 +5532,7 @@ dependencies = [
|
|||||||
"dot_vox",
|
"dot_vox",
|
||||||
"enum-iterator",
|
"enum-iterator",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
|
"image",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"num-derive",
|
"num-derive",
|
||||||
@ -5529,8 +5540,10 @@ dependencies = [
|
|||||||
"ordered-float 2.1.1",
|
"ordered-float 2.1.1",
|
||||||
"rand 0.8.3",
|
"rand 0.8.3",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
"ron",
|
||||||
"roots",
|
"roots",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
"slab",
|
"slab",
|
||||||
"slotmap",
|
"slotmap",
|
||||||
@ -5544,22 +5557,9 @@ dependencies = [
|
|||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"uuid",
|
"uuid",
|
||||||
"vek",
|
"vek",
|
||||||
"veloren-common-assets",
|
|
||||||
"veloren-common-base",
|
"veloren-common-base",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "veloren-common-assets"
|
|
||||||
version = "0.9.0"
|
|
||||||
dependencies = [
|
|
||||||
"assets_manager",
|
|
||||||
"dot_vox",
|
|
||||||
"image",
|
|
||||||
"lazy_static",
|
|
||||||
"ron",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "veloren-common-base"
|
name = "veloren-common-base"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -5652,19 +5652,6 @@ dependencies = [
|
|||||||
"veloren-common-net",
|
"veloren-common-net",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "veloren-i18n"
|
|
||||||
version = "0.9.0"
|
|
||||||
dependencies = [
|
|
||||||
"deunicode",
|
|
||||||
"git2",
|
|
||||||
"hashbrown",
|
|
||||||
"ron",
|
|
||||||
"serde",
|
|
||||||
"tracing",
|
|
||||||
"veloren-common-assets",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "veloren-network"
|
name = "veloren-network"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -5749,6 +5736,7 @@ dependencies = [
|
|||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
|
"inline_tweak",
|
||||||
"itertools 0.10.0",
|
"itertools 0.10.0",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
@ -5817,6 +5805,7 @@ dependencies = [
|
|||||||
"cpal",
|
"cpal",
|
||||||
"criterion",
|
"criterion",
|
||||||
"crossbeam",
|
"crossbeam",
|
||||||
|
"deunicode",
|
||||||
"directories-next",
|
"directories-next",
|
||||||
"dispatch 0.1.4",
|
"dispatch 0.1.4",
|
||||||
"dot_vox",
|
"dot_vox",
|
||||||
@ -5826,6 +5815,7 @@ dependencies = [
|
|||||||
"gfx_device_gl",
|
"gfx_device_gl",
|
||||||
"gfx_gl",
|
"gfx_gl",
|
||||||
"gilrs",
|
"gilrs",
|
||||||
|
"git2",
|
||||||
"glsl-include",
|
"glsl-include",
|
||||||
"glutin",
|
"glutin",
|
||||||
"glyph_brush",
|
"glyph_brush",
|
||||||
@ -5863,7 +5853,6 @@ dependencies = [
|
|||||||
"veloren-common-net",
|
"veloren-common-net",
|
||||||
"veloren-common-state",
|
"veloren-common-state",
|
||||||
"veloren-common-systems",
|
"veloren-common-systems",
|
||||||
"veloren-i18n",
|
|
||||||
"veloren-server",
|
"veloren-server",
|
||||||
"veloren-voxygen-anim",
|
"veloren-voxygen-anim",
|
||||||
"veloren-world",
|
"veloren-world",
|
||||||
|
@ -204,6 +204,7 @@
|
|||||||
secondary: "common.abilities.custom.mindflayer.necroticvortex",
|
secondary: "common.abilities.custom.mindflayer.necroticvortex",
|
||||||
abilities: [
|
abilities: [
|
||||||
(None, "common.abilities.custom.mindflayer.dimensionaldoor"),
|
(None, "common.abilities.custom.mindflayer.dimensionaldoor"),
|
||||||
|
(None, "common.abilities.custom.mindflayer.necroticsphere"),
|
||||||
(None, "common.abilities.custom.mindflayer.summonminions"),
|
(None, "common.abilities.custom.mindflayer.summonminions"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
16
assets/common/abilities/custom/mindflayer/necroticsphere.ron
Normal file
16
assets/common/abilities/custom/mindflayer/necroticsphere.ron
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
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_light: Some(LightEmitter {
|
||||||
|
col: (1.0, 0.75, 0.11).into(),
|
||||||
|
..Default::default()
|
||||||
|
}),*/
|
||||||
|
projectile_speed: 100.0,
|
||||||
|
)
|
||||||
|
|
@ -280,7 +280,7 @@ pub struct Agent {
|
|||||||
pub struct ActionState {
|
pub struct ActionState {
|
||||||
pub timer: f32,
|
pub timer: f32,
|
||||||
pub counter: f32,
|
pub counter: f32,
|
||||||
pub condition: bool,
|
pub condition: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Agent {
|
impl Agent {
|
||||||
|
@ -54,6 +54,10 @@ pub enum ProjectileConstructor {
|
|||||||
damage: f32,
|
damage: f32,
|
||||||
radius: f32,
|
radius: f32,
|
||||||
},
|
},
|
||||||
|
NecroticSphere {
|
||||||
|
damage: f32,
|
||||||
|
radius: f32,
|
||||||
|
},
|
||||||
Possess,
|
Possess,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,6 +172,32 @@ impl ProjectileConstructor {
|
|||||||
ignore_group: true,
|
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 {
|
Possess => Projectile {
|
||||||
hit_solid: vec![Effect::Stick],
|
hit_solid: vec![Effect::Stick],
|
||||||
hit_entity: vec![Effect::Stick, Effect::Possess],
|
hit_entity: vec![Effect::Stick, Effect::Possess],
|
||||||
@ -207,6 +237,14 @@ impl ProjectileConstructor {
|
|||||||
*damage *= power;
|
*damage *= power;
|
||||||
*radius *= range;
|
*radius *= range;
|
||||||
},
|
},
|
||||||
|
NecroticSphere {
|
||||||
|
ref mut damage,
|
||||||
|
ref mut radius,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
*damage *= power;
|
||||||
|
*radius *= range;
|
||||||
|
},
|
||||||
Possess => {},
|
Possess => {},
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
|
@ -577,27 +577,33 @@ fn handle_ability(data: &JoinData, update: &mut StateUpdate, input: InputKind) {
|
|||||||
.inventory
|
.inventory
|
||||||
.equipped(equip_slot)
|
.equipped(equip_slot)
|
||||||
.map(|i| &i.item_config_expect().abilities)
|
.map(|i| &i.item_config_expect().abilities)
|
||||||
.and_then(|abilities| match input {
|
.and_then(|abilities| {
|
||||||
InputKind::Primary => Some(abilities.primary.clone()),
|
tracing::info!("ability: {:?} {:?}", input, abilities);
|
||||||
InputKind::Secondary => Some(abilities.secondary.clone()),
|
match input {
|
||||||
InputKind::Ability(0) => abilities.abilities.get(0).cloned().and_then(unlocked),
|
InputKind::Primary => Some(abilities.primary.clone()),
|
||||||
InputKind::Ability(_) => abilities
|
InputKind::Secondary => Some(abilities.secondary.clone()),
|
||||||
.abilities
|
InputKind::Ability(0) => abilities.abilities.get(0).cloned().and_then(unlocked),
|
||||||
.get(skill_index)
|
InputKind::Ability(skill_index) => abilities
|
||||||
.cloned()
|
.abilities
|
||||||
.and_then(unlocked),
|
.get(skill_index)
|
||||||
InputKind::Roll | InputKind::Jump | InputKind::Fly | InputKind::Block => None,
|
.cloned()
|
||||||
|
.and_then(unlocked),
|
||||||
|
InputKind::Roll | InputKind::Jump | InputKind::Fly | InputKind::Block => None,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.map(|a| {
|
.map(|a| {
|
||||||
let tool = unwrap_tool_data(data, equip_slot).map(|t| t.kind);
|
let tool = unwrap_tool_data(data, equip_slot).map(|t| t.kind);
|
||||||
|
tracing::info!("ability tool: {:?} {:?}", input, tool);
|
||||||
a.adjusted_by_skills(&data.skill_set, tool)
|
a.adjusted_by_skills(&data.skill_set, tool)
|
||||||
})
|
})
|
||||||
.filter(|ability| ability.requirements_paid(data, update))
|
.filter(|ability| ability.requirements_paid(data, update))
|
||||||
{
|
{
|
||||||
|
tracing::info!("ability before setting state: {:?} {:?}", input, ability);
|
||||||
update.character = CharacterState::from((
|
update.character = CharacterState::from((
|
||||||
&ability,
|
&ability,
|
||||||
AbilityInfo::from_input(data, matches!(equip_slot, EquipSlot::Offhand), input),
|
AbilityInfo::from_input(data, matches!(equip_slot, EquipSlot::Offhand), input),
|
||||||
));
|
));
|
||||||
|
tracing::info!("ability setting state: {:?} {:?}", input, update.character);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -801,12 +807,14 @@ impl AbilityInfo {
|
|||||||
tool_data.map(|t| HandInfo::from_main_tool(t, from_offhand)),
|
tool_data.map(|t| HandInfo::from_main_tool(t, from_offhand)),
|
||||||
);
|
);
|
||||||
|
|
||||||
Self {
|
let ret = Self {
|
||||||
tool,
|
tool,
|
||||||
hand,
|
hand,
|
||||||
input,
|
input,
|
||||||
input_attr: data.controller.queued_inputs.get(&input).copied(),
|
input_attr: data.controller.queued_inputs.get(&input).copied(),
|
||||||
}
|
};
|
||||||
|
tracing::info!("AbilityInfo::from_input: {:?} {:?}", input, ret);
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@ common-net = { package = "veloren-common-net", path = "../common/net" }
|
|||||||
world = { package = "veloren-world", path = "../world" }
|
world = { package = "veloren-world", path = "../world" }
|
||||||
network = { package = "veloren-network", path = "../network", features = ["metrics", "compression"], default-features = false }
|
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 = { git = "https://github.com/amethyst/specs.git", features = ["shred-derive"], rev = "5a9b71035007be0e3574f35184acac1cd4530496" }
|
||||||
specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", rev = "b65fb220e94f5d3c9bc30074a076149763795556" }
|
specs-idvs = { git = "https://gitlab.com/veloren/specs-idvs.git", rev = "b65fb220e94f5d3c9bc30074a076149763795556" }
|
||||||
|
|
||||||
|
@ -2996,33 +2996,73 @@ impl<'a> AgentData<'a> {
|
|||||||
) {
|
) {
|
||||||
const MINDFLAYER_ATTACK_DIST: f32 = 16.0;
|
const MINDFLAYER_ATTACK_DIST: f32 = 16.0;
|
||||||
const MINION_SUMMON_THRESHOLD: f32 = 0.20;
|
const MINION_SUMMON_THRESHOLD: f32 = 0.20;
|
||||||
|
// Bit index of action_state.condition for whether the mindflayer initialized
|
||||||
|
// minion summoning state
|
||||||
|
const MINDFLAYER_INITIALIZED_THRESHOLD: usize = 0;
|
||||||
|
// Bit index of action_state.condition for how many fireballs left to shoot
|
||||||
|
// before blinking (this is a 2 bit number, from 0-3)
|
||||||
|
const MINDFLAYER_NUM_FIREBALLS_LO: usize = 1;
|
||||||
|
const MINDFLAYER_NUM_FIREBALLS_MASK: usize = 0b110;
|
||||||
let health_fraction = self.health.map_or(0.5, |h| h.fraction());
|
let health_fraction = self.health.map_or(0.5, |h| h.fraction());
|
||||||
// Sets counter at start of combat
|
// Sets counter at start of combat
|
||||||
if agent.action_state.condition {
|
if (agent.action_state.condition & (1 << MINDFLAYER_INITIALIZED_THRESHOLD)) == 0 {
|
||||||
agent.action_state.counter = 1.0 - MINION_SUMMON_THRESHOLD;
|
agent.action_state.counter = 1.0 - MINION_SUMMON_THRESHOLD;
|
||||||
agent.action_state.condition = true;
|
agent.action_state.condition |= 1 << MINDFLAYER_INITIALIZED_THRESHOLD;
|
||||||
|
}
|
||||||
|
agent.action_state.timer = (agent.action_state.timer - read_data.dt.0 as f32).max(0.0);
|
||||||
|
if agent.action_state.timer > 0.0 {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
let mindflayer_is_far = attack_data.dist_sqrd > MINDFLAYER_ATTACK_DIST.powi(2);
|
let mindflayer_is_far = attack_data.dist_sqrd > MINDFLAYER_ATTACK_DIST.powi(2);
|
||||||
if agent.action_state.counter > health_fraction {
|
if agent.action_state.counter > health_fraction {
|
||||||
// Summon minions at particular thresholds of health
|
// Summon minions at particular thresholds of health
|
||||||
controller
|
controller
|
||||||
.actions
|
.actions
|
||||||
.push(ControlAction::basic_input(InputKind::Ability(1)));
|
.push(ControlAction::basic_input(InputKind::Ability(2)));
|
||||||
|
|
||||||
|
//tracing::info!("Pushing summon state: {:?}", agent);
|
||||||
if matches!(self.char_state, CharacterState::BasicSummon(c) if matches!(c.stage_section, StageSection::Recover))
|
if matches!(self.char_state, CharacterState::BasicSummon(c) if matches!(c.stage_section, StageSection::Recover))
|
||||||
{
|
{
|
||||||
agent.action_state.counter -= MINION_SUMMON_THRESHOLD;
|
agent.action_state.counter -= MINION_SUMMON_THRESHOLD;
|
||||||
}
|
}
|
||||||
|
} else if matches!(
|
||||||
|
self.char_state,
|
||||||
|
CharacterState::BasicSummon(_) | CharacterState::Blink(_)
|
||||||
|
) {
|
||||||
|
// Deliberately do nothing here to prevent overwriting summon/blink state with another
|
||||||
|
// input
|
||||||
} else if mindflayer_is_far {
|
} else if mindflayer_is_far {
|
||||||
// If too far from target, blink to them.
|
// If too far from target, throw a random number of necrotic spheres at them and then
|
||||||
controller.actions.push(ControlAction::StartInput {
|
// blink to them.
|
||||||
input: InputKind::Ability(0),
|
let num_fireballs = (agent.action_state.condition & 0b110) >> 1;
|
||||||
target_entity: agent
|
if num_fireballs == 0 {
|
||||||
.target
|
let new_num_fireballs = rand::random::<u8>() % 4;
|
||||||
.as_ref()
|
agent.action_state.condition &= !0b110;
|
||||||
.and_then(|t| read_data.uids.get(t.target))
|
agent.action_state.condition |= new_num_fireballs << 1;
|
||||||
.copied(),
|
controller.actions.push(ControlAction::StartInput {
|
||||||
select_pos: None,
|
input: InputKind::Ability(0),
|
||||||
});
|
target_entity: agent
|
||||||
|
.target
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|t| read_data.uids.get(t.target))
|
||||||
|
.copied(),
|
||||||
|
select_pos: None,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let new_num_fireballs = num_fireballs - 1;
|
||||||
|
agent.action_state.condition &= !0b110;
|
||||||
|
agent.action_state.condition |= new_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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
agent.action_state.timer = 0.1;
|
||||||
} else {
|
} else {
|
||||||
// If close to target, use either primary or secondary ability
|
// 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))
|
if matches!(self.char_state, CharacterState::BasicBeam(c) if c.timer < Duration::from_secs(10) && !matches!(c.stage_section, StageSection::Recover))
|
||||||
@ -3353,6 +3393,9 @@ impl<'a> AgentData<'a> {
|
|||||||
const MINOTAUR_FRENZY_THRESHOLD: f32 = 0.5;
|
const MINOTAUR_FRENZY_THRESHOLD: f32 = 0.5;
|
||||||
const MINOTAUR_ATTACK_RANGE: f32 = 5.0;
|
const MINOTAUR_ATTACK_RANGE: f32 = 5.0;
|
||||||
const MINOTAUR_CHARGE_DISTANCE: f32 = 15.0;
|
const MINOTAUR_CHARGE_DISTANCE: f32 = 15.0;
|
||||||
|
// Bit index of the action_state.condition if the minotaur should use secondary
|
||||||
|
// instead of primary
|
||||||
|
const MINOTAUR_STATE_SECONDARY: usize = 0;
|
||||||
let minotaur_attack_distance =
|
let minotaur_attack_distance =
|
||||||
self.body.map_or(0.0, |b| b.radius()) + MINOTAUR_ATTACK_RANGE;
|
self.body.map_or(0.0, |b| b.radius()) + MINOTAUR_ATTACK_RANGE;
|
||||||
let health_fraction = self.health.map_or(1.0, |h| h.fraction());
|
let health_fraction = self.health.map_or(1.0, |h| h.fraction());
|
||||||
@ -3391,18 +3434,20 @@ impl<'a> AgentData<'a> {
|
|||||||
.push(ControlAction::basic_input(InputKind::Ability(0)));
|
.push(ControlAction::basic_input(InputKind::Ability(0)));
|
||||||
}
|
}
|
||||||
} else if attack_data.dist_sqrd < minotaur_attack_distance.powi(2) {
|
} else if attack_data.dist_sqrd < minotaur_attack_distance.powi(2) {
|
||||||
if agent.action_state.condition && !self.char_state.is_attack() {
|
if (agent.action_state.condition & (1 << MINOTAUR_STATE_SECONDARY)) != 0
|
||||||
|
&& !self.char_state.is_attack()
|
||||||
|
{
|
||||||
// Cripple target if not just used cripple
|
// Cripple target if not just used cripple
|
||||||
controller
|
controller
|
||||||
.actions
|
.actions
|
||||||
.push(ControlAction::basic_input(InputKind::Secondary));
|
.push(ControlAction::basic_input(InputKind::Secondary));
|
||||||
agent.action_state.condition = false;
|
agent.action_state.condition &= !(1 << MINOTAUR_STATE_SECONDARY);
|
||||||
} else if !self.char_state.is_attack() {
|
} else if !self.char_state.is_attack() {
|
||||||
// Cleave target if not just used cleave
|
// Cleave target if not just used cleave
|
||||||
controller
|
controller
|
||||||
.actions
|
.actions
|
||||||
.push(ControlAction::basic_input(InputKind::Primary));
|
.push(ControlAction::basic_input(InputKind::Primary));
|
||||||
agent.action_state.condition = true;
|
agent.action_state.condition |= 1 << MINOTAUR_STATE_SECONDARY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Make minotaur move towards target
|
// Make minotaur move towards target
|
||||||
|
@ -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 {
|
} else {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user