diff --git a/src/rts_states.cpp b/src/rts_states.cpp index 1ac95ce..a955bd1 100644 --- a/src/rts_states.cpp +++ b/src/rts_states.cpp @@ -1,4 +1,6 @@ #include "rts_states.hpp" +#include "unit.hpp" +#include "utility_lock.hpp" #include "utils/util_functions.hpp" #include #include @@ -8,7 +10,7 @@ void MoveTo::_bind_methods() {} void MoveTo::_ready() { this->parent_unit = Object::cast_to(this->get_parent()); - this->agent = this->get_node("../NavigationAgent3D"); + this->agent = this->parent_unit->get_node("%NavigationAgent3D"); if(this->target_node == nullptr) { this->end_state(); gd::UtilityFunctions::push_warning("failed to start MoveTo state due to missing target"); @@ -73,16 +75,36 @@ double MoveTo::get_repath_interval() const { void Activate::_bind_methods() {} void Activate::_ready() { - this->anim = this->get_parent()->get_node("%AnimationPlayer"); - if(!this->anim->has_animation(this->animation)) + this->parent_unit = gd::Object::cast_to(this->get_parent()); + if(this->parent_unit == nullptr) { + gd::UtilityFunctions::push_error(this->get_path(), " parent is not a Unit"); this->end_state(); - else this->anim->play(this->animation); + return; + } + // start activating the lock + this->lock->begin_activate(this->using_item, this->parent_unit); + // play activate animation + this->anim = this->parent_unit->get_node("%AnimationPlayer"); + if(!this->anim->has_animation(this->animation)) { + this->end_state(); + return; + } + this->anim->play(this->animation); } void Activate::_process(double) { bool const animation_finished{!this->anim->is_playing() || this->anim->get_current_animation() != this->animation}; - if(this->is_action_done_interrupt() || animation_finished) + if(animation_finished) { + this->lock->finish_activate(this->using_item, this->parent_unit); this->end_state(); + } else if(this->is_action_done_interrupt()) { + this->end_state(); + } +} + +void Activate::_end_state() { + if(!this->is_action_done()) + this->lock->interrupt_activate(); } void Animate::_bind_methods() {} diff --git a/src/rts_states.hpp b/src/rts_states.hpp index 48049f6..fd193d3 100644 --- a/src/rts_states.hpp +++ b/src/rts_states.hpp @@ -6,6 +6,8 @@ #include #include +class UtilityLock; + /*! Uses navigation to chase the desired target node. */ class MoveTo : public goap::State { @@ -36,10 +38,13 @@ class Activate : public goap::State { public: virtual void _ready() override; virtual void _process(double) override; - gd::Node3D *target_node{nullptr}; + virtual void _end_state() override; + UtilityLock *lock{nullptr}; gd::String animation{}; private: + Item const *using_item{nullptr}; gd::AnimationPlayer *anim{nullptr}; + Unit *parent_unit{nullptr}; }; class Animate : public goap::State { diff --git a/src/unit_world_state.cpp b/src/unit_world_state.cpp index 7ef2b83..9cf7ab6 100644 --- a/src/unit_world_state.cpp +++ b/src/unit_world_state.cpp @@ -1,6 +1,7 @@ #include "unit_world_state.hpp" #include "entity_health.hpp" #include "unit.hpp" +#include "utility_lock.hpp" #include "utils/godot_macros.hpp" #include "utils/util_functions.hpp" #include @@ -19,6 +20,7 @@ void UnitWorldState::_bind_methods() { GDFUNCTION(get_has_target); GDFUNCTION(get_target_node); GDFUNCTION(get_is_target_enemy); + GDFUNCTION(get_is_target_activated); GDFUNCTION(get_is_in_range); GDFUNCTION(get_is_health_safe); GDFUNCTION(get_parent_global_position); @@ -35,9 +37,8 @@ void UnitWorldState::_enter_tree() { gd::Variant UnitWorldState::get_world_property(gd::String property) { if(this->cache.has(property)) { CachedWorldProperty prop{this->cache[property]}; - if(prop.auto_invalidate_time > utils::time_seconds()) { + if(prop.auto_invalidate_time > utils::time_seconds()) return prop.value; - } } return ActorWorldState::get_world_property(property); } @@ -57,7 +58,6 @@ bool UnitWorldState::get_can_see_node(gd::Node3D *node) const { gd::Node3D *vision_target{node->get_node("VisionTarget")}; gd::Transform3D const eyes{this->eye_location->get_global_transform()}; gd::Vector3 const target_position{vision_target ? vision_target->get_global_position() : node->get_global_position()}; - // construct list for ignored objects including target node and parent unit gd::TypedArray ignore_list{this->parent_unit->get_rid()}; // ignore target if it is a collision object that might obstruct it's own collision test @@ -105,6 +105,11 @@ bool UnitWorldState::get_is_unit_enemy(Unit *unit) const { && unit->get_team() != this->parent_unit->get_team(); } +bool UnitWorldState::get_is_target_activated() const { + UtilityLock *lock{gd::Object::cast_to(this->target_node)}; + return lock != nullptr && lock->get_activation_state() == UtilityLock::ActivationState::Done; +} + bool UnitWorldState::get_is_in_range() const { return this->target_node != nullptr && this->target_node->get_global_position().distance_squared_to(this->parent_unit->get_global_position()) <= 2.f * 2.f; diff --git a/src/unit_world_state.hpp b/src/unit_world_state.hpp index 3009b10..c9f82dc 100644 --- a/src/unit_world_state.hpp +++ b/src/unit_world_state.hpp @@ -32,6 +32,7 @@ public: bool get_is_target_unit() const; bool get_is_target_enemy() const; bool get_is_unit_enemy(Unit *unit) const; + bool get_is_target_activated() const; virtual bool get_is_in_range() const; bool get_is_health_safe() const; gd::Vector3 get_parent_global_position() const;