#include "KingSystem/ActorSystem/aiForkAI.h" #include "KingSystem/ActorSystem/aiRootAi.h" namespace ksys::act::ai { ForkAI::ForkAI(const InitArg& arg) : Ai(arg) {} ForkAI::~ForkAI() = default; bool ForkAI::init_(sead::Heap* heap) { mFlags.set(Flag::_80); return true; } void ForkAI::enter_(InlineParamPack* params) { const int num_children = getNumChildren(); if (num_children >= 1) { for (int i = 0; i < num_children; ++i) getChild(i)->enter(params, getName()); changeChildIdx(num_children - 1); } else { SEAD_WARN("ForkAI::enter_: no children"); changeChildIdx(num_children - 1); } setRootAiFlag(RootAiFlag::_8); } bool ForkAI::reenter(ActionBase* other, const sead::SafeString& context) { auto* other_ = sead::DynamicCast(other); if (!other_) return false; const int num_children = getNumChildren(); if (other_->getNumChildren() != num_children) return false; changeChildIdx(other_->mPrevChildIdx); changeChildIdx(other_->mChildIdx); bool ok = true; for (int i = 0; i < num_children; ++i) { auto* child_other = other_->getChild(i); auto* child = getChild(i); if (child_other && child) ok &= child->takeOver(child_other, getName()); } return ok; } void ForkAI::calc() { calc_(); const int num_children = getNumChildren(); for (int i = 0; i < num_children; ++i) getChild(i)->calc(); handlePendingChildChange(); } void ForkAI::leave_() { const int num_children = getNumChildren(); for (int i = num_children - 2; i >= 0; --i) getChild(i)->leave(); } bool ForkAI::isFailed() const { const int num_children = getNumChildren(); bool failed = false; int i = 0; for (; i < num_children; ++i) { auto* child = getChild(i); failed |= child->isFailed(); if (!child->isFinished() && !child->isFailed() && !child->isChangeable()) break; } return i == num_children && failed; } bool ForkAI::isFinished() const { const int num_children = getNumChildren(); bool finished = false; int i = 0; for (; i < num_children; ++i) { auto* child = getChild(i); if (child->isFailed()) break; if (child->isFinished()) finished = true; else if (!child->isChangeable()) break; } return i == num_children && finished; } bool ForkAI::isChangeable() const { const int num_children = getNumChildren(); for (int i = 0; i < num_children; ++i) { if (!getChild(i)->isChangeable()) return false; } return true; } bool ForkAI::handleMessage_(const Message& message) { const int num_children = getNumChildren(); bool ok = false; for (int i = 0; i < num_children - 1; ++i) ok |= getChild(i)->handleMessage(message); if (!ok) return false; getChild(num_children - 1)->handleMessage(message); return true; } bool ForkAI::handleAck_(const MessageAck& message) { const int num_children = getNumChildren(); bool ok = false; for (int i = 0; i < num_children - 1; ++i) ok |= getChild(i)->handleAck(message); if (!ok) return false; getChild(num_children - 1)->handleAck(message); return true; } void ForkAI::getCurrentName(sead::BufferedSafeString* name, ActionBase* last) const { name->appendWithFormat("/%s{", getName()); if (this != last) { const int num_children = getNumChildren(); for (int i = 0; i < num_children; ++i) { getChild(i)->getCurrentName(name, last); name->appendWithFormat(","); } } name->appendWithFormat("}"); } void ForkAI::getNames(sead::BufferedSafeString* out) const { out->appendWithFormat("{"); const int num_children = getNumChildren(); for (int i = 0; i < num_children; ++i) { auto* child = getChild(i); out->appendWithFormat("/%s", child->getName()); if (auto* ai = sead::DynamicCast(child)) ai->getNames(out); out->appendWithFormat(","); } out->appendWithFormat("}"); } } // namespace ksys::act::ai