void CompositeBehavior::doAction(bool directlyExecuted) {
	if (agent->isDead() || agent->isIncapacitated() || (agent->getZone() == NULL)) {
		agent->setFollowObject(NULL);
		return;
	}

	if (!started())
		this->start();
	else if (!checkConditions())
		endWithFailure();

	if (finished()) {
		Behavior::doAction(directlyExecuted);
		return;
	}

	Behavior* currentChild;

	do {
		currentChild = children.get(currentPos);

		if (currentChild == NULL) {
			agent->error("NULL child or empty children list in CompositeBehavior");
			endWithError();
			Behavior::doAction(directlyExecuted);
			return;
		}

		if (!currentChild->started())
			currentChild->start();
		else if (!currentChild->checkConditions()) // if this isn't here, I can get a single recursion where the child will call the parent's (this) doAction()
			endWithFailure();

		if (!currentChild->finished())
			currentChild->doAction();

		if (currentChild->finished()) {
			if (currentChild->succeeded())
				this->childSucceeded();
			else if (currentChild->failed())
				this->childFailed();

			currentChild->end();
		}
	} while (currentChild != NULL && currentChild->finished() && !this->finished() && currentPos < children.size());

	if (currentChild->finished())
		Behavior::doAction(directlyExecuted);
}
Ejemplo n.º 2
0
void ParallelBehavior::doAction(bool directlyExecuted) {
	if (finished()) {
		Behavior::doAction(directlyExecuted);
		return;
	}

	if (!started())
		this->start();

	for (int i = 0; i < children.size(); i++) {
		Behavior* currentChild = children.get(i);

		if (currentChild == NULL) { // this shouldn't happen. Bail.
			agent->error("NULL child or empty children list in ParallelBehavior");
			endWithError();
			Behavior::doAction(directlyExecuted);
			return;
		}

		if (!unfinishedChildren.contains(currentChild)) // we don't want to process a child after it has already ended
			continue;

		if (!currentChild->started())
			currentChild->start();
		else if (currentChild->finished()) {
			if (currentChild->succeeded())
				this->childSucceeded();
			else if (currentChild->failed())
				this->childFailed();

			currentChild->end();
			unfinishedChildren.removeElement(currentChild);
		} else {
			currentChild->doAction();
		}
	}

	if (unfinishedChildren.isEmpty())
		this->finish();

	Behavior::doAction(directlyExecuted);
}