commit
5621b433c9
|
@ -16,23 +16,39 @@ void BTRunLimit::set_run_limit(int p_value) {
|
|||
emit_changed();
|
||||
}
|
||||
|
||||
void BTRunLimit::set_count_policy(CountPolicy p_policy) {
|
||||
count_policy = p_policy;
|
||||
emit_changed();
|
||||
}
|
||||
|
||||
String BTRunLimit::_generate_name() {
|
||||
return vformat("RunLimit x%d", run_limit);
|
||||
}
|
||||
|
||||
BT::Status BTRunLimit::_tick(double p_delta) {
|
||||
ERR_FAIL_COND_V_MSG(get_child_count() == 0, FAILURE, "BT decorator has no child.");
|
||||
if (get_child(0)->get_status() != RUNNING) {
|
||||
if (num_runs >= run_limit) {
|
||||
return FAILURE;
|
||||
}
|
||||
Status child_status = get_child(0)->execute(p_delta);
|
||||
if ((count_policy == COUNT_SUCCESSFUL && child_status == SUCCESS) ||
|
||||
(count_policy == COUNT_FAILED && child_status == FAILURE) ||
|
||||
(count_policy == COUNT_ALL && child_status != RUNNING)) {
|
||||
num_runs += 1;
|
||||
}
|
||||
return get_child(0)->execute(p_delta);
|
||||
return child_status;
|
||||
}
|
||||
|
||||
void BTRunLimit::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_run_limit", "p_value"), &BTRunLimit::set_run_limit);
|
||||
ClassDB::bind_method(D_METHOD("get_run_limit"), &BTRunLimit::get_run_limit);
|
||||
ClassDB::bind_method(D_METHOD("set_count_policy", "p_policy"), &BTRunLimit::set_count_policy);
|
||||
ClassDB::bind_method(D_METHOD("get_count_policy"), &BTRunLimit::get_count_policy);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "run_limit"), "set_run_limit", "get_run_limit");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "count_policy", PROPERTY_HINT_ENUM, "COUNT_SUCCESSFUL,COUNT_FAILED,COUNT_ALL"), "set_count_policy", "get_count_policy");
|
||||
|
||||
BIND_ENUM_CONSTANT(COUNT_SUCCESSFUL);
|
||||
BIND_ENUM_CONSTANT(COUNT_FAILED);
|
||||
BIND_ENUM_CONSTANT(COUNT_ALL);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,16 @@ class BTRunLimit : public BTDecorator {
|
|||
GDCLASS(BTRunLimit, BTDecorator);
|
||||
TASK_CATEGORY(Decorators);
|
||||
|
||||
public:
|
||||
enum CountPolicy {
|
||||
COUNT_SUCCESSFUL,
|
||||
COUNT_FAILED,
|
||||
COUNT_ALL,
|
||||
};
|
||||
|
||||
private:
|
||||
int run_limit = 1;
|
||||
CountPolicy count_policy = CountPolicy::COUNT_SUCCESSFUL;
|
||||
int num_runs = 0;
|
||||
|
||||
protected:
|
||||
|
@ -31,6 +39,11 @@ protected:
|
|||
public:
|
||||
void set_run_limit(int p_value);
|
||||
int get_run_limit() const { return run_limit; }
|
||||
|
||||
void set_count_policy(CountPolicy p_policy);
|
||||
CountPolicy get_count_policy() const { return count_policy; }
|
||||
};
|
||||
|
||||
VARIANT_ENUM_CAST(BTRunLimit::CountPolicy);
|
||||
|
||||
#endif // BT_RUN_LIMIT_H
|
||||
|
|
|
@ -10,8 +10,22 @@
|
|||
<tutorials>
|
||||
</tutorials>
|
||||
<members>
|
||||
<member name="count_policy" type="int" setter="set_count_policy" getter="get_count_policy" enum="BTRunLimit.CountPolicy" default="0">
|
||||
Which runs should be counted towards the limit: successful, failed, or all?
|
||||
</member>
|
||||
<member name="run_limit" type="int" setter="set_run_limit" getter="get_run_limit" default="1">
|
||||
The maximum number of times the child is permitted to be executed.
|
||||
</member>
|
||||
</members>
|
||||
<constants>
|
||||
<constant name="COUNT_SUCCESSFUL" value="0" enum="CountPolicy">
|
||||
Count only successful runs towards the limit.
|
||||
</constant>
|
||||
<constant name="COUNT_FAILED" value="1" enum="CountPolicy">
|
||||
Count only failed runs towards the limit.
|
||||
</constant>
|
||||
<constant name="COUNT_ALL" value="2" enum="CountPolicy">
|
||||
Count successful and failed runs towards the limit.
|
||||
</constant>
|
||||
</constants>
|
||||
</class>
|
||||
|
|
|
@ -40,26 +40,40 @@ TEST_CASE("[Modules][LimboAI] BTRunLimit") {
|
|||
|
||||
SUBCASE("When the child task succeeds") {
|
||||
task->ret_status = BTTask::SUCCESS;
|
||||
|
||||
lim->set_count_policy(BTRunLimit::COUNT_FAILED);
|
||||
CHECK(lim->execute(0.01666) == BTTask::SUCCESS);
|
||||
CHECK_STATUS_ENTRIES_TICKS_EXITS(task, BTTask::SUCCESS, 2, 2, 2); // * task executed
|
||||
|
||||
lim->set_count_policy(BTRunLimit::COUNT_SUCCESSFUL);
|
||||
CHECK(lim->execute(0.01666) == BTTask::SUCCESS);
|
||||
CHECK_STATUS_ENTRIES_TICKS_EXITS(task, BTTask::SUCCESS, 3, 3, 3); // * task executed
|
||||
}
|
||||
SUBCASE("When the child task fails") {
|
||||
task->ret_status = BTTask::FAILURE;
|
||||
|
||||
lim->set_count_policy(BTRunLimit::COUNT_SUCCESSFUL);
|
||||
CHECK(lim->execute(0.01666) == BTTask::FAILURE);
|
||||
CHECK_STATUS_ENTRIES_TICKS_EXITS(task, BTTask::FAILURE, 2, 2, 2); // * task executed
|
||||
|
||||
lim->set_count_policy(BTRunLimit::COUNT_FAILED);
|
||||
CHECK(lim->execute(0.01666) == BTTask::FAILURE);
|
||||
CHECK_STATUS_ENTRIES_TICKS_EXITS(task, BTTask::FAILURE, 3, 3, 3); // * task executed
|
||||
}
|
||||
|
||||
task->ret_status = BTTask::SUCCESS;
|
||||
lim->set_count_policy(BTRunLimit::COUNT_SUCCESSFUL);
|
||||
|
||||
CHECK(lim->execute(0.01666) == BTTask::FAILURE);
|
||||
CHECK_ENTRIES_TICKS_EXITS(task, 2, 2, 2); // * task not executed
|
||||
CHECK_ENTRIES_TICKS_EXITS(task, 3, 3, 3); // * task not executed
|
||||
|
||||
CHECK(lim->execute(0.01666) == BTTask::FAILURE);
|
||||
CHECK_ENTRIES_TICKS_EXITS(task, 2, 2, 2); // * task not executed
|
||||
CHECK_ENTRIES_TICKS_EXITS(task, 3, 3, 3); // * task not executed
|
||||
}
|
||||
|
||||
SUBCASE("When the child task takes more than one tick to finish") {
|
||||
lim->set_run_limit(2);
|
||||
lim->set_count_policy(BTRunLimit::COUNT_ALL);
|
||||
|
||||
task->ret_status = BTTask::RUNNING;
|
||||
CHECK(lim->execute(0.01666) == BTTask::RUNNING);
|
||||
|
|
Loading…
Reference in New Issue