mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
(Buggy) Sounds are investigated; choose_target is used for guards to target villager attackers
Bug: The additional code in choose_target does not seem to function.
This commit is contained in:
parent
476be41b9d
commit
c2239daaa0
@ -272,23 +272,15 @@ pub struct Sound {
|
|||||||
pub pos: Vec3<f32>,
|
pub pos: Vec3<f32>,
|
||||||
pub vol: f32,
|
pub vol: f32,
|
||||||
pub time: f64,
|
pub time: f64,
|
||||||
pub owner: Option<EcsEntity>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sound {
|
impl Sound {
|
||||||
pub fn new(
|
pub fn new(kind: SoundKind, pos: Vec3<f32>, vol: f32, time: f64) -> Self {
|
||||||
kind: SoundKind,
|
|
||||||
pos: Vec3<f32>,
|
|
||||||
vol: f32,
|
|
||||||
time: f64,
|
|
||||||
owner: Option<EcsEntity>,
|
|
||||||
) -> Self {
|
|
||||||
Sound {
|
Sound {
|
||||||
kind,
|
kind,
|
||||||
pos,
|
pos,
|
||||||
vol,
|
vol,
|
||||||
time,
|
time,
|
||||||
owner,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
if rng.gen_bool(0.005) {
|
if rng.gen_bool(0.005) {
|
||||||
server_events.push(ServerEvent::Sound {
|
server_events.push(ServerEvent::Sound {
|
||||||
sound: Sound::new(SoundKind::Beam, pos.0, 7.0, time, beam_owner),
|
sound: Sound::new(SoundKind::Beam, pos.0, 7.0, time),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,6 @@ impl<'a> System<'a> for Sys {
|
|||||||
pos.0 + Vec3::unit_z() * body.eye_height(),
|
pos.0 + Vec3::unit_z() * body.eye_height(),
|
||||||
8.0, // TODO: Come up with a better way of determining this
|
8.0, // TODO: Come up with a better way of determining this
|
||||||
1.0,
|
1.0,
|
||||||
Some(entity),
|
|
||||||
);
|
);
|
||||||
server_emitter.emit(ServerEvent::Sound { sound });
|
server_emitter.emit(ServerEvent::Sound { sound });
|
||||||
}
|
}
|
||||||
|
@ -70,13 +70,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
server_emitter.emit(ServerEvent::Sound {
|
server_emitter.emit(ServerEvent::Sound {
|
||||||
sound: Sound::new(
|
sound: Sound::new(SoundKind::Melee, pos.0, 3.0, read_data.time.0),
|
||||||
SoundKind::Melee,
|
|
||||||
pos.0,
|
|
||||||
3.0,
|
|
||||||
read_data.time.0,
|
|
||||||
Some(attacker),
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
melee_attack.applied = true;
|
melee_attack.applied = true;
|
||||||
|
|
||||||
|
@ -79,13 +79,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
if physics.on_surface().is_none() && rng.gen_bool(0.05) {
|
if physics.on_surface().is_none() && rng.gen_bool(0.05) {
|
||||||
server_emitter.emit(ServerEvent::Sound {
|
server_emitter.emit(ServerEvent::Sound {
|
||||||
sound: Sound::new(
|
sound: Sound::new(SoundKind::Projectile, pos.0, 2.0, read_data.time.0),
|
||||||
SoundKind::Projectile,
|
|
||||||
pos.0,
|
|
||||||
2.0,
|
|
||||||
read_data.time.0,
|
|
||||||
projectile_owner,
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
if rng.gen_bool(0.05) {
|
if rng.gen_bool(0.05) {
|
||||||
server_emitter.emit(ServerEvent::Sound {
|
server_emitter.emit(ServerEvent::Sound {
|
||||||
sound: Sound::new(SoundKind::Shockwave, pos.0, 16.0, time, shockwave_owner),
|
sound: Sound::new(SoundKind::Shockwave, pos.0, 16.0, time),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,13 +699,7 @@ pub fn handle_explosion(server: &Server, pos: Vec3<f32>, explosion: Explosion, o
|
|||||||
|
|
||||||
let explosion_volume = 2.5 * explosion.radius;
|
let explosion_volume = 2.5 * explosion.radius;
|
||||||
server_eventbus.emit_now(ServerEvent::Sound {
|
server_eventbus.emit_now(ServerEvent::Sound {
|
||||||
sound: Sound::new(
|
sound: Sound::new(SoundKind::Explosion, pos, explosion_volume, time.0),
|
||||||
SoundKind::Explosion,
|
|
||||||
pos,
|
|
||||||
explosion_volume,
|
|
||||||
time.0,
|
|
||||||
owner_entity,
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add an outcome
|
// Add an outcome
|
||||||
|
@ -400,8 +400,8 @@ impl<'a> System<'a> for Sys {
|
|||||||
&read_data.terrain,
|
&read_data.terrain,
|
||||||
tgt_pos,
|
tgt_pos,
|
||||||
);
|
);
|
||||||
} else if target_was_attacked(target, &read_data) {
|
} else if entity_was_attacked(target, &read_data) {
|
||||||
data.attack_targets_attacker(
|
data.attack_agents_attacker(
|
||||||
agent, &read_data, controller,
|
agent, &read_data, controller,
|
||||||
);
|
);
|
||||||
// Follow owner if too far away and not
|
// Follow owner if too far away and not
|
||||||
@ -445,15 +445,13 @@ impl<'a> System<'a> for Sys {
|
|||||||
// have a health component
|
// have a health component
|
||||||
match health {
|
match health {
|
||||||
Some(health) if health.last_change.0 < DAMAGE_MEMORY_DURATION => {
|
Some(health) if health.last_change.0 < DAMAGE_MEMORY_DURATION => {
|
||||||
|
// TODO: Can most of this match be replaced by the function
|
||||||
|
// `attack_agents_attacker`?
|
||||||
if let comp::HealthSource::Damage { by: Some(by), .. } =
|
if let comp::HealthSource::Damage { by: Some(by), .. } =
|
||||||
health.last_change.1.cause
|
health.last_change.1.cause
|
||||||
{
|
{
|
||||||
if let Some(attacker) =
|
if let Some(attacker) = get_entity_by_id(by.id(), &read_data) {
|
||||||
read_data.uid_allocator.retrieve_entity_internal(by.id())
|
|
||||||
{
|
|
||||||
if let Some(tgt_pos) = read_data.positions.get(attacker) {
|
if let Some(tgt_pos) = read_data.positions.get(attacker) {
|
||||||
// If the target is dead or in a safezone, remove the
|
|
||||||
// target and idle.
|
|
||||||
if should_stop_attacking(attacker, &read_data) {
|
if should_stop_attacking(attacker, &read_data) {
|
||||||
agent.target = None;
|
agent.target = None;
|
||||||
data.idle_tree(
|
data.idle_tree(
|
||||||
@ -485,17 +483,15 @@ impl<'a> System<'a> for Sys {
|
|||||||
.rtsim_entity
|
.rtsim_entity
|
||||||
.and_then(|_| read_data.stats.get(attacker))
|
.and_then(|_| read_data.stats.get(attacker))
|
||||||
{
|
{
|
||||||
agent.rtsim_controller.events.push(
|
if data.rtsim_entity.is_some() {
|
||||||
RtSimEvent::AddMemory(Memory {
|
remember_fight(
|
||||||
item: MemoryItem::CharacterFight {
|
agent,
|
||||||
name: tgt_stats.name.clone(),
|
tgt_stats.name.clone(),
|
||||||
},
|
read_data.time.0,
|
||||||
time_to_forget: read_data.time.0
|
|
||||||
+ 300.0,
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
agent.target = None;
|
agent.target = None;
|
||||||
data.idle_tree(
|
data.idle_tree(
|
||||||
@ -561,7 +557,7 @@ impl<'a> AgentData<'a> {
|
|||||||
// Set owner if no target
|
// Set owner if no target
|
||||||
if agent.target.is_none() && thread_rng().gen_bool(0.1) {
|
if agent.target.is_none() && thread_rng().gen_bool(0.1) {
|
||||||
if let Some(Alignment::Owned(owner)) = self.alignment {
|
if let Some(Alignment::Owned(owner)) = self.alignment {
|
||||||
if let Some(owner) = read_data.uid_allocator.retrieve_entity_internal(owner.id()) {
|
if let Some(owner) = get_entity_by_id(owner.id(), read_data) {
|
||||||
agent.target = build_target(owner, false, read_data.time.0);
|
agent.target = build_target(owner, false, read_data.time.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -947,8 +943,7 @@ impl<'a> AgentData<'a> {
|
|||||||
match msg {
|
match msg {
|
||||||
Some(AgentEvent::Talk(by, subject)) => {
|
Some(AgentEvent::Talk(by, subject)) => {
|
||||||
if can_speak(agent) {
|
if can_speak(agent) {
|
||||||
if let Some(target) = read_data.uid_allocator.retrieve_entity_internal(by.id())
|
if let Some(target) = get_entity_by_id(by.id(), read_data) {
|
||||||
{
|
|
||||||
agent.target = build_target(target, false, read_data.time.0);
|
agent.target = build_target(target, false, read_data.time.0);
|
||||||
|
|
||||||
if self.look_toward(controller, read_data, &target) {
|
if self.look_toward(controller, read_data, &target) {
|
||||||
@ -1135,9 +1130,7 @@ impl<'a> AgentData<'a> {
|
|||||||
// stand still and looking towards the trading player
|
// stand still and looking towards the trading player
|
||||||
controller.actions.push(ControlAction::Stand);
|
controller.actions.push(ControlAction::Stand);
|
||||||
controller.actions.push(ControlAction::Talk);
|
controller.actions.push(ControlAction::Talk);
|
||||||
if let Some(target) =
|
if let Some(target) = get_entity_by_id(with.id(), read_data) {
|
||||||
read_data.uid_allocator.retrieve_entity_internal(with.id())
|
|
||||||
{
|
|
||||||
agent.target = build_target(target, false, read_data.time.0);
|
agent.target = build_target(target, false, read_data.time.0);
|
||||||
}
|
}
|
||||||
controller
|
controller
|
||||||
@ -1163,9 +1156,7 @@ impl<'a> AgentData<'a> {
|
|||||||
},
|
},
|
||||||
Some(AgentEvent::TradeAccepted(with)) => {
|
Some(AgentEvent::TradeAccepted(with)) => {
|
||||||
if !agent.behavior.is(BehaviorState::TRADING) {
|
if !agent.behavior.is(BehaviorState::TRADING) {
|
||||||
if let Some(target) =
|
if let Some(target) = get_entity_by_id(with.id(), read_data) {
|
||||||
read_data.uid_allocator.retrieve_entity_internal(with.id())
|
|
||||||
{
|
|
||||||
agent.target = build_target(target, false, read_data.time.0);
|
agent.target = build_target(target, false, read_data.time.0);
|
||||||
}
|
}
|
||||||
agent.behavior.set(BehaviorState::TRADING);
|
agent.behavior.set(BehaviorState::TRADING);
|
||||||
@ -1384,6 +1375,17 @@ impl<'a> AgentData<'a> {
|
|||||||
agent.action_state.timer = 0.0;
|
agent.action_state.timer = 0.0;
|
||||||
|
|
||||||
// Search area
|
// Search area
|
||||||
|
// TODO: REMOVE THIS BEFORE MERGE
|
||||||
|
if let Some(agent_stats) = read_data.stats.get(*self.entity) {
|
||||||
|
let is_village_guard = agent_stats.name == *"Guard".to_string();
|
||||||
|
if is_village_guard {
|
||||||
|
self.chat_general(
|
||||||
|
"I am a guard, searching for target".to_string(),
|
||||||
|
event_emitter,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let target = self.cached_spatial_grid.0
|
let target = self.cached_spatial_grid.0
|
||||||
.in_circle_aabr(self.pos.0.xy(), SEARCH_DIST)
|
.in_circle_aabr(self.pos.0.xy(), SEARCH_DIST)
|
||||||
.filter_map(|entity| {
|
.filter_map(|entity| {
|
||||||
@ -1404,11 +1406,7 @@ impl<'a> AgentData<'a> {
|
|||||||
search_dist *= SNEAK_COEFFICIENT;
|
search_dist *= SNEAK_COEFFICIENT;
|
||||||
listen_dist *= SNEAK_COEFFICIENT;
|
listen_dist *= SNEAK_COEFFICIENT;
|
||||||
}
|
}
|
||||||
((e_pos.0.distance_squared(self.pos.0) < search_dist.powi(2) &&
|
((self.within_range_of(search_dist, e_pos.0) && self.within_view_angle(e_pos.0, controller)) || self.within_range_of(listen_dist, e_pos.0)) // TODO implement proper sound system for agents
|
||||||
// Within our view
|
|
||||||
(e_pos.0 - self.pos.0).try_normalized().map(|v| v.dot(*controller.inputs.look_dir) > 0.15).unwrap_or(true))
|
|
||||||
// Within listen distance
|
|
||||||
|| e_pos.0.distance_squared(self.pos.0) < listen_dist.powi(2)) // TODO implement proper sound system for agents
|
|
||||||
&& e != self.entity
|
&& e != self.entity
|
||||||
&& !e_health.is_dead
|
&& !e_health.is_dead
|
||||||
&& !invulnerability_is_in_buffs(read_data.buffs.get(*e))
|
&& !invulnerability_is_in_buffs(read_data.buffs.get(*e))
|
||||||
@ -1416,12 +1414,7 @@ impl<'a> AgentData<'a> {
|
|||||||
if let Some(rtsim_entity) = &self.rtsim_entity {
|
if let Some(rtsim_entity) = &self.rtsim_entity {
|
||||||
if can_speak(agent) {
|
if can_speak(agent) {
|
||||||
if rtsim_entity.brain.remembers_fight_with_character(&e_stats.name) {
|
if rtsim_entity.brain.remembers_fight_with_character(&e_stats.name) {
|
||||||
agent.rtsim_controller.events.push(
|
remember_fight(agent, e_stats.name.clone(), read_data.time.0);
|
||||||
RtSimEvent::AddMemory(Memory {
|
|
||||||
item: MemoryItem::CharacterFight { name: e_stats.name.clone() },
|
|
||||||
time_to_forget: read_data.time.0 + 300.0,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
let msg = format!("{}! How dare you cross me again!", e_stats.name.clone());
|
let msg = format!("{}! How dare you cross me again!", e_stats.name.clone());
|
||||||
self.chat_general(msg, event_emitter);
|
self.chat_general(msg, event_emitter);
|
||||||
true
|
true
|
||||||
@ -1440,12 +1433,7 @@ impl<'a> AgentData<'a> {
|
|||||||
if matches!(alignment, Alignment::Npc) && e_inventory.equipped_items().filter(|item| item.tags().contains(&ItemTag::Cultist)).count() > 2 {
|
if matches!(alignment, Alignment::Npc) && e_inventory.equipped_items().filter(|item| item.tags().contains(&ItemTag::Cultist)).count() > 2 {
|
||||||
if can_speak(agent) {
|
if can_speak(agent) {
|
||||||
if self.rtsim_entity.is_some() {
|
if self.rtsim_entity.is_some() {
|
||||||
agent.rtsim_controller.events.push(
|
remember_fight(agent, e_stats.name.clone(), read_data.time.0);
|
||||||
RtSimEvent::AddMemory(Memory {
|
|
||||||
item: MemoryItem::CharacterFight { name: e_stats.name.clone() },
|
|
||||||
time_to_forget: read_data.time.0 + 300.0,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
let msg = "npc.speech.villager_cultist_alarm".to_string();
|
let msg = "npc.speech.villager_cultist_alarm".to_string();
|
||||||
self.chat_general(msg, event_emitter);
|
self.chat_general(msg, event_emitter);
|
||||||
@ -1459,14 +1447,57 @@ impl<'a> AgentData<'a> {
|
|||||||
))
|
))
|
||||||
|
|
||||||
})
|
})
|
||||||
|
.filter_map(|(e, e_pos, e_health, _e_stats, _e_inventory, e_alignment, _char_state)| {
|
||||||
|
// TODO: REMOVE THIS BEFORE MERGE
|
||||||
|
if let Some(agent_stats) = read_data.stats.get(*self.entity) {
|
||||||
|
let is_village_guard = agent_stats.name == *"Guard".to_string();
|
||||||
|
if is_village_guard {
|
||||||
|
println!("{}", "I am a guard, made it to the filter_map".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if entity_was_attacked(e, &read_data) {
|
||||||
|
if let Some(alignment) = e_alignment {
|
||||||
|
let is_npc = matches!(alignment, Alignment::Npc);
|
||||||
|
|
||||||
|
if is_npc {
|
||||||
|
if let comp::HealthSource::Damage { by: Some(by), .. } = e_health.last_change.1.cause {
|
||||||
|
get_entity_by_id(by.id(), read_data)
|
||||||
|
.and_then(|attacker| {
|
||||||
|
println!("attacker data: {:?}", Some(attacker).zip(read_data.positions.get(attacker)));
|
||||||
|
Some(attacker).zip(read_data.positions.get(attacker))
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Some(e).zip(Some(e_pos))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Some(e).zip(Some(e_pos))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Some(e).zip(Some(e_pos))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Some(e).zip(Some(e_pos))
|
||||||
|
}
|
||||||
|
})
|
||||||
// Can we even see them?
|
// Can we even see them?
|
||||||
.filter(|(_, e_pos, _, _, _, _, _)| read_data.terrain
|
.filter(|(_e, e_pos)| {
|
||||||
|
// TODO: REMOVE THIS BEFORE MERGE
|
||||||
|
if let Some(agent_stats) = read_data.stats.get(*self.entity) {
|
||||||
|
let is_village_guard = agent_stats.name == *"Guard".to_string();
|
||||||
|
if is_village_guard {
|
||||||
|
println!("looking at: {:?} at {:?}", _e, e_pos);
|
||||||
|
println!("can we see them: {:?}", read_data.terrain.ray(self.pos.0 + Vec3::unit_z(), e_pos.0 + Vec3::unit_z()).until(Block::is_opaque).cast().0 >= e_pos.0.distance(self.pos.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
read_data.terrain
|
||||||
.ray(self.pos.0 + Vec3::unit_z(), e_pos.0 + Vec3::unit_z())
|
.ray(self.pos.0 + Vec3::unit_z(), e_pos.0 + Vec3::unit_z())
|
||||||
.until(Block::is_opaque)
|
.until(Block::is_opaque)
|
||||||
.cast()
|
.cast()
|
||||||
.0 >= e_pos.0.distance(self.pos.0))
|
.0 >= e_pos.0.distance(self.pos.0)
|
||||||
.min_by_key(|(_, e_pos, _, _, _, _, _)| (e_pos.0.distance_squared(self.pos.0) * 100.0) as i32) // TODO choose target by more than just distance
|
})
|
||||||
.map(|(e, _, _, _, _, _, _)| e);
|
.min_by_key(|(_e, e_pos)| (e_pos.0.distance_squared(self.pos.0) * 100.0) as i32) // TODO choose target by more than just distance
|
||||||
|
.map(|(e, _e_pos)| e);
|
||||||
|
|
||||||
if agent.target.is_none() && target.is_some() {
|
if agent.target.is_none() && target.is_some() {
|
||||||
controller.push_event(ControlEvent::Utterance(UtteranceKind::Angry));
|
controller.push_event(ControlEvent::Utterance(UtteranceKind::Angry));
|
||||||
@ -1477,6 +1508,14 @@ impl<'a> AgentData<'a> {
|
|||||||
hostile: true,
|
hostile: true,
|
||||||
selected_at: read_data.time.0,
|
selected_at: read_data.time.0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: REMOVE THIS BEFORE MERGE
|
||||||
|
if let Some(agent_stats) = read_data.stats.get(*self.entity) {
|
||||||
|
let is_village_guard = agent_stats.name == *"Guard".to_string();
|
||||||
|
if is_village_guard {
|
||||||
|
println!("guard's target is: {:?}", agent.target);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attack(
|
fn attack(
|
||||||
@ -3845,12 +3884,7 @@ impl<'a> AgentData<'a> {
|
|||||||
let sound_is_villager_alarm = matches!(sound.kind, SoundKind::VillagerAlarm);
|
let sound_is_villager_alarm = matches!(sound.kind, SoundKind::VillagerAlarm);
|
||||||
|
|
||||||
if sound_is_villager_alarm {
|
if sound_is_villager_alarm {
|
||||||
if let Some(alarmist) = sound.owner {
|
|
||||||
agent.target = build_target(alarmist, true, read_data.time.0);
|
|
||||||
self.attack_targets_attacker(agent, &read_data, controller);
|
|
||||||
} else {
|
|
||||||
self.follow(agent, controller, &read_data.terrain, &sound_pos);
|
self.follow(agent, controller, &read_data.terrain, &sound_pos);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
self.idle(agent, controller, &read_data);
|
self.idle(agent, controller, &read_data);
|
||||||
}
|
}
|
||||||
@ -3862,7 +3896,7 @@ impl<'a> AgentData<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn attack_targets_attacker(
|
fn attack_agents_attacker(
|
||||||
&self,
|
&self,
|
||||||
agent: &mut Agent,
|
agent: &mut Agent,
|
||||||
read_data: &ReadData,
|
read_data: &ReadData,
|
||||||
@ -3873,9 +3907,7 @@ impl<'a> AgentData<'a> {
|
|||||||
if let comp::HealthSource::Damage { by: Some(by), .. } =
|
if let comp::HealthSource::Damage { by: Some(by), .. } =
|
||||||
tgt_health.last_change.1.cause
|
tgt_health.last_change.1.cause
|
||||||
{
|
{
|
||||||
if let Some(attacker) =
|
if let Some(attacker) = get_entity_by_id(by.id(), read_data) {
|
||||||
read_data.uid_allocator.retrieve_entity_internal(by.id())
|
|
||||||
{
|
|
||||||
if agent.target.is_none() {
|
if agent.target.is_none() {
|
||||||
controller.push_event(ControlEvent::Utterance(UtteranceKind::Angry));
|
controller.push_event(ControlEvent::Utterance(UtteranceKind::Angry));
|
||||||
}
|
}
|
||||||
@ -3976,15 +4008,20 @@ impl<'a> AgentData<'a> {
|
|||||||
|
|
||||||
fn emit_villager_alarm(&self, time: f64, event_emitter: &mut Emitter<'_, ServerEvent>) {
|
fn emit_villager_alarm(&self, time: f64, event_emitter: &mut Emitter<'_, ServerEvent>) {
|
||||||
event_emitter.emit(ServerEvent::Sound {
|
event_emitter.emit(ServerEvent::Sound {
|
||||||
sound: Sound::new(
|
sound: Sound::new(SoundKind::VillagerAlarm, self.pos.0, 100.0, time),
|
||||||
SoundKind::VillagerAlarm,
|
|
||||||
self.pos.0,
|
|
||||||
100.0,
|
|
||||||
time,
|
|
||||||
Some(*self.entity),
|
|
||||||
),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn within_view_angle(&self, tgt_pos: Vec3<f32>, controller: &Controller) -> bool {
|
||||||
|
(tgt_pos - self.pos.0)
|
||||||
|
.try_normalized()
|
||||||
|
.map(|v| v.dot(*controller.inputs.look_dir) > 0.15)
|
||||||
|
.unwrap_or(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn within_range_of(&self, range: f32, their_pos: Vec3<f32>) -> bool {
|
||||||
|
their_pos.distance_squared(self.pos.0) < range.powi(2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_see_tgt(terrain: &TerrainGrid, pos: &Pos, tgt_pos: &Pos, dist_sqrd: f32) -> bool {
|
fn can_see_tgt(terrain: &TerrainGrid, pos: &Pos, tgt_pos: &Pos, dist_sqrd: f32) -> bool {
|
||||||
@ -4017,10 +4054,7 @@ fn try_owner_alignment<'a>(
|
|||||||
read_data: &'a ReadData,
|
read_data: &'a ReadData,
|
||||||
) -> Option<&'a Alignment> {
|
) -> Option<&'a Alignment> {
|
||||||
if let Some(Alignment::Owned(owner_uid)) = alignment {
|
if let Some(Alignment::Owned(owner_uid)) = alignment {
|
||||||
if let Some(owner) = read_data
|
if let Some(owner) = get_entity_by_id(owner_uid.id(), read_data) {
|
||||||
.uid_allocator
|
|
||||||
.retrieve_entity_internal(owner_uid.id())
|
|
||||||
{
|
|
||||||
return read_data.alignments.get(owner);
|
return read_data.alignments.get(owner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4079,9 +4113,9 @@ fn decrement_awareness(agent: &mut Agent) {
|
|||||||
agent.awareness -= decrement;
|
agent.awareness -= decrement;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn target_was_attacked(target: EcsEntity, read_data: &ReadData) -> bool {
|
fn entity_was_attacked(entity: EcsEntity, read_data: &ReadData) -> bool {
|
||||||
if let Some(tgt_health) = read_data.healths.get(target) {
|
if let Some(entity_health) = read_data.healths.get(entity) {
|
||||||
tgt_health.last_change.0 < 5.0 && tgt_health.last_change.1.amount < 0
|
entity_health.last_change.0 < 5.0 && entity_health.last_change.1.amount < 0
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -4108,3 +4142,17 @@ fn build_target_data<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn can_speak(agent: &Agent) -> bool { agent.behavior.can(BehaviorCapability::SPEAK) }
|
fn can_speak(agent: &Agent) -> bool { agent.behavior.can(BehaviorCapability::SPEAK) }
|
||||||
|
|
||||||
|
fn remember_fight(agent: &mut Agent, name: String, time: f64) {
|
||||||
|
agent
|
||||||
|
.rtsim_controller
|
||||||
|
.events
|
||||||
|
.push(RtSimEvent::AddMemory(Memory {
|
||||||
|
item: MemoryItem::CharacterFight { name },
|
||||||
|
time_to_forget: time + 300.0,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_entity_by_id(id: u64, read_data: &ReadData) -> Option<EcsEntity> {
|
||||||
|
read_data.uid_allocator.retrieve_entity_internal(id)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user