diff options
| author | Léo Lam <leo@leolam.fr> | 2026-10-11 04:13:20 +0200 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2026-10-11 04:13:20 +0200 |
| commit | 6e9afd0f7d6f8e037fd71e91dfdad4b45f8e7e2f (patch) | |
| tree | d971f814d1cde46f56da6041037a65f512654ee3 /src/KingSystem/ActorSystem | |
| parent | 49c6b5c18344de6555163b3af7044970ad9d7c5e (diff) | |
ksys/act: rename the actor accessor to ActorLinkConstDataAccess
The 0x18-sized accessor appears to be named ActorLinkConstDataAccess
based on a source path string in the Wii U build. The 0x10-sized
base class (which we had given the name to) only holds a BaseProc and
its dtor/acquire functions live in a separate TU so let's rename it
BaseProcAccessor (unofficial name).
acquireActor is a header inline whose one copy landed in the BeamBase
object. Nothing in BeamBase calls it, so the BeamBase function that used
it was probably dead-stripped by the linker.
(AI assisted using Claude Opus 5.5)
Diffstat (limited to 'src/KingSystem/ActorSystem')
18 files changed, 685 insertions, 696 deletions
diff --git a/src/KingSystem/ActorSystem/CMakeLists.txt b/src/KingSystem/ActorSystem/CMakeLists.txt index 1a549493..b3f0e0da 100644 --- a/src/KingSystem/ActorSystem/CMakeLists.txt +++ b/src/KingSystem/ActorSystem/CMakeLists.txt @@ -25,8 +25,6 @@ target_sources(uking PRIVATE actActor.h actActorCaptureMgr.cpp actActorCaptureMgr.h - actActorConstDataAccess.cpp - actActorConstDataAccess.h actActorCreator.cpp actActorCreator.h actActorEditorNode.cpp @@ -70,6 +68,8 @@ target_sources(uking PRIVATE actASSetting.h actBaseProc.cpp actBaseProc.h + actBaseProcAccessor.cpp + actBaseProcAccessor.h actBaseProcCreateTask.cpp actBaseProcCreateTask.h actBaseProcCreateTaskSelector.cpp diff --git a/src/KingSystem/ActorSystem/actActorConstDataAccess.cpp b/src/KingSystem/ActorSystem/actActorConstDataAccess.cpp deleted file mode 100644 index c3061e90..00000000 --- a/src/KingSystem/ActorSystem/actActorConstDataAccess.cpp +++ /dev/null @@ -1,420 +0,0 @@ -#include "KingSystem/ActorSystem/actActorConstDataAccess.h" -#include <prim/seadRuntimeTypeInfo.h> -#include "KingSystem/ActorSystem/actActor.h" -#include "KingSystem/ActorSystem/actActorParam.h" -#include "KingSystem/ActorSystem/actActorUtil.h" -#include "KingSystem/ActorSystem/actAiRoot.h" -#include "KingSystem/Map/mapObject.h" -#include "KingSystem/Resource/Actor/resResourceGParamList.h" -#include "KingSystem/Resource/GeneralParamList/resGParamListObjectAttack.h" -#include "KingSystem/Resource/GeneralParamList/resGParamListObjectEnemy.h" -#include "KingSystem/Resource/GeneralParamList/resGParamListObjectHorseTargetedInfo.h" -#include "KingSystem/Resource/GeneralParamList/resGParamListObjectLiftable.h" -#include "KingSystem/Resource/GeneralParamList/resGParamListObjectSystem.h" - -namespace ksys::act { - -static BaseProc* getProcIfActor(BaseProc* proc) { - if (proc && sead::IsDerivedFrom<Actor>(proc)) - return proc; - return nullptr; -} - -inline Actor* ActorConstDataAccess::getActor() const { - return static_cast<Actor*>(getProcIfActor(mProc)); -} - -bool ActorConstDataAccess::acquireActor(const ActorLinkConstDataAccess& other) { - return acquire(getProcIfActor(other.mProc)); -} - -bool ActorConstDataAccess::hasProc(BaseProc* proc) const { - return mProc == proc; -} - -bool ActorConstDataAccess::hasProc(const BaseProcLink& link) const { - return link.hasProcById(getActor()); -} - -bool ActorConstDataAccess::linkAcquire(BaseProcLink* link) const { - auto* proc = getActor(); - if (proc) - return link->acquire(proc, false); - - link->reset(); - return false; -} - -bool ActorConstDataAccess::linkAcquireImmediately(BaseProcLink* link) const { - auto* proc = getActor(); - if (proc) - return link->acquire(proc, true); - - link->reset(); - return false; -} - -bool ActorConstDataAccess::isPlayerProfile() const { - return act::isPlayerProfile(getActor()); -} - -bool ActorConstDataAccess::isWeaponProfile() const { - return act::isWeaponProfile(getActor()); -} - -bool ActorConstDataAccess::isNPCProfile() const { - return act::isNPCProfile(getActor()); -} - -bool ActorConstDataAccess::isEnemyProfile() const { - return act::isEnemyProfile(getActor()); -} - -const sead::SafeString& ActorConstDataAccess::getProfile() const { - auto* actor = getActor(); - return actor && actor->getParam() ? actor->getProfile() : sead::SafeString::cEmptyString; -} - -void ActorConstDataAccess::debugLog(s32, const sead::SafeString&) const { - // Intentionally left empty. -} - -const sead::SafeString& ActorConstDataAccess::getName() const { - auto* proc = getProcIfActor(mProc); - if (!proc) - return sead::SafeString::cEmptyString; - return proc->getName(); -} - -const sead::SafeString& ActorConstDataAccess::getLiftType() const { - auto* actor = getActor(); - if (!actor) - return sead::SafeString::cEmptyString; - return actor->getParam()->getRes().mGParamList->getLiftable()->mLiftType.ref(); -} - -bool ActorConstDataAccess::isDisableFreezeLift() const { - auto* actor = getActor(); - if (!actor) - return false; - return actor->getParam()->getRes().mGParamList->getLiftable()->mDisableFreezeLift.ref(); -} - -bool ActorConstDataAccess::isDisableBurnLift() const { - auto* actor = getActor(); - if (!actor) - return false; - return actor->getParam()->getRes().mGParamList->getLiftable()->mDisableBurnLift.ref(); -} - -bool ActorConstDataAccess::hasTag(const char* tag) const { - auto* actor = getActor(); - if (!actor) - return false; - return actor->getParam()->getRes().mActorLink->hasTag(tag); -} - -bool ActorConstDataAccess::hasTag(u32 tag) const { - auto* actor = getActor(); - if (!actor) - return false; - return actor->getParam()->getRes().mActorLink->hasTag(tag); -} - -const char* ActorConstDataAccess::getUniqueName() const { - auto* actor = getActor(); - if (!actor) - return nullptr; - return actor->getUniqueName(); -} - -u32 ActorConstDataAccess::getId() const { - auto* proc = getActor(); - if (!proc) - return 0xffffffff; - return proc->getId(); -} - -bool ActorConstDataAccess::acquireConnectedCalcParent(ActorLinkConstDataAccess* accessor) const { - auto* proc = getActor(); - if (!proc) - return false; - - accessor->acquire(sead::DynamicCast<Actor>(proc->getConnectedCalcParent())); - return accessor->mProc != nullptr; -} - -bool ActorConstDataAccess::acquireConnectedCalcChild(ActorLinkConstDataAccess* accessor) const { - auto* proc = getActor(); - if (!proc) - return false; - - accessor->acquire(sead::DynamicCast<Actor>(proc->getConnectedCalcChild())); - return accessor->mProc != nullptr; -} - -bool ActorConstDataAccess::hasConnectedCalcParent() const { - auto* proc = getActor(); - return proc && sead::DynamicCast<Actor>(proc->getConnectedCalcParent()) != nullptr; -} - -bool ActorConstDataAccess::checkFlag2B() const { - auto* actor = getActor(); - if (!actor) - return false; - return actor->checkFlag(Actor::ActorFlag::_2b); -} - -bool ActorConstDataAccess::deleteLater(BaseProc::DeleteReason reason) const { - auto* actor = getActor(); - if (!actor) - return false; - return actor->deleteLater(reason); -} - -bool ActorConstDataAccess::deleteEx(BaseProc::DeleteReason reason) const { - auto* actor = getActor(); - if (!actor) - return false; - return actor->deleteEx(Actor::DeleteType::_1, reason); -} - -bool ActorConstDataAccess::sleep(BaseProc::SleepWakeReason reason) const { - auto* actor = getActor(); - if (!actor) - return false; - actor->sleep(reason); - return true; -} - -bool ActorConstDataAccess::wakeUp(BaseProc::SleepWakeReason reason) const { - auto* actor = getActor(); - if (!actor) - return false; - actor->wakeUp(reason); - return true; -} - -bool ActorConstDataAccess::setProperties(int x, const sead::Matrix34f& mtx, - const sead::Vector3f& vel, const sead::Vector3f& ang_vel, - const sead::Vector3f& scale, bool is_life_infinite, int i, - int life) const { - auto* actor = getActor(); - if (!actor) - return false; - actor->setProperties(x, mtx, vel, ang_vel, scale, is_life_infinite, i, life); - return true; -} - -bool ActorConstDataAccess::setProperties(const sead::Matrix34f& mtx, const sead::Vector3f& vel, - const sead::Vector3f& ang_vel, const sead::Vector3f& scale, - bool is_life_infinite, int i, int life) const { - return setProperties(0, mtx, vel, ang_vel, scale, is_life_infinite, i, life); -} - -bool ActorConstDataAccess::isStateSleep() const { - auto* actor = getActor(); - return actor && actor->isSleep(); -} - -bool ActorConstDataAccess::isStateCalc() const { - auto* actor = getActor(); - return actor && actor->isCalc(); -} - -bool ActorConstDataAccess::isDeletedOrDeleting() const { - auto* actor = getActor(); - return actor && actor->isDeletedOrDeleting(); -} - -res::GParamList* ActorConstDataAccess::getGParamList() const { - auto* actor = getActor(); - if (!actor) - return nullptr; - return actor->getParam()->getRes().mGParamList; -} - -res::Shop* ActorConstDataAccess::getShopData() const { - auto* actor = getActor(); - if (!actor) - return nullptr; - return actor->getParam()->getRes().mShopData; -} - -const sead::SafeString& ActorConstDataAccess::getAttackSpHitActor() const { - auto* actor = getActor(); - if (!actor) - return sead::SafeString::cEmptyString; - return actor->getParam()->getRes().mGParamList->getAttack()->mSpHitActor.ref(); -} - -const sead::SafeString& ActorConstDataAccess::getAttackSpHitTag() const { - auto* actor = getActor(); - if (!actor) - return sead::SafeString::cEmptyString; - return actor->getParam()->getRes().mGParamList->getAttack()->mSpHitTag.ref(); -} - -const sead::SafeString& ActorConstDataAccess::getAttackWeakHitTag() const { - auto* actor = getActor(); - if (!actor) - return sead::SafeString::cEmptyString; - return actor->getParam()->getRes().mGParamList->getAttack()->mSpWeakHitActor.ref(); -} - -f32 ActorConstDataAccess::getAttackSpHitRatio() const { - auto* actor = getActor(); - if (!actor) - return 1.0f; - return actor->getParam()->getRes().mGParamList->getAttack()->mSpHitRatio.ref(); -} - -s32 ActorConstDataAccess::getAttackPower() const { - auto* actor = getActor(); - if (!actor) - return 0; - return actor->getParam()->getRes().mGParamList->getAttack()->mPower.ref(); -} - -map::ObjectLinkData* ActorConstDataAccess::getMapObjectLinkData() const { - auto* actor = getActor(); - if (!actor) - return nullptr; - - auto* object = actor->getMapObject(); - if (!object) - return nullptr; - - return object->getLinkData(); -} - -map::Object* ActorConstDataAccess::getMapObject() const { - auto* actor = getActor(); - if (!actor) - return nullptr; - return actor->getMapObject(); -} - -s32 ActorConstDataAccess::getEnemyRank() const { - auto* actor = getActor(); - if (!actor) - return 0; - - auto* gparam = actor->getParam()->getRes().mGParamList; - if (!gparam || !gparam->getEnemy()) - return 0; - - return gparam->getEnemy()->mRank.ref(); -} - -bool ActorConstDataAccess::getSameGroupActorName(sead::SafeString* name) const { - auto* actor = getActor(); - if (!actor) { - *name = sead::SafeString::cEmptyString; - return false; - } - - auto* gparam = actor->getParam()->getRes().mGParamList; - if (!gparam || !gparam->getSystem()) { - *name = actor->getName(); - return false; - } - - const auto& group_name = gparam->getSystem()->mSameGroupActorName.ref(); - if (group_name.isEmpty()) { - *name = actor->getName(); - return false; - } - - *name = group_name; - return true; -} - -bool ActorConstDataAccess::checkFlag18() const { - auto* actor = getActor(); - return actor && actor->checkFlag(Actor::ActorFlag::_18); -} - -bool ActorConstDataAccess::isPlayerTheConnectedParent() const { - auto* actor = getActor(); - if (!actor) - return false; - - auto* parent = sead::DynamicCast<Actor>(actor->getConnectedCalcParent()); - if (!parent) - return false; - - return parent->getProfile() == "Player"; -} - -void ActorConstDataAccess::setThisActorAsParent(BaseProc* child, bool delete_parent_on_delete) { - auto* actor = getActor(); - if (!actor) - return; - child->setConnectedCalcParent(actor, delete_parent_on_delete); -} - -void ActorConstDataAccess::setThisActorAsChild(BaseProc* parent, bool delete_child_on_delete) { - auto* actor = getActor(); - if (!actor) - return; - parent->setConnectedCalcChild(actor, delete_child_on_delete); -} - -bool ActorConstDataAccess::isFlyingBalloon() const { - auto* actor = getActor(); - if (!actor) - return false; - bool* value; - return actor->getRootAi()->getAITreeVariable(&value, "IsFlyingBalloon") && *value; -} - -u32 ActorConstDataAccess::getBalloonHungActorBaseProcID() const { - auto* actor = getActor(); - if (!actor) - return -1; - int* value; - if (!actor->getRootAi()->getAITreeVariable(&value, "BalloonHungActorBaseProcID")) - return -1; - return *value; -} - -bool ActorConstDataAccess::checkFlag25() const { - auto* actor = getActor(); - return actor && actor->checkFlag(Actor::ActorFlag::_25); -} - -f32 ActorConstDataAccess::getHorseMoveRadius() const { - auto* actor = getActor(); - if (!actor) - return -1.0; - return actor->getParam()->getRes().mGParamList->getHorseTargetedInfo()->mHorseMoveRadius.ref(); -} - -f32 ActorConstDataAccess::getHorseAvoidOffset() const { - auto* actor = getActor(); - if (!actor) - return -1.0; - return actor->getParam()->getRes().mGParamList->getHorseTargetedInfo()->mHorseAvoidOffset.ref(); -} - -bool ActorConstDataAccess::horseTargetedIsCircularMoveAlways() const { - auto* actor = getActor(); - if (!actor) - return false; - auto* gparam = actor->getParam()->getRes().mGParamList; - return gparam->getHorseTargetedInfo()->mIsCircularMoveAlways.ref(); -} - -bool acquireActor(BaseProcLink* link, ActorConstDataAccess* accessor) { - return link->getProcInContext([accessor](BaseProc* proc, bool valid) { - if (!proc) { - if (!valid) - accessor->acquire(nullptr); - return false; - } - return accessor->acquire(sead::DynamicCast<Actor>(proc)); - }); -} - -} // namespace ksys::act diff --git a/src/KingSystem/ActorSystem/actActorConstDataAccess.h b/src/KingSystem/ActorSystem/actActorConstDataAccess.h deleted file mode 100644 index b78e9fbc..00000000 --- a/src/KingSystem/ActorSystem/actActorConstDataAccess.h +++ /dev/null @@ -1,131 +0,0 @@ -#pragma once - -#include <math/seadMatrix.h> -#include <math/seadVector.h> -#include <prim/seadRuntimeTypeInfo.h> -#include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h" -#include "KingSystem/ActorSystem/actBaseProc.h" -#include "KingSystem/ActorSystem/actBaseProcLink.h" -#include "KingSystem/Utils/Types.h" - -namespace ksys::map { -class Object; -class ObjectLinkData; -} // namespace ksys::map - -namespace ksys::res { -class GParamList; -class Shop; -} // namespace ksys::res - -namespace ksys::act { - -class Actor; - -class ActorConstDataAccess : public ActorLinkConstDataAccess { -public: - ActorConstDataAccess() = default; - explicit ActorConstDataAccess(BaseProc* proc) : ActorLinkConstDataAccess(proc) {} - - bool acquireActor(const ActorLinkConstDataAccess& other); - - bool hasProc() const { return ActorLinkConstDataAccess::hasProc(); } - - /// Checks whether the acquired BaseProc is `proc`. - bool hasProc(BaseProc* proc) const; - - /// Checks whether the acquired BaseProc and the BaseProcLink's actor are the same - /// by comparing the IDs. - bool hasProc(const BaseProcLink& link) const; - - template <typename T> - bool isDerivedFrom() const { - return sead::IsDerivedFrom<T>(mProc); - } - - bool linkAcquire(BaseProcLink* link) const; - bool linkAcquireImmediately(BaseProcLink* link) const; - - void debugLog(s32, const sead::SafeString& method_name) const; - - bool isPlayerProfile() const; - bool isWeaponProfile() const; - bool isNPCProfile() const; - bool isEnemyProfile() const; - - const sead::SafeString& getProfile() const; - const sead::SafeString& getName() const; - - const sead::SafeString& getLiftType() const; - bool isDisableFreezeLift() const; - bool isDisableBurnLift() const; - - bool hasTag(const char* tag) const; - bool hasTag(u32 tag) const; - const char* getUniqueName() const; - u32 getId() const; - bool acquireConnectedCalcParent(ActorLinkConstDataAccess* accessor) const; - bool acquireConnectedCalcChild(ActorLinkConstDataAccess* accessor) const; - bool hasConnectedCalcParent() const; - bool checkFlag2B() const; - - bool deleteLater(BaseProc::DeleteReason reason) const; - bool deleteEx(BaseProc::DeleteReason reason) const; - bool sleep(BaseProc::SleepWakeReason reason) const; - bool wakeUp(BaseProc::SleepWakeReason reason) const; - bool setProperties(int x, const sead::Matrix34f& mtx, const sead::Vector3f& vel, - const sead::Vector3f& ang_vel, const sead::Vector3f& scale, - bool is_life_infinite, int i, int life) const; - bool setProperties(const sead::Matrix34f& mtx, const sead::Vector3f& vel, - const sead::Vector3f& ang_vel, const sead::Vector3f& scale, - bool is_life_infinite, int i, int life) const; - bool isStateSleep() const; - bool isStateCalc() const; - bool isDeletedOrDeleting() const; - - res::GParamList* getGParamList() const; - res::Shop* getShopData() const; - - const sead::SafeString& getAttackSpHitActor() const; - const sead::SafeString& getAttackSpHitTag() const; - const sead::SafeString& getAttackWeakHitTag() const; - f32 getAttackSpHitRatio() const; - s32 getAttackPower() const; - - bool checkLinkTagActivated(bool a, bool b); - map::ObjectLinkData* getMapObjectLinkData() const; - map::Object* getMapObject() const; - - s32 getEnemyRank() const; - - bool getSameGroupActorName(sead::SafeString* name) const; - - bool checkFlag18() const; - bool isPlayerTheConnectedParent() const; - - const sead::Vector3f& getPreviousPos() const; - - void setThisActorAsParent(BaseProc* child, bool delete_parent_on_delete); - void setThisActorAsChild(BaseProc* parent, bool delete_child_on_delete); - - bool isAttClientEnabled(const sead::SafeString& client) const; - - bool isFlyingBalloon() const; - u32 getBalloonHungActorBaseProcID() const; - - bool checkFlag25() const; - - f32 getHorseMoveRadius() const; - f32 getHorseAvoidOffset() const; - bool horseTargetedIsCircularMoveAlways() const; - -private: - Actor* getActor() const; - - u8 _10 = 0; -}; -KSYS_CHECK_SIZE_NX150(ActorConstDataAccess, 0x18); - -bool acquireActor(BaseProcLink* link, ActorConstDataAccess* accessor); - -} // namespace ksys::act diff --git a/src/KingSystem/ActorSystem/actActorLimiter.cpp b/src/KingSystem/ActorSystem/actActorLimiter.cpp index 94531c96..fdc7b348 100644 --- a/src/KingSystem/ActorSystem/actActorLimiter.cpp +++ b/src/KingSystem/ActorSystem/actActorLimiter.cpp @@ -1,5 +1,5 @@ #include "KingSystem/ActorSystem/actActorLimiter.h" -#include "KingSystem/ActorSystem/actActorConstDataAccess.h" +#include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h" #include "KingSystem/ActorSystem/actTag.h" namespace ksys::act { @@ -35,7 +35,7 @@ bool ActorLimiter::List::addActor(BaseProc* proc, bool allow_evicting_old_actors target_node = mActorList.popFront(); if (target_node) { - ActorConstDataAccess acc; + ActorLinkConstDataAccess acc; acquireActor(&target_node->proc_link, &acc); // Priority material actors will not be evicted if possible. diff --git a/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.cpp b/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.cpp index 06694bbf..591df49e 100644 --- a/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.cpp +++ b/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.cpp @@ -1,64 +1,419 @@ #include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h" #include <prim/seadRuntimeTypeInfo.h> #include "KingSystem/ActorSystem/actActor.h" +#include "KingSystem/ActorSystem/actActorParam.h" +#include "KingSystem/ActorSystem/actActorUtil.h" +#include "KingSystem/ActorSystem/actAiRoot.h" #include "KingSystem/ActorSystem/actBaseProc.h" -#include "KingSystem/ActorSystem/actBaseProcMgr.h" -#include "KingSystem/Utils/Debug.h" +#include "KingSystem/Map/mapObject.h" +#include "KingSystem/Resource/Actor/resResourceGParamList.h" +#include "KingSystem/Resource/GeneralParamList/resGParamListObjectAttack.h" +#include "KingSystem/Resource/GeneralParamList/resGParamListObjectEnemy.h" +#include "KingSystem/Resource/GeneralParamList/resGParamListObjectHorseTargetedInfo.h" +#include "KingSystem/Resource/GeneralParamList/resGParamListObjectLiftable.h" +#include "KingSystem/Resource/GeneralParamList/resGParamListObjectSystem.h" namespace ksys::act { -ActorLinkConstDataAccess::~ActorLinkConstDataAccess() { - if (mAcquired && mProc) - mProc->release(); +static BaseProc* getProcIfActor(BaseProc* proc) { + if (proc && sead::IsDerivedFrom<Actor>(proc)) + return proc; + return nullptr; +} - mAcquired = false; - mProc = nullptr; +inline Actor* ActorLinkConstDataAccess::getActor() const { + return static_cast<Actor*>(getProcIfActor(mProc)); } -bool ActorLinkConstDataAccess::acquire(BaseProc* proc) { - if (mProc) { - if (mAcquired) - mProc->release(); +bool ActorLinkConstDataAccess::acquireActor(const BaseProcAccessor& other) { + return acquire(getProcIfActor(other.mProc)); +} - mAcquired = false; - mProc = nullptr; - } +bool ActorLinkConstDataAccess::hasProc(BaseProc* proc) const { + return mProc == proc; +} + +bool ActorLinkConstDataAccess::hasProc(const BaseProcLink& link) const { + return link.hasProcById(getActor()); +} + +bool ActorLinkConstDataAccess::linkAcquire(BaseProcLink* link) const { + auto* proc = getActor(); + if (proc) + return link->acquire(proc, false); + + link->reset(); + return false; +} + +bool ActorLinkConstDataAccess::linkAcquireImmediately(BaseProcLink* link) const { + auto* proc = getActor(); + if (proc) + return link->acquire(proc, true); + + link->reset(); + return false; +} + +bool ActorLinkConstDataAccess::isPlayerProfile() const { + return act::isPlayerProfile(getActor()); +} + +bool ActorLinkConstDataAccess::isWeaponProfile() const { + return act::isWeaponProfile(getActor()); +} + +bool ActorLinkConstDataAccess::isNPCProfile() const { + return act::isNPCProfile(getActor()); +} + +bool ActorLinkConstDataAccess::isEnemyProfile() const { + return act::isEnemyProfile(getActor()); +} + +const sead::SafeString& ActorLinkConstDataAccess::getProfile() const { + auto* actor = getActor(); + return actor && actor->getParam() ? actor->getProfile() : sead::SafeString::cEmptyString; +} + +void ActorLinkConstDataAccess::debugLog(s32, const sead::SafeString&) const { + // Intentionally left empty. +} + +const sead::SafeString& ActorLinkConstDataAccess::getName() const { + auto* proc = getProcIfActor(mProc); + if (!proc) + return sead::SafeString::cEmptyString; + return proc->getName(); +} + +const sead::SafeString& ActorLinkConstDataAccess::getLiftType() const { + auto* actor = getActor(); + if (!actor) + return sead::SafeString::cEmptyString; + return actor->getParam()->getRes().mGParamList->getLiftable()->mLiftType.ref(); +} + +bool ActorLinkConstDataAccess::isDisableFreezeLift() const { + auto* actor = getActor(); + if (!actor) + return false; + return actor->getParam()->getRes().mGParamList->getLiftable()->mDisableFreezeLift.ref(); +} - return proc && proc->acquire(*this); +bool ActorLinkConstDataAccess::isDisableBurnLift() const { + auto* actor = getActor(); + if (!actor) + return false; + return actor->getParam()->getRes().mGParamList->getLiftable()->mDisableBurnLift.ref(); } -const Actor* ActorLinkConstDataAccess::getActor() const { - if (!mProc) +bool ActorLinkConstDataAccess::hasTag(const char* tag) const { + auto* actor = getActor(); + if (!actor) + return false; + return actor->getParam()->getRes().mActorLink->hasTag(tag); +} + +bool ActorLinkConstDataAccess::hasTag(u32 tag) const { + auto* actor = getActor(); + if (!actor) + return false; + return actor->getParam()->getRes().mActorLink->hasTag(tag); +} + +const char* ActorLinkConstDataAccess::getUniqueName() const { + auto* actor = getActor(); + if (!actor) return nullptr; - return sead::DynamicCast<Actor>(mProc); + return actor->getUniqueName(); } -const sead::Matrix34f& ActorLinkConstDataAccess::getActorMtx() { - const Actor* actor = getActor(); - if (actor) - return actor->getMtx(); - return sead::Matrix34f::ident; +u32 ActorLinkConstDataAccess::getId() const { + auto* proc = getActor(); + if (!proc) + return 0xffffffff; + return proc->getId(); +} + +bool ActorLinkConstDataAccess::acquireConnectedCalcParent(BaseProcAccessor* accessor) const { + auto* proc = getActor(); + if (!proc) + return false; + + accessor->acquire(sead::DynamicCast<Actor>(proc->getConnectedCalcParent())); + return accessor->mProc != nullptr; +} + +bool ActorLinkConstDataAccess::acquireConnectedCalcChild(BaseProcAccessor* accessor) const { + auto* proc = getActor(); + if (!proc) + return false; + + accessor->acquire(sead::DynamicCast<Actor>(proc->getConnectedCalcChild())); + return accessor->mProc != nullptr; +} + +bool ActorLinkConstDataAccess::hasConnectedCalcParent() const { + auto* proc = getActor(); + return proc && sead::DynamicCast<Actor>(proc->getConnectedCalcParent()) != nullptr; +} + +bool ActorLinkConstDataAccess::checkFlag2B() const { + auto* actor = getActor(); + if (!actor) + return false; + return actor->checkFlag(Actor::ActorFlag::_2b); +} + +bool ActorLinkConstDataAccess::deleteLater(BaseProc::DeleteReason reason) const { + auto* actor = getActor(); + if (!actor) + return false; + return actor->deleteLater(reason); +} + +bool ActorLinkConstDataAccess::deleteEx(BaseProc::DeleteReason reason) const { + auto* actor = getActor(); + if (!actor) + return false; + return actor->deleteEx(Actor::DeleteType::_1, reason); +} + +bool ActorLinkConstDataAccess::sleep(BaseProc::SleepWakeReason reason) const { + auto* actor = getActor(); + if (!actor) + return false; + actor->sleep(reason); + return true; +} + +bool ActorLinkConstDataAccess::wakeUp(BaseProc::SleepWakeReason reason) const { + auto* actor = getActor(); + if (!actor) + return false; + actor->wakeUp(reason); + return true; +} + +bool ActorLinkConstDataAccess::setProperties(int x, const sead::Matrix34f& mtx, + const sead::Vector3f& vel, + const sead::Vector3f& ang_vel, + const sead::Vector3f& scale, bool is_life_infinite, + int i, int life) const { + auto* actor = getActor(); + if (!actor) + return false; + actor->setProperties(x, mtx, vel, ang_vel, scale, is_life_infinite, i, life); + return true; +} + +bool ActorLinkConstDataAccess::setProperties(const sead::Matrix34f& mtx, const sead::Vector3f& vel, + const sead::Vector3f& ang_vel, + const sead::Vector3f& scale, bool is_life_infinite, + int i, int life) const { + return setProperties(0, mtx, vel, ang_vel, scale, is_life_infinite, i, life); +} + +bool ActorLinkConstDataAccess::isStateSleep() const { + auto* actor = getActor(); + return actor && actor->isSleep(); } -bool acquireProc(ActorLinkConstDataAccess* accessor, BaseProc* proc, const sead::SafeString& from, - s32) { - bool acquired = false; +bool ActorLinkConstDataAccess::isStateCalc() const { + auto* actor = getActor(); + return actor && actor->isCalc(); +} + +bool ActorLinkConstDataAccess::isDeletedOrDeleting() const { + auto* actor = getActor(); + return actor && actor->isDeletedOrDeleting(); +} + +res::GParamList* ActorLinkConstDataAccess::getGParamList() const { + auto* actor = getActor(); + if (!actor) + return nullptr; + return actor->getParam()->getRes().mGParamList; +} + +res::Shop* ActorLinkConstDataAccess::getShopData() const { + auto* actor = getActor(); + if (!actor) + return nullptr; + return actor->getParam()->getRes().mShopData; +} + +const sead::SafeString& ActorLinkConstDataAccess::getAttackSpHitActor() const { + auto* actor = getActor(); + if (!actor) + return sead::SafeString::cEmptyString; + return actor->getParam()->getRes().mGParamList->getAttack()->mSpHitActor.ref(); +} + +const sead::SafeString& ActorLinkConstDataAccess::getAttackSpHitTag() const { + auto* actor = getActor(); + if (!actor) + return sead::SafeString::cEmptyString; + return actor->getParam()->getRes().mGParamList->getAttack()->mSpHitTag.ref(); +} + +const sead::SafeString& ActorLinkConstDataAccess::getAttackWeakHitTag() const { + auto* actor = getActor(); + if (!actor) + return sead::SafeString::cEmptyString; + return actor->getParam()->getRes().mGParamList->getAttack()->mSpWeakHitActor.ref(); +} + +f32 ActorLinkConstDataAccess::getAttackSpHitRatio() const { + auto* actor = getActor(); + if (!actor) + return 1.0f; + return actor->getParam()->getRes().mGParamList->getAttack()->mSpHitRatio.ref(); +} + +s32 ActorLinkConstDataAccess::getAttackPower() const { + auto* actor = getActor(); + if (!actor) + return 0; + return actor->getParam()->getRes().mGParamList->getAttack()->mPower.ref(); +} + +map::ObjectLinkData* ActorLinkConstDataAccess::getMapObjectLinkData() const { + auto* actor = getActor(); + if (!actor) + return nullptr; + + auto* object = actor->getMapObject(); + if (!object) + return nullptr; + + return object->getLinkData(); +} + +map::Object* ActorLinkConstDataAccess::getMapObject() const { + auto* actor = getActor(); + if (!actor) + return nullptr; + return actor->getMapObject(); +} + +s32 ActorLinkConstDataAccess::getEnemyRank() const { + auto* actor = getActor(); + if (!actor) + return 0; + + auto* gparam = actor->getParam()->getRes().mGParamList; + if (!gparam || !gparam->getEnemy()) + return 0; + + return gparam->getEnemy()->mRank.ref(); +} - if (accessor) { - acquired = accessor->acquire(proc); - if (!acquired) - return false; +bool ActorLinkConstDataAccess::getSameGroupActorName(sead::SafeString* name) const { + auto* actor = getActor(); + if (!actor) { + *name = sead::SafeString::cEmptyString; + return false; } - if (acquired || BaseProcMgr::instance()->isHighPriorityThread()) - return true; + auto* gparam = actor->getParam()->getRes().mGParamList; + if (!gparam || !gparam->getSystem()) { + *name = actor->getName(); + return false; + } - sead::FixedSafeString<256> message; - // (%s)Acquiring from a low priority thread. Please change via ActorLinkConstDataAccess - message.format("(%s)低スレッドからの取得です。ActorLinkConstDataAccess経由に変更お願いします", - from.cstr()); - util::PrintDebug(message); - return false; + const auto& group_name = gparam->getSystem()->mSameGroupActorName.ref(); + if (group_name.isEmpty()) { + *name = actor->getName(); + return false; + } + + *name = group_name; + return true; +} + +bool ActorLinkConstDataAccess::checkFlag18() const { + auto* actor = getActor(); + return actor && actor->checkFlag(Actor::ActorFlag::_18); +} + +bool ActorLinkConstDataAccess::isPlayerTheConnectedParent() const { + auto* actor = getActor(); + if (!actor) + return false; + + auto* parent = sead::DynamicCast<Actor>(actor->getConnectedCalcParent()); + if (!parent) + return false; + + return parent->getProfile() == "Player"; +} + +void ActorLinkConstDataAccess::setThisActorAsParent(BaseProc* child, bool delete_parent_on_delete) { + auto* actor = getActor(); + if (!actor) + return; + child->setConnectedCalcParent(actor, delete_parent_on_delete); +} + +void ActorLinkConstDataAccess::setThisActorAsChild(BaseProc* parent, bool delete_child_on_delete) { + auto* actor = getActor(); + if (!actor) + return; + parent->setConnectedCalcChild(actor, delete_child_on_delete); +} + +bool ActorLinkConstDataAccess::isFlyingBalloon() const { + auto* actor = getActor(); + if (!actor) + return false; + bool* value; + return actor->getRootAi()->getAITreeVariable(&value, "IsFlyingBalloon") && *value; +} + +u32 ActorLinkConstDataAccess::getBalloonHungActorBaseProcID() const { + auto* actor = getActor(); + if (!actor) + return -1; + int* value; + if (!actor->getRootAi()->getAITreeVariable(&value, "BalloonHungActorBaseProcID")) + return -1; + return *value; +} + +bool ActorLinkConstDataAccess::checkFlag25() const { + auto* actor = getActor(); + return actor && actor->checkFlag(Actor::ActorFlag::_25); +} + +f32 ActorLinkConstDataAccess::getHorseMoveRadius() const { + auto* actor = getActor(); + if (!actor) + return -1.0; + return actor->getParam()->getRes().mGParamList->getHorseTargetedInfo()->mHorseMoveRadius.ref(); +} + +f32 ActorLinkConstDataAccess::getHorseAvoidOffset() const { + auto* actor = getActor(); + if (!actor) + return -1.0; + return actor->getParam()->getRes().mGParamList->getHorseTargetedInfo()->mHorseAvoidOffset.ref(); +} + +bool ActorLinkConstDataAccess::horseTargetedIsCircularMoveAlways() const { + auto* actor = getActor(); + if (!actor) + return false; + auto* gparam = actor->getParam()->getRes().mGParamList; + return gparam->getHorseTargetedInfo()->mIsCircularMoveAlways.ref(); +} + +const sead::Matrix34f& ActorLinkConstDataAccess::getActorMtx() { + const Actor* actor = mProc ? sead::DynamicCast<Actor>(mProc) : nullptr; + if (actor) + return actor->getMtx(); + return sead::Matrix34f::ident; } } // namespace ksys::act diff --git a/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.h b/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.h index 4c67c686..cd10f9ad 100644 --- a/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.h +++ b/src/KingSystem/ActorSystem/actActorLinkConstDataAccess.h @@ -1,62 +1,149 @@ #pragma once -#include <basis/seadTypes.h> #include <math/seadMatrix.h> -#include <prim/seadSafeString.h> +#include <math/seadVector.h> +#include <prim/seadRuntimeTypeInfo.h> +#include "KingSystem/ActorSystem/actActor.h" +#include "KingSystem/ActorSystem/actBaseProc.h" +#include "KingSystem/ActorSystem/actBaseProcAccessor.h" +#include "KingSystem/ActorSystem/actBaseProcLink.h" +#include "KingSystem/Utils/Types.h" namespace ksys { struct MesTransceiverId; -namespace act { +} // namespace ksys + +namespace ksys::map { +class Object; +class ObjectLinkData; +} // namespace ksys::map + +namespace ksys::res { +class GParamList; +class Shop; +} // namespace ksys::res + +namespace ksys::act { class Actor; -class BaseProc; /// Provides read-only access to actor data for safe, multi-threaded access. -class ActorLinkConstDataAccess { +class ActorLinkConstDataAccess : public BaseProcAccessor { public: ActorLinkConstDataAccess() = default; - explicit ActorLinkConstDataAccess(BaseProc* proc) { acquire(proc); } - /// Destructor that automatically releases any acquired BaseProc. - ~ActorLinkConstDataAccess(); - - ActorLinkConstDataAccess(const ActorLinkConstDataAccess&) = delete; - ActorLinkConstDataAccess& operator=(const ActorLinkConstDataAccess&) = delete; - ActorLinkConstDataAccess(ActorLinkConstDataAccess&& other) noexcept { - *this = std::move(other); - } - ActorLinkConstDataAccess& operator=(ActorLinkConstDataAccess&& other) noexcept { - std::swap(mAcquired, other.mAcquired); - std::swap(mProc, other.mProc); - return *this; - } + explicit ActorLinkConstDataAccess(BaseProc* proc) : BaseProcAccessor(proc) {} - /// Acquire a BaseProc. This increments its reference count. - /// If an actor was already acquired, it is released. - bool acquire(BaseProc* proc); + bool acquireActor(const BaseProcAccessor& other); - void release() { acquire(nullptr); } + bool hasProc() const { return BaseProcAccessor::hasProc(); } - bool hasProc() const { return mProc != nullptr; } + /// Checks whether the acquired BaseProc is `proc`. + bool hasProc(BaseProc* proc) const; + + /// Checks whether the acquired BaseProc and the BaseProcLink's actor are the same + /// by comparing the IDs. + bool hasProc(const BaseProcLink& link) const; + + template <typename T> + bool isDerivedFrom() const { + return sead::IsDerivedFrom<T>(mProc); + } const MesTransceiverId* getMessageTransceiverId() const; - const Actor* getActor() const; const sead::Matrix34f& getActorMtx(); -protected: - friend class ActorConstDataAccess; - friend class BaseProc; - friend class BaseProcHandle; - friend class BaseProcUnit; + bool linkAcquire(BaseProcLink* link) const; + bool linkAcquireImmediately(BaseProcLink* link) const; - bool mAcquired = false; - BaseProc* mProc = nullptr; -}; + void debugLog(s32, const sead::SafeString& method_name) const; -/// Acquire the specified BaseProc using `accessor`. Using ActorLinkConstDataAccess is mandatory -/// when acquiring from a low priority thread (see BaseProcMgr for a definition). -bool acquireProc(ActorLinkConstDataAccess* accessor, BaseProc* proc, const sead::SafeString& from, - s32 = 2); + bool isPlayerProfile() const; + bool isWeaponProfile() const; + bool isNPCProfile() const; + bool isEnemyProfile() const; -} // namespace act + const sead::SafeString& getProfile() const; + const sead::SafeString& getName() const; -} // namespace ksys + const sead::SafeString& getLiftType() const; + bool isDisableFreezeLift() const; + bool isDisableBurnLift() const; + + bool hasTag(const char* tag) const; + bool hasTag(u32 tag) const; + const char* getUniqueName() const; + u32 getId() const; + bool acquireConnectedCalcParent(BaseProcAccessor* accessor) const; + bool acquireConnectedCalcChild(BaseProcAccessor* accessor) const; + bool hasConnectedCalcParent() const; + bool checkFlag2B() const; + + bool deleteLater(BaseProc::DeleteReason reason) const; + bool deleteEx(BaseProc::DeleteReason reason) const; + bool sleep(BaseProc::SleepWakeReason reason) const; + bool wakeUp(BaseProc::SleepWakeReason reason) const; + bool setProperties(int x, const sead::Matrix34f& mtx, const sead::Vector3f& vel, + const sead::Vector3f& ang_vel, const sead::Vector3f& scale, + bool is_life_infinite, int i, int life) const; + bool setProperties(const sead::Matrix34f& mtx, const sead::Vector3f& vel, + const sead::Vector3f& ang_vel, const sead::Vector3f& scale, + bool is_life_infinite, int i, int life) const; + bool isStateSleep() const; + bool isStateCalc() const; + bool isDeletedOrDeleting() const; + + res::GParamList* getGParamList() const; + res::Shop* getShopData() const; + + const sead::SafeString& getAttackSpHitActor() const; + const sead::SafeString& getAttackSpHitTag() const; + const sead::SafeString& getAttackWeakHitTag() const; + f32 getAttackSpHitRatio() const; + s32 getAttackPower() const; + + bool checkLinkTagActivated(bool a, bool b); + map::ObjectLinkData* getMapObjectLinkData() const; + map::Object* getMapObject() const; + + s32 getEnemyRank() const; + + bool getSameGroupActorName(sead::SafeString* name) const; + + bool checkFlag18() const; + bool isPlayerTheConnectedParent() const; + + const sead::Vector3f& getPreviousPos() const; + + void setThisActorAsParent(BaseProc* child, bool delete_parent_on_delete); + void setThisActorAsChild(BaseProc* parent, bool delete_child_on_delete); + + bool isAttClientEnabled(const sead::SafeString& client) const; + + bool isFlyingBalloon() const; + u32 getBalloonHungActorBaseProcID() const; + + bool checkFlag25() const; + + f32 getHorseMoveRadius() const; + f32 getHorseAvoidOffset() const; + bool horseTargetedIsCircularMoveAlways() const; + +private: + Actor* getActor() const; + + u8 _10 = 0; +}; +KSYS_CHECK_SIZE_NX150(ActorLinkConstDataAccess, 0x18); + +inline bool acquireActor(BaseProcLink* link, ActorLinkConstDataAccess* accessor) { + return link->getProcInContext([accessor](BaseProc* proc, bool valid) { + if (!proc) { + if (!valid) + accessor->acquire(nullptr); + return false; + } + return accessor->acquire(sead::DynamicCast<Actor>(proc)); + }); +} + +} // namespace ksys::act diff --git a/src/KingSystem/ActorSystem/actActorSystem.h b/src/KingSystem/ActorSystem/actActorSystem.h index b147658b..ba09ecc7 100644 --- a/src/KingSystem/ActorSystem/actActorSystem.h +++ b/src/KingSystem/ActorSystem/actActorSystem.h @@ -6,7 +6,7 @@ namespace ksys::act { -class ActorConstDataAccess; +class ActorLinkConstDataAccess; // TODO: incomplete class ActorSystem { @@ -16,7 +16,7 @@ class ActorSystem { public: void onBaseProcMgrCalc(); - bool getPlayer(ActorConstDataAccess* accessor); + bool getPlayer(ActorLinkConstDataAccess* accessor); bool getAutoPlacementActorPos(const sead::SafeString& name, sead::Vector3f* pos) const; diff --git a/src/KingSystem/ActorSystem/actActorUtil.cpp b/src/KingSystem/ActorSystem/actActorUtil.cpp index 3f5e3a74..3b85c7d3 100644 --- a/src/KingSystem/ActorSystem/actActorUtil.cpp +++ b/src/KingSystem/ActorSystem/actActorUtil.cpp @@ -4,7 +4,7 @@ #include <random/seadGlobalRandom.h> #include "KingSystem/ActorSystem/Profiles/actRopeBase.h" #include "KingSystem/ActorSystem/actActor.h" -#include "KingSystem/ActorSystem/actActorConstDataAccess.h" +#include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h" #include "KingSystem/ActorSystem/actActorParam.h" #include "KingSystem/ActorSystem/actBaseProcLink.h" #include "KingSystem/ActorSystem/actInfoData.h" @@ -23,14 +23,14 @@ namespace ksys::act { namespace { -ActorConstDataAccess getAccessor(BaseProcLink* link) { - ActorConstDataAccess accessor; +ActorLinkConstDataAccess getAccessor(BaseProcLink* link) { + ActorLinkConstDataAccess accessor; acquireActor(link, &accessor); return accessor; } -ActorConstDataAccess getAccessor(Actor* actor) { - ActorConstDataAccess accessor{actor}; +ActorLinkConstDataAccess getAccessor(Actor* actor) { + ActorLinkConstDataAccess accessor{actor}; return accessor; } @@ -59,7 +59,7 @@ bool hasTag(BaseProcLink* link, const sead::SafeString& tag) { return hasTag(getAccessor(link), tag); } -bool hasTag(const ActorConstDataAccess& accessor, const sead::SafeString& tag) { +bool hasTag(const ActorLinkConstDataAccess& accessor, const sead::SafeString& tag) { return accessor.hasTag(tag.cstr()); } @@ -76,7 +76,7 @@ bool hasTag(BaseProcLink* link, u32 tag) { return hasTag(getAccessor(link), tag); } -bool hasTag(const ActorConstDataAccess& accessor, u32 tag) { +bool hasTag(const ActorLinkConstDataAccess& accessor, u32 tag) { return accessor.hasTag(tag); } @@ -105,7 +105,7 @@ bool hasOneTagAtLeast(BaseProcLink* link, const sead::SafeString& tags) { return false; } -bool hasOneTagAtLeast(const ActorConstDataAccess& accessor, const sead::SafeString& tags) { +bool hasOneTagAtLeast(const ActorLinkConstDataAccess& accessor, const sead::SafeString& tags) { sead::FixedSafeString<32> tag; for (auto it = tags.tokenBegin(","); tags.tokenEnd(",") != it; ++it) { it.get(&tag); @@ -268,11 +268,11 @@ ZukanType getZukanType(Actor* actor) { return ZukanType::Invalid; } -static bool isProfile(const ActorConstDataAccess& accessor, const sead::SafeString& profile) { +static bool isProfile(const ActorLinkConstDataAccess& accessor, const sead::SafeString& profile) { return accessor.hasProc() && accessor.getProfile() == profile; } -bool isPlayerProfile(const ActorConstDataAccess& accessor) { +bool isPlayerProfile(const ActorLinkConstDataAccess& accessor) { return isProfile(accessor, "Player"); } @@ -292,7 +292,7 @@ bool isCameraProfile(Actor* actor) { return isProfile(getAccessor(actor), "Camera"); } -bool isNPCProfile(const ActorConstDataAccess& accessor) { +bool isNPCProfile(const ActorLinkConstDataAccess& accessor) { return isProfile(accessor, "NPC"); } @@ -320,7 +320,7 @@ bool isDemoNPCProfile(Actor* actor) { return isProfile(getAccessor(actor), "DemoNPC"); } -bool isEnemyProfile(const ActorConstDataAccess& accessor) { +bool isEnemyProfile(const ActorLinkConstDataAccess& accessor) { if (!accessor.hasProc()) return false; @@ -349,7 +349,7 @@ bool isGuardianProfile(BaseProcLink* link) { return profile == "Guardian" || profile == "GuardianComponent"; } -bool isLargeEnemy(const ActorConstDataAccess& accessor) { +bool isLargeEnemy(const ActorLinkConstDataAccess& accessor) { if (!accessor.hasProc()) return false; @@ -362,7 +362,7 @@ bool isLargeEnemy(Actor* actor) { return isLargeEnemy(getAccessor(actor)); } -bool isGanonBeast(const ActorConstDataAccess& accessor) { +bool isGanonBeast(const ActorLinkConstDataAccess& accessor) { return accessor.hasProc() && accessor.getName() == "Enemy_GanonBeast"; } @@ -374,7 +374,7 @@ bool isNotLivingCreature(Actor* actor) { return isNotLivingCreature(getAccessor(actor)); } -bool isNotLivingCreature(const ActorConstDataAccess& accessor) { +bool isNotLivingCreature(const ActorLinkConstDataAccess& accessor) { if (isPlayerProfile(accessor)) return false; if (isNPCProfile(accessor)) @@ -392,7 +392,7 @@ bool isNotLivingCreature(BaseProcLink* link) { return isNotLivingCreature(getAccessor(link)); } -bool isWeaponProfile(const ActorConstDataAccess& accessor) { +bool isWeaponProfile(const ActorLinkConstDataAccess& accessor) { if (!accessor.hasProc()) return false; return isWeaponProfile(accessor.getName()); @@ -412,7 +412,7 @@ bool isWeaponProfile(BaseProcLink* link) { return isWeaponProfile(getAccessor(link)); } -bool isWeaponOrArmor(const ActorConstDataAccess& accessor) { +bool isWeaponOrArmor(const ActorLinkConstDataAccess& accessor) { if (!accessor.hasProc()) return false; @@ -429,7 +429,7 @@ bool isWeaponOrArmor(Actor* actor) { return isWeaponOrArmor(getAccessor(actor)); } -bool isBulletProfile(const ActorConstDataAccess& accessor) { +bool isBulletProfile(const ActorLinkConstDataAccess& accessor) { return isProfile(accessor, "Bullet"); } @@ -441,7 +441,7 @@ bool isBulletProfile(BaseProcLink* link) { return isBulletProfile(getAccessor(link)); } -bool isHorseProfile(const ActorConstDataAccess& accessor) { +bool isHorseProfile(const ActorLinkConstDataAccess& accessor) { return isProfile(accessor, "Horse"); } @@ -462,7 +462,7 @@ bool isStalfosParts(BaseProcLink* link) { return accessor.hasProc() && accessor.hasTag(tags::StalfosParts); } -bool isDoor(const ActorConstDataAccess& accessor) { +bool isDoor(const ActorLinkConstDataAccess& accessor) { return accessor.hasProc() && accessor.hasTag(tags::Door); } @@ -470,7 +470,7 @@ bool isDoor(BaseProcLink* link) { return isDoor(getAccessor(link)); } -bool isPreyOrSwarm(const ActorConstDataAccess& accessor) { +bool isPreyOrSwarm(const ActorLinkConstDataAccess& accessor) { if (!accessor.hasProc()) return false; const auto& profile = accessor.getProfile(); @@ -485,7 +485,7 @@ bool isPreyOrSwarm(BaseProcLink* link) { return isPreyOrSwarm(getAccessor(link)); } -bool isWolfOrBear(const ActorConstDataAccess& accessor) { +bool isWolfOrBear(const ActorLinkConstDataAccess& accessor) { if (!accessor.hasProc()) return false; return accessor.hasTag(tags::AnimalTypeWolf) || accessor.hasTag(tags::AnimalTypeBear); diff --git a/src/KingSystem/ActorSystem/actActorUtil.h b/src/KingSystem/ActorSystem/actActorUtil.h index 2e0a576e..44210f1f 100644 --- a/src/KingSystem/ActorSystem/actActorUtil.h +++ b/src/KingSystem/ActorSystem/actActorUtil.h @@ -18,7 +18,7 @@ class Object; namespace ksys::act { class Actor; -class ActorConstDataAccess; +class ActorLinkConstDataAccess; class BaseProcLink; enum class ArrowType { @@ -51,19 +51,19 @@ enum class ZukanType { bool hasTag(Actor* actor, const sead::SafeString& tag); bool hasTag(BaseProcLink* link, const sead::SafeString& tag); -bool hasTag(const ActorConstDataAccess& accessor, const sead::SafeString& tag); +bool hasTag(const ActorLinkConstDataAccess& accessor, const sead::SafeString& tag); bool hasTag(const sead::SafeString& actor, const sead::SafeString& tag); bool hasTag(Actor* actor, u32 tag); bool hasTag(BaseProcLink* link, u32 tag); -bool hasTag(const ActorConstDataAccess& accessor, u32 tag); +bool hasTag(const ActorLinkConstDataAccess& accessor, u32 tag); bool hasTag(const sead::SafeString& actor, u32 tag); /// Checks whether the actor has at least one of the specified tags. /// @param tags A comma separated list of tags. bool hasOneTagAtLeast(Actor* actor, const sead::SafeString& tags); bool hasOneTagAtLeast(BaseProcLink* link, const sead::SafeString& tags); -bool hasOneTagAtLeast(const ActorConstDataAccess& accessor, const sead::SafeString& tags); +bool hasOneTagAtLeast(const ActorLinkConstDataAccess& accessor, const sead::SafeString& tags); bool shouldSkipSpawnWhenRaining(map::Object* obj); bool shouldSkipSpawnIfGodForestOff(map::Object* obj); @@ -88,48 +88,48 @@ ArrowType arrowTypeFromString(const sead::SafeString& name); ZukanType getZukanType(al::ByamlIter* iter); ZukanType getZukanType(Actor* actor); -bool isPlayerProfile(const ActorConstDataAccess& accessor); +bool isPlayerProfile(const ActorLinkConstDataAccess& accessor); bool isPlayerProfile(Actor* actor); bool isPlayerProfile(BaseProcLink* link); bool isCameraProfile(Actor* actor); -bool isNPCProfile(const ActorConstDataAccess& accessor); +bool isNPCProfile(const ActorLinkConstDataAccess& accessor); bool isNPCProfile(Actor* actor); bool isNPCProfile(BaseProcLink* link); bool isNPCOffPodFromWeapon(Actor* actor); bool isDemoNPCProfile(Actor* actor); -bool isEnemyProfile(const ActorConstDataAccess& accessor); +bool isEnemyProfile(const ActorLinkConstDataAccess& accessor); bool isEnemyProfile(Actor* actor); bool isEnemyProfile(BaseProcLink* link); bool isGuardianProfile(BaseProcLink* link); -bool isLargeEnemy(const ActorConstDataAccess& accessor); +bool isLargeEnemy(const ActorLinkConstDataAccess& accessor); bool isLargeEnemy(Actor* actor); -bool isGanonBeast(const ActorConstDataAccess& accessor); +bool isGanonBeast(const ActorLinkConstDataAccess& accessor); bool isGanonBeast(BaseProcLink* link); bool isNotLivingCreature(Actor* actor); -bool isNotLivingCreature(const ActorConstDataAccess& accessor); +bool isNotLivingCreature(const ActorLinkConstDataAccess& accessor); bool isNotLivingCreature(BaseProcLink* link); -bool isWeaponProfile(const ActorConstDataAccess& accessor); +bool isWeaponProfile(const ActorLinkConstDataAccess& accessor); bool isWeaponProfile(const sead::SafeString& actor); bool isWeaponProfile(Actor* actor); bool isWeaponProfile(BaseProcLink* link); -bool isWeaponOrArmor(const ActorConstDataAccess& accessor); +bool isWeaponOrArmor(const ActorLinkConstDataAccess& accessor); bool isWeaponOrArmor(Actor* actor); -bool isBulletProfile(const ActorConstDataAccess& accessor); +bool isBulletProfile(const ActorLinkConstDataAccess& accessor); bool isBulletProfile(Actor* actor); bool isBulletProfile(BaseProcLink* link); -bool isHorseProfile(const ActorConstDataAccess& accessor); +bool isHorseProfile(const ActorLinkConstDataAccess& accessor); bool isHorseProfile(Actor* actor); bool isHorseProfile(BaseProcLink* link); @@ -138,14 +138,14 @@ bool isGrabAttClientEnabled(void* x, BaseProcLink* link); bool isStalfosParts(BaseProcLink* link); -bool isDoor(const ActorConstDataAccess& accessor); +bool isDoor(const ActorLinkConstDataAccess& accessor); bool isDoor(BaseProcLink* link); -bool isPreyOrSwarm(const ActorConstDataAccess& accessor); +bool isPreyOrSwarm(const ActorLinkConstDataAccess& accessor); bool isPreyOrSwarm(Actor* actor); bool isPreyOrSwarm(BaseProcLink* link); -bool isWolfOrBear(const ActorConstDataAccess& accessor); +bool isWolfOrBear(const ActorLinkConstDataAccess& accessor); bool isWolfOrBear(Actor* actor); bool isWolfOrBear(BaseProcLink* link); diff --git a/src/KingSystem/ActorSystem/actBaseProc.cpp b/src/KingSystem/ActorSystem/actBaseProc.cpp index ea4f8884..cce31c21 100644 --- a/src/KingSystem/ActorSystem/actBaseProc.cpp +++ b/src/KingSystem/ActorSystem/actBaseProc.cpp @@ -1,7 +1,7 @@ #include "KingSystem/ActorSystem/actBaseProc.h" #include <thread/seadThread.h> #include <time/seadTickSpan.h> -#include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h" +#include "KingSystem/ActorSystem/actBaseProcAccessor.h" #include "KingSystem/ActorSystem/actBaseProcHandle.h" #include "KingSystem/ActorSystem/actBaseProcJobHandler.h" #include "KingSystem/ActorSystem/actBaseProcLink.h" @@ -595,7 +595,7 @@ bool BaseProc::setStateFlag(u32 flag_bit) { return BaseProcMgr::instance()->setProcFlag(*this, flag_bit); } -bool BaseProc::acquire(ActorLinkConstDataAccess& accessor) { +bool BaseProc::acquire(BaseProcAccessor& accessor) { if (mState == State::Delete) return false; diff --git a/src/KingSystem/ActorSystem/actBaseProc.h b/src/KingSystem/ActorSystem/actBaseProc.h index fb9d3142..48c99176 100644 --- a/src/KingSystem/ActorSystem/actBaseProc.h +++ b/src/KingSystem/ActorSystem/actBaseProc.h @@ -16,7 +16,7 @@ namespace ksys::act { -class ActorLinkConstDataAccess; +class BaseProcAccessor; class BaseProc; class BaseProcLinkData; class BaseProcJobHandler; @@ -103,10 +103,10 @@ public: } bool isDeleteOrInvalid() const { return mState >= act::BaseProc::State::Delete; } - /// For BaseProcLink or ActorLinkConstDataAccess. - bool acquire(ActorLinkConstDataAccess& accessor); + /// For BaseProcLink or BaseProcAccessor. + bool acquire(BaseProcAccessor& accessor); BaseProcLinkData* getBaseProcLinkData() const { return mBaseProcLinkData; } - /// For BaseProcLink or ActorLinkConstDataAccess. + /// For BaseProcLink or BaseProcAccessor. void release(); BaseProc* getConnectedCalcParent() const; diff --git a/src/KingSystem/ActorSystem/actBaseProcAccessor.cpp b/src/KingSystem/ActorSystem/actBaseProcAccessor.cpp new file mode 100644 index 00000000..4333471a --- /dev/null +++ b/src/KingSystem/ActorSystem/actBaseProcAccessor.cpp @@ -0,0 +1,48 @@ +#include "KingSystem/ActorSystem/actBaseProcAccessor.h" +#include "KingSystem/ActorSystem/actBaseProc.h" +#include "KingSystem/ActorSystem/actBaseProcMgr.h" +#include "KingSystem/Utils/Debug.h" + +namespace ksys::act { + +BaseProcAccessor::~BaseProcAccessor() { + if (mAcquired && mProc) + mProc->release(); + + mAcquired = false; + mProc = nullptr; +} + +bool BaseProcAccessor::acquire(BaseProc* proc) { + if (mProc) { + if (mAcquired) + mProc->release(); + + mAcquired = false; + mProc = nullptr; + } + + return proc && proc->acquire(*this); +} + +bool acquireProc(BaseProcAccessor* accessor, BaseProc* proc, const sead::SafeString& from, s32) { + bool acquired = false; + + if (accessor) { + acquired = accessor->acquire(proc); + if (!acquired) + return false; + } + + if (acquired || BaseProcMgr::instance()->isHighPriorityThread()) + return true; + + sead::FixedSafeString<256> message; + // (%s)Acquiring from a low priority thread. Please change via ActorLinkConstDataAccess + message.format("(%s)低スレッドからの取得です。ActorLinkConstDataAccess経由に変更お願いします", + from.cstr()); + util::PrintDebug(message); + return false; +} + +} // namespace ksys::act diff --git a/src/KingSystem/ActorSystem/actBaseProcAccessor.h b/src/KingSystem/ActorSystem/actBaseProcAccessor.h new file mode 100644 index 00000000..da7376ff --- /dev/null +++ b/src/KingSystem/ActorSystem/actBaseProcAccessor.h @@ -0,0 +1,50 @@ +#pragma once + +#include <basis/seadTypes.h> +#include <prim/seadSafeString.h> +#include <utility> + +namespace ksys::act { + +class BaseProc; + +/// Holds a reference to a BaseProc for safe, multi-threaded access. +class BaseProcAccessor { +public: + BaseProcAccessor() = default; + explicit BaseProcAccessor(BaseProc* proc) { acquire(proc); } + /// Destructor that automatically releases any acquired BaseProc. + ~BaseProcAccessor(); + + BaseProcAccessor(const BaseProcAccessor&) = delete; + BaseProcAccessor& operator=(const BaseProcAccessor&) = delete; + BaseProcAccessor(BaseProcAccessor&& other) noexcept { *this = std::move(other); } + BaseProcAccessor& operator=(BaseProcAccessor&& other) noexcept { + std::swap(mAcquired, other.mAcquired); + std::swap(mProc, other.mProc); + return *this; + } + + /// Acquire a BaseProc. This increments its reference count. + /// If an actor was already acquired, it is released. + bool acquire(BaseProc* proc); + + void release() { acquire(nullptr); } + + bool hasProc() const { return mProc != nullptr; } + +protected: + friend class ActorLinkConstDataAccess; + friend class BaseProc; + friend class BaseProcHandle; + friend class BaseProcUnit; + + bool mAcquired = false; + BaseProc* mProc = nullptr; +}; + +/// Acquire the specified BaseProc using `accessor`. Using ActorLinkConstDataAccess is mandatory +/// when acquiring from a low priority thread (see BaseProcMgr for a definition). +bool acquireProc(BaseProcAccessor* accessor, BaseProc* proc, const sead::SafeString& from, s32 = 2); + +} // namespace ksys::act diff --git a/src/KingSystem/ActorSystem/actBaseProcHandle.cpp b/src/KingSystem/ActorSystem/actBaseProcHandle.cpp index cc780cc3..371f7c43 100644 --- a/src/KingSystem/ActorSystem/actBaseProcHandle.cpp +++ b/src/KingSystem/ActorSystem/actBaseProcHandle.cpp @@ -1,7 +1,7 @@ #include "KingSystem/ActorSystem/actBaseProcHandle.h" #include <prim/seadScopedLock.h> -#include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h" #include "KingSystem/ActorSystem/actBaseProc.h" +#include "KingSystem/ActorSystem/actBaseProcAccessor.h" #include "KingSystem/Utils/Debug.h" namespace ksys::act { @@ -80,7 +80,7 @@ BaseProc* BaseProcHandle::releaseProc() { BaseProc* proc = nullptr; { - ActorLinkConstDataAccess accessor; + BaseProcAccessor accessor; { const auto lock = sead::makeScopedLock(unit->getCS()); if (unit->compareExchangeHandle(this, &gDummyProcHandle)) { @@ -106,7 +106,7 @@ BaseProc* BaseProcHandle::releaseAndWakeProc() { BaseProc* proc = nullptr; { - ActorLinkConstDataAccess accessor; + BaseProcAccessor accessor; { const auto lock = sead::makeScopedLock(unit->getCS()); if (unit->compareExchangeHandle(this, &gDummyProcHandle)) { @@ -172,7 +172,7 @@ bool BaseProcUnit::deleteProc([[maybe_unused]] u32 x, BaseProcHandle* handle) { __builtin_assume(x); #endif - ActorLinkConstDataAccess accessor; + BaseProcAccessor accessor; { const auto lock = sead::makeScopedLock(mCS); diff --git a/src/KingSystem/ActorSystem/actBaseProcLink.cpp b/src/KingSystem/ActorSystem/actBaseProcLink.cpp index 935a1f33..d2dcce17 100644 --- a/src/KingSystem/ActorSystem/actBaseProcLink.cpp +++ b/src/KingSystem/ActorSystem/actBaseProcLink.cpp @@ -1,8 +1,8 @@ #include "KingSystem/ActorSystem/actBaseProcLink.h" #include <prim/seadScopedLock.h> #include <thread/seadThread.h> -#include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h" #include "KingSystem/ActorSystem/actBaseProc.h" +#include "KingSystem/ActorSystem/actBaseProcAccessor.h" #include "KingSystem/ActorSystem/actBaseProcMgr.h" namespace ksys::act { @@ -39,7 +39,7 @@ bool BaseProcLink::hasProcById(BaseProc* proc) const { return proc != nullptr & mId != cInvalidId && mId == proc->getId(); } -BaseProc* BaseProcLink::getProc(ActorLinkConstDataAccess* accessor, BaseProc* other_proc) const { +BaseProc* BaseProcLink::getProc(BaseProcAccessor* accessor, BaseProc* other_proc) const { return getProcInContext([&](BaseProc* proc, bool) -> BaseProc* { if (proc && acquireProc(accessor, proc, "frm::BaseProcLink") && BaseProcMgr::instance()->isAccessingProcSafe(proc, other_proc)) { @@ -49,7 +49,7 @@ BaseProc* BaseProcLink::getProc(ActorLinkConstDataAccess* accessor, BaseProc* ot }); } -BaseProc* BaseProcLink::getProc(ActorLinkConstDataAccess* accessor) const { +BaseProc* BaseProcLink::getProc(BaseProcAccessor* accessor) const { return getProcInContext([&](BaseProc* proc, bool) -> BaseProc* { if (proc && acquireProc(accessor, proc, "frm::BaseProcLink")) return proc; diff --git a/src/KingSystem/ActorSystem/actBaseProcLink.h b/src/KingSystem/ActorSystem/actBaseProcLink.h index 5d997c29..accf3d20 100644 --- a/src/KingSystem/ActorSystem/actBaseProcLink.h +++ b/src/KingSystem/ActorSystem/actBaseProcLink.h @@ -11,7 +11,7 @@ namespace ksys::act { -class ActorLinkConstDataAccess; +class BaseProcAccessor; class BaseProc; class BaseProcLinkData; @@ -29,8 +29,8 @@ public: bool hasProcInCalcState() const; bool hasProcById(BaseProc* proc) const; - BaseProc* getProc(ActorLinkConstDataAccess* accessor, BaseProc* other_proc) const; - BaseProc* getProc(ActorLinkConstDataAccess* accessor) const; + BaseProc* getProc(BaseProcAccessor* accessor, BaseProc* other_proc) const; + BaseProc* getProc(BaseProcAccessor* accessor) const; /// Acquire the specified BaseProc. /// If a BaseProc has already been specified, it is released. @@ -44,7 +44,7 @@ public: bool isAccessingSpecifiedProcUnsafe(BaseProc* other) const; template <typename Function> - auto getProcInContext(const Function& function) const; + KSYS_ALWAYS_INLINE auto getProcInContext(const Function& function) const; private: static constexpr u32 cInvalidId = -1; diff --git a/src/KingSystem/ActorSystem/actPhysicsUserTag.cpp b/src/KingSystem/ActorSystem/actPhysicsUserTag.cpp index 7e46a767..1f4dcdeb 100644 --- a/src/KingSystem/ActorSystem/actPhysicsUserTag.cpp +++ b/src/KingSystem/ActorSystem/actPhysicsUserTag.cpp @@ -1,6 +1,6 @@ #include "KingSystem/ActorSystem/actPhysicsUserTag.h" #include "KingSystem/ActorSystem/actActor.h" -#include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h" +#include "KingSystem/ActorSystem/actBaseProcAccessor.h" #include "KingSystem/ActorSystem/actBaseProcMgr.h" namespace ksys::act { @@ -9,7 +9,7 @@ PhysicsUserTag::PhysicsUserTag(Actor* actor) : mActor(actor) {} PhysicsUserTag::~PhysicsUserTag() = default; -Actor* PhysicsUserTag::getActor(ActorLinkConstDataAccess* accessor, Actor* other_actor) const { +Actor* PhysicsUserTag::getActor(BaseProcAccessor* accessor, Actor* other_actor) const { if (mActor != nullptr) { if (mActor != other_actor && !BaseProcMgr::instance()->isAccessingProcSafe(mActor, nullptr)) return mActor; @@ -19,7 +19,7 @@ Actor* PhysicsUserTag::getActor(ActorLinkConstDataAccess* accessor, Actor* other return mActor; } -bool PhysicsUserTag::acquireActor(ActorLinkConstDataAccess* accessor) const { +bool PhysicsUserTag::acquireActor(BaseProcAccessor* accessor) const { return accessor->acquire(mActor); } diff --git a/src/KingSystem/ActorSystem/actPhysicsUserTag.h b/src/KingSystem/ActorSystem/actPhysicsUserTag.h index 257e281c..5bd22670 100644 --- a/src/KingSystem/ActorSystem/actPhysicsUserTag.h +++ b/src/KingSystem/ActorSystem/actPhysicsUserTag.h @@ -6,7 +6,7 @@ namespace ksys::act { class Actor; -class ActorLinkConstDataAccess; +class BaseProcAccessor; class PhysicsUserTag : public phys::UserTag { SEAD_RTTI_OVERRIDE(PhysicsUserTag, phys::UserTag) @@ -15,8 +15,8 @@ public: explicit PhysicsUserTag(Actor* actor); ~PhysicsUserTag() override; - Actor* getActor(ActorLinkConstDataAccess* accessor, Actor* other_actor) const; - bool acquireActor(ActorLinkConstDataAccess* accessor) const; + Actor* getActor(BaseProcAccessor* accessor, Actor* other_actor) const; + bool acquireActor(BaseProcAccessor* accessor) const; Actor* getActor() const { return mActor; } |
