mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added summon minions ability to mindflayer
This commit is contained in:
parent
30da614e89
commit
a5b7477e96
@ -23,6 +23,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
- Seperated character randomization buttons into appearance and name.
|
- Seperated character randomization buttons into appearance and name.
|
||||||
|
|
||||||
|
- Reworked mindflayer to have unique attacks
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@ -1 +0,0 @@
|
|||||||
BasicBlock
|
|
16
assets/common/abilities/unique/mindflayer/summonminions.ron
Normal file
16
assets/common/abilities/unique/mindflayer/summonminions.ron
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
BasicSummon(
|
||||||
|
buildup_duration: 0.5,
|
||||||
|
cast_duration: 1.0,
|
||||||
|
recover_duration: 0.5,
|
||||||
|
summon_amount: 4,
|
||||||
|
summon_info: (
|
||||||
|
body: QuadrupedMedium((
|
||||||
|
species: Darkhound,
|
||||||
|
body_type: Male,
|
||||||
|
)),
|
||||||
|
scale: None,
|
||||||
|
health_scaling: 0,
|
||||||
|
loadout_config: None,
|
||||||
|
skillset_config: None,
|
||||||
|
),
|
||||||
|
)
|
@ -199,7 +199,7 @@
|
|||||||
secondary: "common.abilities.unique.mindflayer.necroticvortex",
|
secondary: "common.abilities.unique.mindflayer.necroticvortex",
|
||||||
abilities: [
|
abilities: [
|
||||||
(None, "common.abilities.unique.mindflayer.dimensionaldoor"),
|
(None, "common.abilities.unique.mindflayer.dimensionaldoor"),
|
||||||
(None, "common.abilities.unique.mindflayer.raiseundead"),
|
(None, "common.abilities.unique.mindflayer.summonminions"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Debug: (
|
Debug: (
|
||||||
|
@ -256,6 +256,13 @@ pub enum CharacterAbility {
|
|||||||
recover_duration: f32,
|
recover_duration: f32,
|
||||||
max_range: f32,
|
max_range: f32,
|
||||||
},
|
},
|
||||||
|
BasicSummon {
|
||||||
|
buildup_duration: f32,
|
||||||
|
cast_duration: f32,
|
||||||
|
recover_duration: f32,
|
||||||
|
summon_amount: u32,
|
||||||
|
summon_info: basic_summon::SummonInfo,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CharacterAbility {
|
impl Default for CharacterAbility {
|
||||||
@ -544,6 +551,17 @@ impl CharacterAbility {
|
|||||||
*buildup_duration /= speed;
|
*buildup_duration /= speed;
|
||||||
*recover_duration /= speed;
|
*recover_duration /= speed;
|
||||||
},
|
},
|
||||||
|
BasicSummon {
|
||||||
|
ref mut buildup_duration,
|
||||||
|
ref mut cast_duration,
|
||||||
|
ref mut recover_duration,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
// TODO: Figure out how/if power should affect this
|
||||||
|
*buildup_duration /= speed;
|
||||||
|
*cast_duration /= speed;
|
||||||
|
*recover_duration /= speed;
|
||||||
|
},
|
||||||
}
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -570,7 +588,7 @@ impl CharacterAbility {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
BasicBlock | Boost { .. } | ComboMelee { .. } | Blink { .. } => 0,
|
BasicBlock | Boost { .. } | ComboMelee { .. } | Blink { .. } | BasicSummon { .. } => 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1586,6 +1604,25 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
stage_section: StageSection::Buildup,
|
stage_section: StageSection::Buildup,
|
||||||
}),
|
}),
|
||||||
|
CharacterAbility::BasicSummon {
|
||||||
|
buildup_duration,
|
||||||
|
cast_duration,
|
||||||
|
recover_duration,
|
||||||
|
summon_amount,
|
||||||
|
summon_info,
|
||||||
|
} => CharacterState::BasicSummon(basic_summon::Data {
|
||||||
|
static_data: basic_summon::StaticData {
|
||||||
|
buildup_duration: Duration::from_secs_f32(*buildup_duration),
|
||||||
|
cast_duration: Duration::from_secs_f32(*cast_duration),
|
||||||
|
recover_duration: Duration::from_secs_f32(*recover_duration),
|
||||||
|
summon_amount: *summon_amount,
|
||||||
|
summon_info: *summon_info,
|
||||||
|
ability_info,
|
||||||
|
},
|
||||||
|
summon_count: 0,
|
||||||
|
timer: Duration::default(),
|
||||||
|
stage_section: StageSection::Buildup,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,8 @@ pub enum CharacterState {
|
|||||||
HealingBeam(healing_beam::Data),
|
HealingBeam(healing_beam::Data),
|
||||||
/// A short teleport that targets either a position or entity
|
/// A short teleport that targets either a position or entity
|
||||||
Blink(blink::Data),
|
Blink(blink::Data),
|
||||||
|
/// Summons creatures that fight for the caster
|
||||||
|
BasicSummon(basic_summon::Data),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CharacterState {
|
impl CharacterState {
|
||||||
|
@ -34,7 +34,7 @@ pub enum HealthSource {
|
|||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Health {
|
pub struct Health {
|
||||||
current: u32,
|
current: u32,
|
||||||
base_max: u32,
|
base_max: u32,
|
||||||
|
@ -12,6 +12,7 @@ use crate::{
|
|||||||
trade::{Good, SiteInformation},
|
trade::{Good, SiteInformation},
|
||||||
};
|
};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Builder for character Loadouts, containing weapon and armour items belonging
|
/// Builder for character Loadouts, containing weapon and armour items belonging
|
||||||
/// to a character, along with some helper methods for loading Items and
|
/// to a character, along with some helper methods for loading Items and
|
||||||
@ -34,7 +35,7 @@ use rand::Rng;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct LoadoutBuilder(Loadout);
|
pub struct LoadoutBuilder(Loadout);
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, PartialEq, Serialize, Deserialize, Debug)]
|
||||||
pub enum LoadoutConfig {
|
pub enum LoadoutConfig {
|
||||||
Adlet,
|
Adlet,
|
||||||
Gnarling,
|
Gnarling,
|
||||||
|
@ -4,9 +4,10 @@ use crate::comp::{
|
|||||||
AxeSkill, BowSkill, HammerSkill, Skill, SkillGroupKind, SkillSet, StaffSkill, SwordSkill,
|
AxeSkill, BowSkill, HammerSkill, Skill, SkillGroupKind, SkillSet, StaffSkill, SwordSkill,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, PartialEq, Serialize, Deserialize, Debug)]
|
||||||
pub enum SkillSetConfig {
|
pub enum SkillSetConfig {
|
||||||
Adlet,
|
Adlet,
|
||||||
Gnarling,
|
Gnarling,
|
||||||
|
176
common/src/states/basic_summon.rs
Normal file
176
common/src/states/basic_summon.rs
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
use crate::{
|
||||||
|
comp::{
|
||||||
|
self,
|
||||||
|
inventory::loadout_builder::{LoadoutBuilder, LoadoutConfig},
|
||||||
|
CharacterState, StateUpdate,
|
||||||
|
},
|
||||||
|
event::ServerEvent,
|
||||||
|
skillset_builder::{SkillSetBuilder, SkillSetConfig},
|
||||||
|
states::{
|
||||||
|
behavior::{CharacterBehavior, JoinData},
|
||||||
|
utils::*,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
/// Separated out to condense update portions of character state
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct StaticData {
|
||||||
|
/// How long the state builds up for
|
||||||
|
pub buildup_duration: Duration,
|
||||||
|
/// How long the state is casting for
|
||||||
|
pub cast_duration: Duration,
|
||||||
|
/// How long the state recovers for
|
||||||
|
pub recover_duration: Duration,
|
||||||
|
/// How many creatures the state should summon
|
||||||
|
pub summon_amount: u32,
|
||||||
|
/// Information about the summoned creature
|
||||||
|
pub summon_info: SummonInfo,
|
||||||
|
/// Miscellaneous information about the ability
|
||||||
|
pub ability_info: AbilityInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct Data {
|
||||||
|
/// Struct containing data that does not change over the course of the
|
||||||
|
/// character state
|
||||||
|
pub static_data: StaticData,
|
||||||
|
/// How many creatures have been summoned
|
||||||
|
pub summon_count: u32,
|
||||||
|
/// Timer for each stage
|
||||||
|
pub timer: Duration,
|
||||||
|
/// What section the character stage is in
|
||||||
|
pub stage_section: StageSection,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CharacterBehavior for Data {
|
||||||
|
fn behavior(&self, data: &JoinData) -> StateUpdate {
|
||||||
|
let mut update = StateUpdate::from(data);
|
||||||
|
|
||||||
|
match self.stage_section {
|
||||||
|
StageSection::Buildup => {
|
||||||
|
if self.timer < self.static_data.buildup_duration {
|
||||||
|
// Build up
|
||||||
|
update.character = CharacterState::BasicSummon(Data {
|
||||||
|
timer: self
|
||||||
|
.timer
|
||||||
|
.checked_add(Duration::from_secs_f32(data.dt.0))
|
||||||
|
.unwrap_or_default(),
|
||||||
|
..*self
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Transitions to recover section of stage
|
||||||
|
update.character = CharacterState::BasicSummon(Data {
|
||||||
|
timer: Duration::default(),
|
||||||
|
stage_section: StageSection::Cast,
|
||||||
|
..*self
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
StageSection::Cast => {
|
||||||
|
if self.timer < self.static_data.cast_duration
|
||||||
|
|| self.summon_count < self.static_data.summon_amount
|
||||||
|
{
|
||||||
|
if self.timer
|
||||||
|
> self.static_data.cast_duration * self.summon_count
|
||||||
|
/ self.static_data.summon_amount
|
||||||
|
{
|
||||||
|
let body = self.static_data.summon_info.body;
|
||||||
|
|
||||||
|
let mut stats = comp::Stats::new("Summon".to_string());
|
||||||
|
stats.skill_set = SkillSetBuilder::build_skillset(
|
||||||
|
&None,
|
||||||
|
self.static_data.summon_info.skillset_config,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
let loadout = LoadoutBuilder::build_loadout(
|
||||||
|
body,
|
||||||
|
None,
|
||||||
|
self.static_data.summon_info.loadout_config,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
update.server_events.push_front(ServerEvent::CreateNpc {
|
||||||
|
pos: *data.pos,
|
||||||
|
stats,
|
||||||
|
health: comp::Health::new(
|
||||||
|
body,
|
||||||
|
self.static_data.summon_info.health_scaling,
|
||||||
|
),
|
||||||
|
poise: comp::Poise::new(body),
|
||||||
|
loadout,
|
||||||
|
body,
|
||||||
|
agent: Some(comp::Agent::new(None, false, None, &body, true)),
|
||||||
|
alignment: comp::Alignment::Owned(*data.uid),
|
||||||
|
scale: self
|
||||||
|
.static_data
|
||||||
|
.summon_info
|
||||||
|
.scale
|
||||||
|
.unwrap_or(comp::Scale(1.0)),
|
||||||
|
home_chunk: None,
|
||||||
|
drop_item: None,
|
||||||
|
rtsim_entity: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
update.character = CharacterState::BasicSummon(Data {
|
||||||
|
timer: self
|
||||||
|
.timer
|
||||||
|
.checked_add(Duration::from_secs_f32(data.dt.0))
|
||||||
|
.unwrap_or_default(),
|
||||||
|
summon_count: self.summon_count + 1,
|
||||||
|
..*self
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Cast
|
||||||
|
update.character = CharacterState::BasicSummon(Data {
|
||||||
|
timer: self
|
||||||
|
.timer
|
||||||
|
.checked_add(Duration::from_secs_f32(data.dt.0))
|
||||||
|
.unwrap_or_default(),
|
||||||
|
..*self
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Transitions to recover section of stage
|
||||||
|
update.character = CharacterState::BasicSummon(Data {
|
||||||
|
timer: Duration::default(),
|
||||||
|
stage_section: StageSection::Recover,
|
||||||
|
..*self
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
StageSection::Recover => {
|
||||||
|
if self.timer < self.static_data.recover_duration {
|
||||||
|
// Recovery
|
||||||
|
update.character = CharacterState::BasicSummon(Data {
|
||||||
|
timer: self
|
||||||
|
.timer
|
||||||
|
.checked_add(Duration::from_secs_f32(data.dt.0))
|
||||||
|
.unwrap_or_default(),
|
||||||
|
..*self
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Done
|
||||||
|
update.character = CharacterState::Wielding;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
// If it somehow ends up in an incorrect stage section
|
||||||
|
update.character = CharacterState::Wielding;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
update
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct SummonInfo {
|
||||||
|
body: comp::Body,
|
||||||
|
scale: Option<comp::Scale>,
|
||||||
|
health_scaling: u16,
|
||||||
|
loadout_config: Option<LoadoutConfig>,
|
||||||
|
skillset_config: Option<SkillSetConfig>,
|
||||||
|
}
|
@ -12,9 +12,13 @@ use std::time::Duration;
|
|||||||
/// Separated out to condense update portions of character state
|
/// Separated out to condense update portions of character state
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct StaticData {
|
pub struct StaticData {
|
||||||
|
/// How long the state builds up for
|
||||||
pub buildup_duration: Duration,
|
pub buildup_duration: Duration,
|
||||||
|
/// How long the state recovers for
|
||||||
pub recover_duration: Duration,
|
pub recover_duration: Duration,
|
||||||
|
/// What the max range of the teleport is
|
||||||
pub max_range: f32,
|
pub max_range: f32,
|
||||||
|
/// Miscellaneous information about the ability
|
||||||
pub ability_info: AbilityInfo,
|
pub ability_info: AbilityInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ pub mod basic_beam;
|
|||||||
pub mod basic_block;
|
pub mod basic_block;
|
||||||
pub mod basic_melee;
|
pub mod basic_melee;
|
||||||
pub mod basic_ranged;
|
pub mod basic_ranged;
|
||||||
|
pub mod basic_summon;
|
||||||
pub mod behavior;
|
pub mod behavior;
|
||||||
pub mod blink;
|
pub mod blink;
|
||||||
pub mod boost;
|
pub mod boost;
|
||||||
|
@ -47,7 +47,7 @@ pub struct StaticData {
|
|||||||
pub num_spins: u32,
|
pub num_spins: u32,
|
||||||
/// What key is used to press ability
|
/// What key is used to press ability
|
||||||
pub ability_info: AbilityInfo,
|
pub ability_info: AbilityInfo,
|
||||||
/// Used to specify the beam to the frontend
|
/// Used to specify the melee attack to the frontend
|
||||||
pub specifier: Option<FrontendSpecifier>,
|
pub specifier: Option<FrontendSpecifier>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,6 +303,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
CharacterState::BasicAura(data) => data.handle_event(&j, action),
|
CharacterState::BasicAura(data) => data.handle_event(&j, action),
|
||||||
CharacterState::HealingBeam(data) => data.handle_event(&j, action),
|
CharacterState::HealingBeam(data) => data.handle_event(&j, action),
|
||||||
CharacterState::Blink(data) => data.handle_event(&j, action),
|
CharacterState::Blink(data) => data.handle_event(&j, action),
|
||||||
|
CharacterState::BasicSummon(data) => data.handle_event(&j, action),
|
||||||
};
|
};
|
||||||
local_emitter.append(&mut state_update.local_events);
|
local_emitter.append(&mut state_update.local_events);
|
||||||
server_emitter.append(&mut state_update.server_events);
|
server_emitter.append(&mut state_update.server_events);
|
||||||
@ -356,6 +357,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
CharacterState::BasicAura(data) => data.behavior(&j),
|
CharacterState::BasicAura(data) => data.behavior(&j),
|
||||||
CharacterState::HealingBeam(data) => data.behavior(&j),
|
CharacterState::HealingBeam(data) => data.behavior(&j),
|
||||||
CharacterState::Blink(data) => data.behavior(&j),
|
CharacterState::Blink(data) => data.behavior(&j),
|
||||||
|
CharacterState::BasicSummon(data) => data.behavior(&j),
|
||||||
};
|
};
|
||||||
|
|
||||||
local_emitter.append(&mut state_update.local_events);
|
local_emitter.append(&mut state_update.local_events);
|
||||||
|
@ -247,7 +247,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
| CharacterState::BasicBeam { .. }
|
| CharacterState::BasicBeam { .. }
|
||||||
| CharacterState::BasicAura { .. }
|
| CharacterState::BasicAura { .. }
|
||||||
| CharacterState::HealingBeam { .. }
|
| CharacterState::HealingBeam { .. }
|
||||||
| CharacterState::Blink { .. } => {
|
| CharacterState::Blink { .. }
|
||||||
|
| CharacterState::BasicSummon { .. } => {
|
||||||
if energy.get_unchecked().regen_rate != 0.0 {
|
if energy.get_unchecked().regen_rate != 0.0 {
|
||||||
energy.get_mut_unchecked().regen_rate = 0.0
|
energy.get_mut_unchecked().regen_rate = 0.0
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{sys, Server, StateExt};
|
use crate::{client::Client, sys, Server, StateExt};
|
||||||
use common::{
|
use common::{
|
||||||
character::CharacterId,
|
character::CharacterId,
|
||||||
comp::{
|
comp::{
|
||||||
@ -6,15 +6,16 @@ use common::{
|
|||||||
aura::{Aura, AuraKind, AuraTarget},
|
aura::{Aura, AuraKind, AuraTarget},
|
||||||
beam,
|
beam,
|
||||||
buff::{BuffCategory, BuffData, BuffKind, BuffSource},
|
buff::{BuffCategory, BuffData, BuffKind, BuffSource},
|
||||||
group,
|
|
||||||
inventory::loadout::Loadout,
|
inventory::loadout::Loadout,
|
||||||
shockwave, Agent, Alignment, Body, Gravity, Health, HomeChunk, Inventory, Item, ItemDrop,
|
shockwave, Agent, Alignment, Body, Gravity, Health, HomeChunk, Inventory, Item, ItemDrop,
|
||||||
LightEmitter, Object, Ori, Poise, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
|
LightEmitter, Object, Ori, Poise, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
|
||||||
},
|
},
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
rtsim::RtSimEntity,
|
rtsim::RtSimEntity,
|
||||||
|
uid::Uid,
|
||||||
util::Dir,
|
util::Dir,
|
||||||
};
|
};
|
||||||
|
use common_net::{msg::ServerGeneral, sync::WorldSyncExt};
|
||||||
use specs::{Builder, Entity as EcsEntity, WorldExt};
|
use specs::{Builder, Entity as EcsEntity, WorldExt};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use vek::{Rgb, Vec3};
|
use vek::{Rgb, Vec3};
|
||||||
@ -59,15 +60,6 @@ pub fn handle_create_npc(
|
|||||||
home_chunk: Option<HomeChunk>,
|
home_chunk: Option<HomeChunk>,
|
||||||
rtsim_entity: Option<RtSimEntity>,
|
rtsim_entity: Option<RtSimEntity>,
|
||||||
) {
|
) {
|
||||||
let group = match alignment {
|
|
||||||
Alignment::Wild => None,
|
|
||||||
Alignment::Passive => None,
|
|
||||||
Alignment::Enemy => Some(group::ENEMY),
|
|
||||||
Alignment::Npc | Alignment::Tame => Some(group::NPC),
|
|
||||||
// TODO: handle
|
|
||||||
Alignment::Owned(_) => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let inventory = Inventory::new_with_loadout(loadout);
|
let inventory = Inventory::new_with_loadout(loadout);
|
||||||
|
|
||||||
let entity = server
|
let entity = server
|
||||||
@ -76,12 +68,6 @@ pub fn handle_create_npc(
|
|||||||
.with(scale)
|
.with(scale)
|
||||||
.with(alignment);
|
.with(alignment);
|
||||||
|
|
||||||
let entity = if let Some(group) = group {
|
|
||||||
entity.with(group)
|
|
||||||
} else {
|
|
||||||
entity
|
|
||||||
};
|
|
||||||
|
|
||||||
let entity = if let Some(agent) = agent.into() {
|
let entity = if let Some(agent) = agent.into() {
|
||||||
entity.with(agent)
|
entity.with(agent)
|
||||||
} else {
|
} else {
|
||||||
@ -106,7 +92,45 @@ pub fn handle_create_npc(
|
|||||||
entity
|
entity
|
||||||
};
|
};
|
||||||
|
|
||||||
entity.build();
|
let new_entity = entity.build();
|
||||||
|
|
||||||
|
// Add to group system if a pet
|
||||||
|
if let comp::Alignment::Owned(owner_uid) = alignment {
|
||||||
|
let state = server.state();
|
||||||
|
let clients = state.ecs().read_storage::<Client>();
|
||||||
|
let uids = state.ecs().read_storage::<Uid>();
|
||||||
|
let mut group_manager = state.ecs().write_resource::<comp::group::GroupManager>();
|
||||||
|
if let Some(owner) = state.ecs().entity_from_uid(owner_uid.into()) {
|
||||||
|
group_manager.new_pet(
|
||||||
|
new_entity,
|
||||||
|
owner,
|
||||||
|
&mut state.ecs().write_storage(),
|
||||||
|
&state.ecs().entities(),
|
||||||
|
&state.ecs().read_storage(),
|
||||||
|
&uids,
|
||||||
|
&mut |entity, group_change| {
|
||||||
|
clients
|
||||||
|
.get(entity)
|
||||||
|
.and_then(|c| {
|
||||||
|
group_change
|
||||||
|
.try_map(|e| uids.get(e).copied())
|
||||||
|
.map(|g| (g, c))
|
||||||
|
})
|
||||||
|
.map(|(g, c)| {
|
||||||
|
c.send_fallible(ServerGeneral::GroupUpdate(g));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if let Some(group) = match alignment {
|
||||||
|
comp::Alignment::Wild => None,
|
||||||
|
comp::Alignment::Passive => None,
|
||||||
|
comp::Alignment::Enemy => Some(comp::group::ENEMY),
|
||||||
|
comp::Alignment::Npc | comp::Alignment::Tame => Some(comp::group::NPC),
|
||||||
|
comp::Alignment::Owned(_) => unreachable!(),
|
||||||
|
} {
|
||||||
|
let _ = server.state.ecs().write_storage().insert(new_entity, group);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
Loading…
Reference in New Issue
Block a user