mirror of https://github.com/zeldaret/botw.git
264 lines
8.5 KiB
C++
264 lines
8.5 KiB
C++
#pragma once
|
|
|
|
#include <basis/seadTypes.h>
|
|
#include <math/seadMathCalcCommon.h>
|
|
#include <prim/seadRuntimeTypeInfo.h>
|
|
#include <prim/seadTypedBitFlag.h>
|
|
#include "KingSystem/ActorSystem/actAiParam.h"
|
|
#include "KingSystem/Utils/Types.h"
|
|
|
|
namespace ksys::mes {
|
|
class Message;
|
|
}
|
|
|
|
namespace ksys::res {
|
|
class AIProgram;
|
|
class GParamList;
|
|
} // namespace ksys::res
|
|
|
|
namespace ksys::act {
|
|
|
|
class Actor;
|
|
|
|
namespace ai {
|
|
|
|
class Action;
|
|
|
|
enum class ActionType {
|
|
AI = 0,
|
|
Action = 1,
|
|
};
|
|
|
|
enum class RootAiFlag : u16;
|
|
enum class RootAiFlag2 : u16;
|
|
|
|
sead::SafeString* getDefaultString();
|
|
s32* getDefaultInt();
|
|
f32* getDefaultFloat();
|
|
sead::Vector3f* getDefaultVec3();
|
|
bool* getDefaultBool();
|
|
BaseProcLink* getDefaultBaseProcLink();
|
|
mes::TransceiverId* getDefaultMesTransceiverId();
|
|
BaseProcHandle** getDefaultBaseProcHandle();
|
|
Rail** getDefaultRail();
|
|
sead::FixedSafeString<32>* getDefaultString32();
|
|
|
|
/// Base class for actions and AIs, which can be seen as looping actions.
|
|
class ActionBase {
|
|
SEAD_RTTI_BASE(ActionBase)
|
|
public:
|
|
struct InitArg {
|
|
Actor* actor;
|
|
/// The index of the query definition in the actor's AI program.
|
|
s32 def_idx;
|
|
s32 root_idx;
|
|
};
|
|
KSYS_CHECK_SIZE_NX150(InitArg, 0x10);
|
|
|
|
explicit ActionBase(const InitArg& arg);
|
|
virtual ~ActionBase() = default;
|
|
|
|
bool init(sead::Heap* heap, bool skip_loading_map_or_tree_params);
|
|
void enter(InlineParamPack* params, const sead::SafeString& context);
|
|
bool takeOver(ActionBase* src, const sead::SafeString& context);
|
|
void leave();
|
|
bool oneShot(InlineParamPack* params);
|
|
|
|
Action* getCurrentAction();
|
|
bool handleMessage(mes::Message* message);
|
|
// TODO: rename
|
|
bool handleMessage2(mes::Message* message);
|
|
|
|
Actor* getActor() const { return mActor; }
|
|
s32 getDefinitionIdx() const { return mDefinitionIdx; }
|
|
const char* getClassName() const;
|
|
const char* getName() const;
|
|
|
|
virtual bool isFailed() const { return mFlags.isOn(Flag::Failed); }
|
|
virtual bool isFinished() const { return mFlags.isOn(Flag::Finished); }
|
|
virtual bool isFlag4Set() const { return mFlags.isOn(Flag::_4); }
|
|
|
|
virtual bool hasPreDeleteCb() { return false; }
|
|
virtual bool hasUpdateForPreDeleteCb() { return false; }
|
|
|
|
virtual void m9() {}
|
|
|
|
protected:
|
|
virtual bool oneShot_() { return true; }
|
|
virtual bool init_(sead::Heap* heap) { return true; }
|
|
virtual void enter_(InlineParamPack* params) {}
|
|
virtual bool reenter_(ActionBase* other, bool x);
|
|
virtual void leave_() {}
|
|
virtual void loadParams_() {}
|
|
virtual bool handleMessage_(mes::Message* message) { return false; }
|
|
// TODO: rename
|
|
virtual bool handleMessage2_(mes::Message* message) { return false; }
|
|
|
|
public:
|
|
virtual bool updateForPreDelete() { return true; }
|
|
virtual void onPreDelete() {}
|
|
virtual void calc() {}
|
|
virtual void getCurrentName(sead::BufferedSafeString* name, ActionBase* last) const;
|
|
|
|
virtual ActionBase* changeChild(const sead::SafeString& name) { return nullptr; }
|
|
virtual void getParams(ParamNameTypePairs* pairs, bool update_use_count) const;
|
|
virtual s32 getNumChildren() const { return 0; }
|
|
virtual bool initChildren(const AIDefSet& set, sead::Heap* heap) { return true; }
|
|
virtual ActionBase* getCurrentChild() const { return nullptr; }
|
|
|
|
virtual ActionType getType() const = 0;
|
|
|
|
virtual bool reenter(ActionBase* other, const sead::SafeString& context) {
|
|
return reenter_(other, false);
|
|
}
|
|
|
|
virtual void postLeave() {}
|
|
|
|
virtual ActionBase* getChild(s32 idx) const { return nullptr; }
|
|
|
|
protected:
|
|
enum class Flag : u8 {
|
|
Finished = 1,
|
|
Failed = 2,
|
|
_4 = 4,
|
|
TriggerAction = 8,
|
|
DynamicParamChild = 0x10,
|
|
_20 = 0x20,
|
|
_40 = 0x40,
|
|
_80 = 0x80,
|
|
};
|
|
|
|
bool isRootAiParamINot5() const;
|
|
bool isActorDeletedOrDeleting() const;
|
|
bool isActorGoingBackToRootAi() const;
|
|
|
|
void copyParams(InlineParamPack* dest, bool x) const;
|
|
|
|
void setFinished();
|
|
void setFailed();
|
|
|
|
void setRootAiFlagBit(int bit) const;
|
|
void setRootAiFlag(RootAiFlag flag) const { setRootAiFlagBit(sead::log2(u32(flag))); }
|
|
|
|
void resetRootAiFlagBit(int bit) const;
|
|
void resetRootAiFlag(RootAiFlag flag) const { resetRootAiFlagBit(sead::log2(u32(flag))); }
|
|
|
|
bool testRootAiFlag2Bit(int bit) const;
|
|
bool testRootAiFlag2(RootAiFlag2 flag) const {
|
|
return testRootAiFlag2Bit(sead::log2(u32(flag)));
|
|
}
|
|
|
|
void resetFlags() {
|
|
mFlags.reset(Flag::Failed);
|
|
mFlags.reset(Flag::Finished);
|
|
mFlags.reset(Flag::_4);
|
|
}
|
|
|
|
res::AIProgram* getAIProg() const;
|
|
auto& getDef() const;
|
|
res::GParamList* getGParamList() const;
|
|
|
|
template <typename T>
|
|
bool getStaticParam(T* value, const sead::SafeString& key) const;
|
|
|
|
void logMissingParam(const sead::SafeString& param) const;
|
|
|
|
template <typename T>
|
|
bool getMapUnitParam(T* value, const sead::SafeString& key) const;
|
|
|
|
template <typename T>
|
|
bool getAITreeVariable(T** value, const sead::SafeString& key) const;
|
|
|
|
template <typename T>
|
|
bool getDynamicParamImpl(T* value, const sead::SafeString& key,
|
|
bool (ParamPack::*getter)(T* value, const sead::SafeString& key) const,
|
|
T* default_value) const {
|
|
auto* action = this;
|
|
while (action && action->mFlags.isOff(Flag::_80)) {
|
|
if ((action->mParams.*getter)(value, key))
|
|
return true;
|
|
if (action->mFlags.isOff(Flag::DynamicParamChild))
|
|
goto fail;
|
|
action = action->getCurrentChild();
|
|
if (!action)
|
|
goto fail;
|
|
}
|
|
|
|
for (s32 i = 0, n = action->getNumChildren(); i < n; ++i) {
|
|
auto* child = action->getChild(i);
|
|
if (child->getDynamicParamImpl<T>(value, key, getter, default_value))
|
|
return true;
|
|
}
|
|
|
|
fail:
|
|
logMissingParam(key);
|
|
*value = *default_value;
|
|
return false;
|
|
}
|
|
|
|
template <AIDefParamType Type, typename T>
|
|
bool getDynamicParamPtrImpl(T** value, const sead::SafeString& key, T* default_value) const {
|
|
return getDynamicParamImpl(value, key, &ParamPack::getPtrGeneric<T, Type>, &default_value);
|
|
}
|
|
|
|
bool getDynamicParam(sead::SafeString* value, const sead::SafeString& key) const {
|
|
return getDynamicParamImpl(value, key, &ParamPack::getString, getDefaultString());
|
|
}
|
|
|
|
bool getDynamicParam(int** value, const sead::SafeString& key) const {
|
|
return getDynamicParamPtrImpl<AIDefParamType::Int>(value, key, getDefaultInt());
|
|
}
|
|
|
|
bool getDynamicParam(float** value, const sead::SafeString& key) const {
|
|
return getDynamicParamPtrImpl<AIDefParamType::Float>(value, key, getDefaultFloat());
|
|
}
|
|
|
|
bool getDynamicParam(sead::Vector3f** value, const sead::SafeString& key) const {
|
|
return getDynamicParamPtrImpl<AIDefParamType::Vec3>(value, key, getDefaultVec3());
|
|
}
|
|
|
|
bool getDynamicParam(bool** value, const sead::SafeString& key) const {
|
|
return getDynamicParamPtrImpl<AIDefParamType::Bool>(value, key, getDefaultBool());
|
|
}
|
|
|
|
bool getDynamicParam(BaseProcLink** value, const sead::SafeString& key) const {
|
|
return getDynamicParamPtrImpl<AIDefParamType::BaseProcLink>(value, key,
|
|
getDefaultBaseProcLink());
|
|
}
|
|
|
|
bool getDynamicParam(mes::TransceiverId** value, const sead::SafeString& key) const {
|
|
return getDynamicParamPtrImpl<AIDefParamType::MesTransceiverId>(
|
|
value, key, getDefaultMesTransceiverId());
|
|
}
|
|
|
|
bool getDynamicParam(BaseProcHandle*** value, const sead::SafeString& key) const {
|
|
return getDynamicParamPtrImpl<AIDefParamType::BaseProcHandle>(value, key,
|
|
getDefaultBaseProcHandle());
|
|
}
|
|
|
|
bool getDynamicParam(Rail*** value, const sead::SafeString& key) const {
|
|
return getDynamicParamPtrImpl<AIDefParamType::Rail>(value, key, getDefaultRail());
|
|
}
|
|
|
|
bool getDynamicParam(sead::SafeString** value, const sead::SafeString& key) const {
|
|
return getDynamicParamPtrImpl<AIDefParamType::String>(
|
|
value, key, static_cast<sead::SafeString*>(getDefaultString32()));
|
|
}
|
|
|
|
Actor* mActor;
|
|
ParamPack mParams;
|
|
s16 mDefinitionIdx;
|
|
s8 mRootIdx;
|
|
sead::TypedBitFlag<Flag> mFlags;
|
|
|
|
private:
|
|
void initFlags(res::AIProgram* aiprog, s32 def_idx, ActionType type);
|
|
void updateBehaviorsOnEnter();
|
|
void updateBehaviorsOnLeave();
|
|
};
|
|
KSYS_CHECK_SIZE_NX150(ActionBase, 0x20);
|
|
|
|
} // namespace ai
|
|
|
|
} // namespace ksys::act
|