feat: improved take cover action node selection
This commit is contained in:
parent
2c21845991
commit
dc60937660
|
@ -17,7 +17,7 @@ MoveToTarget::MoveToTarget()
|
|||
goap::State *MoveToTarget::get_apply_state(goap::ActorWorldState *context) const {
|
||||
gd::Node3D *target{gd::Object::cast_to<gd::Node3D>(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<MoveTo>()};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue