diff --git a/src/entity_health.cpp b/src/entity_health.cpp index 25c9f0a..99592b8 100644 --- a/src/entity_health.cpp +++ b/src/entity_health.cpp @@ -55,8 +55,9 @@ void EntityHealth::healed_by(int amount, Unit *source) { void EntityHealth::receive_wounds(int incoming_amount, Unit *source) { if(this->is_conscious()) { this->wounds_current -= incoming_amount; - if(this->injury_current <= 0) + if(this->wounds_current <= 0) { this->emit_signal("unconscious", source); + } } } diff --git a/src/unit.cpp b/src/unit.cpp index 00af6f6..505924f 100644 --- a/src/unit.cpp +++ b/src/unit.cpp @@ -16,18 +16,20 @@ void Unit::_bind_methods() { GDSIGNAL("plan_failed"); GDSIGNAL("plan_interrupted"); GDPROPERTY_HINTED(configure_team, gd::Variant::INT, gd::PROPERTY_HINT_ENUM, UnitTeam::get_property_hint()); - GDPROPERTY_HINTED(movement_speed, gd::Variant::FLOAT, gd::PROPERTY_HINT_RANGE, "0.1,5.0"); + GDPROPERTY(movement_speed, gd::Variant::FLOAT); GDFUNCTION(use_weapon); } void Unit::_enter_tree() { this->agent = this->get_node("%NavigationAgent3D"); this->agent->connect("velocity_computed", callable_mp(this, &Unit::on_velocity_computed)); + this->connect("plan_failed", callable_mp(this, &Unit::replan_goal)); this->planner = this->get_node("%Planner"); this->world_state = this->get_node("%ActorWorldState"); this->world_state->connect("attention_changed", callable_mp(this, &Unit::stop_plan)); this->anim_player = this->get_node("%AnimationPlayer"); this->health = this->get_node("%EntityHealth"); + this->health->connect("unconscious", callable_mp(this, &Unit::on_unconscious)); this->health->connect("death", callable_mp(this, &Unit::on_death)); } @@ -46,7 +48,7 @@ void Unit::stop_plan() { this->current_goal.unref(); this->current_plan.clear(); this->destroy_state(); - this->call_deferred("emit_signal", "plan_failed"); + this->emit_signal("plan_failed"); } void Unit::begin_marker_temporary(GoalMarker *marker) { @@ -96,8 +98,10 @@ void Unit::on_unconscious(Unit *damage_source) { void Unit::on_death(Unit *damage_source) { this->destroy_state(); - this->anim_player->stop(); - this->anim_player->play("death"); + if(this->anim_player->get_current_animation() != gd::StringName("death")) { + this->anim_player->stop(); + this->anim_player->play("death"); + } } void Unit::on_velocity_computed(gd::Vector3 vel) { @@ -111,7 +115,7 @@ void Unit::on_velocity_computed(gd::Vector3 vel) { void Unit::destroy_state() { if(this->state == nullptr) return; - if(!this->state->is_queued_for_deletion() && this->state->is_inside_tree()) + if(!this->state->is_queued_for_deletion()) this->state->interrupt_state(); this->state = nullptr; } @@ -125,9 +129,10 @@ void Unit::state_finished() { void Unit::next_action() { // destroy active state if relevant this->destroy_state(); - // cannot perform actions while dead + // cannot perform actions while dead or unconscious if(!this->health->is_conscious()) return; + // no next state available if(this->current_plan.is_empty()) return; goap::Action const *action{this->current_plan.get(0)}; @@ -157,11 +162,11 @@ void Unit::set_goal_and_plan(gd::Ref goal) { this->current_goal = goal; if(goal.is_null()) { this->current_plan.clear(); - } else { - this->current_plan = this->planner->plan_for_goal(goal); - if(this->current_plan.is_empty()) - this->current_goal.unref(); + return; } + this->current_plan = this->planner->plan_for_goal(goal); + if(this->current_plan.is_empty()) + this->current_goal.unref(); } UnitWorldState *Unit::get_world_state() const { @@ -198,7 +203,9 @@ float Unit::get_movement_speed() const { #ifdef DEBUG_ENABLED gd::String Unit::DEBUG_print_debug_info() { - gd::String debug_info{"goal: "}; + gd::String debug_info{}; + debug_info += gd::String("health: ") + gd::vformat("%d", this->get_entity_health()->get_wounds_current()); + debug_info += "\ngoal: "; if(!this->current_goal.is_valid()) { debug_info += "No goal assigned"; } else {