feat: added sound events for enemy awareness

This commit is contained in:
Sara 2025-08-04 17:00:23 +02:00
parent 1373656f90
commit 66aede32bd
15 changed files with 234 additions and 16 deletions

View file

@ -1,4 +1,5 @@
#include "player_detector.h"
#include "sound_event_patchboard.h"
String PlayerDetector::sig_awareness_changed{ "awareness_changed" };
@ -6,6 +7,17 @@ void PlayerDetector::_bind_methods() {
ADD_SIGNAL(MethodInfo(sig_awareness_changed, PropertyInfo(Variant::BOOL, "aware")));
}
// check if there is geometry between detector and player
bool PlayerDetector::line_of_sight_exists() const {
PhysicsDirectSpaceState3D::RayParameters params{ this->ray_params };
params.from = get_global_position();
params.to = PlayerBody::get_singleton()->get_global_position();
PhysicsDirectSpaceState3D *space{ get_world_3d()->get_direct_space_state() };
PhysicsDirectSpaceState3D::RayResult result{};
space->intersect_ray(params, result);
return result.collider == nullptr;
}
// Check if the player is in a bounded area in front of the detector and unobscured.
// As all tests are required to pass, we do them in increasing order of complexity, to minimize unneeded resource use.
bool PlayerDetector::check() const {
@ -13,24 +25,18 @@ bool PlayerDetector::check() const {
Vector3 const position{ get_global_position() };
Vector3 const target{ PlayerBody::get_singleton()->get_global_position() + Vector3{ 0.f, 1.5f, 0.f } };
// check if the target is in a view cone
if (forward.dot(target - position) < this->min_dot) {
if (forward.dot(target - position) < this->min_sight_dot) {
return false;
}
// check if the target is in range
if (position.distance_squared_to(target) > this->max_distance * this->max_distance) {
if (position.distance_squared_to(target) > this->max_sight_range * this->max_sight_range) {
return false;
}
// check if the target is obscured
PhysicsDirectSpaceState3D::RayParameters params{ this->ray_params };
params.from = position;
params.to = target;
PhysicsDirectSpaceState3D *space{ get_world_3d()->get_direct_space_state() };
PhysicsDirectSpaceState3D::RayResult result{};
space->intersect_ray(params, result);
return result.collider == nullptr;
return line_of_sight_exists();
}
void PlayerDetector::ready() {
SoundEventPatchboard::get_singleton()->connect(SoundEventPatchboard::sig_sound_triggered, callable_mp(this, &self_type::on_player_sound));
this->ray_params.exclude.insert(PlayerBody::get_singleton()->get_rid());
}
@ -46,6 +52,12 @@ void PlayerDetector::process(double delta) {
}
}
void PlayerDetector::on_player_sound(Vector3 at, float range) {
if (get_global_position().distance_squared_to(at) <= range * range && line_of_sight_exists()) {
set_aware_of_player(true);
}
}
void PlayerDetector::set_aware_of_player(bool value) {
emit_signal(sig_awareness_changed, value);
this->aware_of_player = value;