diff --git a/src/rts_actions.cpp b/src/rts_actions.cpp index c9a2658..f3e2537 100644 --- a/src/rts_actions.cpp +++ b/src/rts_actions.cpp @@ -17,7 +17,7 @@ MoveToTarget::MoveToTarget() goap::State *MoveToTarget::get_apply_state(goap::ActorWorldState *context) const { gd::Node3D *target{gd::Object::cast_to(context->get_world_property("target_node"))}; if(target == nullptr) { - gd::UtilityFunctions::push_warning("Failed to get target node of action ", get_static_class()); + gd::UtilityFunctions::push_warning("Failed to get target node of ", context->get_path()); return nullptr; } else { MoveTo *state{this->create_state()}; @@ -97,34 +97,32 @@ TakeCover::TakeCover() bool TakeCover::procedural_is_possible(goap::ActorWorldState *context) const { // positions of the context and the target - gd::Vector3 const global_position{context->get_world_property("parent_global_position")}; + gd::Vector3 const context_position{context->get_world_property("parent_global_position")}; gd::Vector3 const target_position{context->get_world_property("target_global_position")}; // if there is no available navigation room, it is not possible to find a cover marker - NavRoom *room{NavRoom::get_closest_room(global_position)}; + NavRoom *room{NavRoom::get_closest_room(context_position)}; if(room == nullptr) return false; // immediately return true if there is at least one marker that counts as cover from the target for(NavMarker *marker : room->get_markers()) - if(TakeCover::is_marker_cover_from(marker, target_position)) + if(TakeCover::is_marker_cover_from(marker, target_position, context_position)) return true; return false; } goap::State *TakeCover::get_apply_state(goap::ActorWorldState *context) const { // positions of the context and the target to hide from - gd::Vector3 const global_position{context->get_world_property("parent_global_position")}; + gd::Vector3 const context_position{context->get_world_property("parent_global_position")}; gd::Vector3 const target_position{context->get_world_property("target_global_position")}; // find the room this entity is located in - NavRoom *room{NavRoom::get_closest_room(global_position)}; + NavRoom *room{NavRoom::get_closest_room(context_position)}; if(room == nullptr) return nullptr; NavMarker *best_marker{nullptr}; // marker with the best score found so far - float best_score{0.f}; // best score found so far + float best_score{0.f}; // best score found so far, starts at zero because negative values should not be considered for(NavMarker *marker : room->get_markers()) { - gd::Vector3 const marker_position{marker->get_global_position()}; // position of the marker being considered - float const score{(marker_position.distance_squared_to(target_position) * 1.2f) // score is a comparison between distances to the target and context - - (marker_position.distance_squared_to(global_position) * 0.8f)}; - if(score > best_score && TakeCover::is_marker_cover_from(marker, target_position)) { + float const score{this->score_cover_marker(marker, target_position, context_position)}; + if(score > best_score) { best_score = score; best_marker = marker; } @@ -138,9 +136,22 @@ goap::State *TakeCover::get_apply_state(goap::ActorWorldState *context) const { return state; } -bool TakeCover::is_marker_cover_from(NavMarker *marker, gd::Vector3 const &target) { +bool TakeCover::is_marker_cover_from(NavMarker *marker, gd::Vector3 const &target_position, gd::Vector3 const &context_position) { + gd::Vector3 const marker_position{marker->get_global_position()}; + float const distance_to_target{target_position.distance_to(context_position)}; return marker->get_marker_type() == MarkerType::Cover - && marker->get_global_basis() - .get_column(2) - .dot(marker->get_global_position() - target) < -2.f; + && marker->get_global_basis().get_column(2).dot(marker_position - target_position) < -2.f + && context_position.distance_to(marker_position) < (distance_to_target * 2.f); } + +float TakeCover::score_cover_marker(class NavMarker* marker, const gd::Vector3& target_position, const gd::Vector3& context_position) const { + if(!TakeCover::is_marker_cover_from(marker, target_position, context_position)) + return 0.f; + gd::Vector3 const marker_position{marker->get_global_position()}; // position of the marker being considered + float const target_distance{marker_position.distance_to(target_position)}; + float const context_distance{marker_position.distance_to(context_position)}; + // score is a weighted comparison between distances to the target and context + // marker distance from context grows faster than marker distance from target + return (target_distance) - (context_distance); +} + diff --git a/src/rts_actions.hpp b/src/rts_actions.hpp index fcaf321..e29a219 100644 --- a/src/rts_actions.hpp +++ b/src/rts_actions.hpp @@ -53,7 +53,8 @@ public: virtual bool procedural_is_possible(goap::ActorWorldState *context) const override; virtual goap::State *get_apply_state(goap::ActorWorldState *context) const override; private: - static bool is_marker_cover_from(class NavMarker *marker, gd::Vector3 const &target); + static bool is_marker_cover_from(class NavMarker *marker, gd::Vector3 const &target_position, gd::Vector3 const &context_position); + float score_cover_marker(class NavMarker *marker, gd::Vector3 const &target_position, gd::Vector3 const &context_position) const; }; #endif // !RTS_ACTIONS_HPP