summaryrefslogtreecommitdiff
path: root/src/KingSystem
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2020-11-17 00:54:46 +0100
committerGitHub <noreply@github.com>2020-11-17 00:54:46 +0100
commit4d4edbfe87e77c4e712e7fef7ed8087fff18220e (patch)
tree05b09142b74869f74779a00deff410019b8dcaac /src/KingSystem
parentb0498a15bf6f1782f1429ffbd0b03c187f61d7c9 (diff)
parentd4f80d7cf97641742dd56cabc0b1d503cfdf7b0d (diff)
Merge pull request #15 from notyourav/placement
implement map::Object getters
Diffstat (limited to 'src/KingSystem')
-rw-r--r--src/KingSystem/ActorSystem/CMakeLists.txt2
-rw-r--r--src/KingSystem/ActorSystem/actBaseProc.h2
-rw-r--r--src/KingSystem/ActorSystem/actBaseProcMgr.h2
-rw-r--r--src/KingSystem/ActorSystem/actDebug.cpp12
-rw-r--r--src/KingSystem/ActorSystem/actDebug.h24
-rw-r--r--src/KingSystem/Map/CMakeLists.txt6
-rw-r--r--src/KingSystem/Map/mapDebug.cpp3
-rw-r--r--src/KingSystem/Map/mapDebug.h11
-rw-r--r--src/KingSystem/Map/mapObject.cpp364
-rw-r--r--src/KingSystem/Map/mapObject.h105
-rw-r--r--src/KingSystem/Map/mapObjectLink.cpp21
-rw-r--r--src/KingSystem/Map/mapObjectLink.h98
-rw-r--r--src/KingSystem/Map/mapPlacementMgr.cpp7
-rw-r--r--src/KingSystem/Map/mapPlacementMgr.h119
14 files changed, 763 insertions, 13 deletions
diff --git a/src/KingSystem/ActorSystem/CMakeLists.txt b/src/KingSystem/ActorSystem/CMakeLists.txt
index e5c354bb..05aff8cd 100644
--- a/src/KingSystem/ActorSystem/CMakeLists.txt
+++ b/src/KingSystem/ActorSystem/CMakeLists.txt
@@ -40,6 +40,8 @@ target_sources(uking PRIVATE
actBaseProcMgr.h
actBaseProcUnit.cpp
actBaseProcUnit.h
+ actDebug.cpp
+ actDebug.h
actInfoData.cpp
actInfoData.h
actInstParamPack.cpp
diff --git a/src/KingSystem/ActorSystem/actBaseProc.h b/src/KingSystem/ActorSystem/actBaseProc.h
index c7636998..de5a1a86 100644
--- a/src/KingSystem/ActorSystem/actBaseProc.h
+++ b/src/KingSystem/ActorSystem/actBaseProc.h
@@ -87,6 +87,8 @@ public:
void setPriority(u8 priority) { mPriority = priority; }
State getState() const { return mState; }
+ bool isInit() const { return mState == State::Init; }
+ bool isCalc() const { return mState == State::Calc; }
bool isDeletedOrDeleting() const {
return mState == State::Delete || mStateFlags.isOn(StateFlags::RequestDelete);
}
diff --git a/src/KingSystem/ActorSystem/actBaseProcMgr.h b/src/KingSystem/ActorSystem/actBaseProcMgr.h
index a1ce35d8..f39b8197 100644
--- a/src/KingSystem/ActorSystem/actBaseProcMgr.h
+++ b/src/KingSystem/ActorSystem/actBaseProcMgr.h
@@ -163,6 +163,8 @@ public:
Status getStatus() const { return mStatus; }
u32 getNumJobTypes() const { return mNumJobTypes; }
+ bool checkGetActorOk(BaseProc* proc, void* a2);
+
private:
void doAddToUpdateStateList_(BaseProc& proc);
diff --git a/src/KingSystem/ActorSystem/actDebug.cpp b/src/KingSystem/ActorSystem/actDebug.cpp
new file mode 100644
index 00000000..e30ad960
--- /dev/null
+++ b/src/KingSystem/ActorSystem/actDebug.cpp
@@ -0,0 +1,12 @@
+#include "KingSystem/ActorSystem/actDebug.h"
+#include <prim/seadSafeString.h>
+
+namespace ksys::act {
+
+SEAD_SINGLETON_DISPOSER_IMPL(ActorDebug)
+
+const char* ActorDebug::getNullStr(HashUnused*) {
+ return &sead::SafeString::cNullChar;
+}
+
+} // namespace ksys::act
diff --git a/src/KingSystem/ActorSystem/actDebug.h b/src/KingSystem/ActorSystem/actDebug.h
new file mode 100644
index 00000000..5342d341
--- /dev/null
+++ b/src/KingSystem/ActorSystem/actDebug.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <heap/seadDisposer.h>
+#include "KingSystem/Utils/Types.h"
+
+namespace ksys::act {
+
+class ActorDebug {
+ SEAD_SINGLETON_DISPOSER(ActorDebug)
+public:
+ struct HashUnused {
+ u32 hash = 0;
+ u32 b;
+ };
+
+ const char* getNullStr(HashUnused* u);
+
+ u8 TEMP1[0x2F0];
+ f32 mDispDistanceMultiplier;
+ u8 TEMP2[0x114];
+};
+KSYS_CHECK_SIZE_NX150(ActorDebug, 0x428);
+
+} // namespace ksys::act
diff --git a/src/KingSystem/Map/CMakeLists.txt b/src/KingSystem/Map/CMakeLists.txt
index dd604dc3..858d21a3 100644
--- a/src/KingSystem/Map/CMakeLists.txt
+++ b/src/KingSystem/Map/CMakeLists.txt
@@ -1,7 +1,13 @@
target_sources(uking PRIVATE
mapTypes.h
+ mapDebug.cpp
+ mapDebug.h
mapMubinIter.cpp
mapMubinIter.h
mapObject.cpp
mapObject.h
+ mapObjectLink.cpp
+ mapObjectLink.h
+ mapPlacementMgr.cpp
+ mapPlacementMgr.h
)
diff --git a/src/KingSystem/Map/mapDebug.cpp b/src/KingSystem/Map/mapDebug.cpp
new file mode 100644
index 00000000..0269169b
--- /dev/null
+++ b/src/KingSystem/Map/mapDebug.cpp
@@ -0,0 +1,3 @@
+#include "KingSystem/Map/mapDebug.h"
+
+namespace ksys::map {} // namespace ksys::map
diff --git a/src/KingSystem/Map/mapDebug.h b/src/KingSystem/Map/mapDebug.h
new file mode 100644
index 00000000..28c8b2cc
--- /dev/null
+++ b/src/KingSystem/Map/mapDebug.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <prim/seadSafeString.h>
+
+namespace ksys::map {
+
+class Object;
+
+bool printDebugMsg(Object* object, const sead::SafeString& msg, const char* config_name);
+
+} // namespace ksys::map
diff --git a/src/KingSystem/Map/mapObject.cpp b/src/KingSystem/Map/mapObject.cpp
index 0fc9714a..92cfb6af 100644
--- a/src/KingSystem/Map/mapObject.cpp
+++ b/src/KingSystem/Map/mapObject.cpp
@@ -1,7 +1,371 @@
#include "KingSystem/Map/mapObject.h"
+#include "KingSystem/ActorSystem/actBaseProcMgr.h"
+#include "KingSystem/Utils/Debug.h"
namespace ksys::map {
Object::Object() = default;
+Object::~Object() {
+ if (mLinkData != nullptr) {
+ mLinkData->release(this, true);
+ mLinkData = nullptr;
+ }
}
+
+void Object::free() {
+ mId = 0;
+ _10 = nullptr;
+ _18 = nullptr;
+ _20 = nullptr;
+
+ if (mProc)
+ mProc = nullptr;
+
+ // TODO: figure out what this is
+ mFlags0.reset(Flag0::Freed);
+
+ mHardModeFlags.reset(HardModeFlag::ActorCreated);
+
+ if (mFlags0.isOn(Flag0::_80000))
+ mFlags0.set(Flag0::_40000);
+ else
+ mFlags0.set(Flag0::_8);
+
+ if (mLinkData)
+ mLinkData->field_57 = 0;
+}
+
+// NON_MATCHING: functionally equivalent; CSEL instruction flipped
+bool Object::getActorWithAccessor(act::ActorLinkConstDataAccess& accessor) const {
+ act::BaseProcMgr* instance = act::BaseProcMgr::instance();
+
+ if (instance == nullptr || !instance->isHighPriorityThread() || mProc == nullptr)
+ return accessor.acquire(nullptr);
+
+ if (mProc->isInit() || mProc->isCalc())
+ return accessor.acquire(mProc);
+
+ return accessor.acquire(nullptr);
+}
+
+act::Actor* Object::getActor() const {
+ return sead::DynamicCast<act::Actor>(mProc);
+}
+
+void Object::registerBaseProc(act::BaseProc* proc) {
+ const char* sActorStateStrings[4] = {"Init", "Calc", "Sleep", "Delete"};
+
+ if (mProc != nullptr && mProc != proc) {
+ sead::FixedSafeString<1000> message;
+ message.format("%p (%s:%p:%s) → (%s:%p:%s) \n", this, mProc->getName().cstr(), mProc,
+ sActorStateStrings[static_cast<s32>(mProc->getState())],
+ proc->getName().cstr(), proc,
+ sActorStateStrings[static_cast<s32>(proc->getState())]);
+ util::PrintDebug(message);
+ }
+ mProc = proc;
+
+ mFlags0.set(Flag0::_80);
+ mFlags0.reset(Flag0::_80000000);
+ mHardModeFlags.set(HardModeFlag::ActorCreated);
+}
+
+void Object::setBaseProcDirect(act::BaseProc* proc) {
+ mProc = proc;
+}
+
+bool Object::checkActorDataFlag(const PlacementActors* pa, ActorData::Flag flag) const {
+ return pa->mActorData[mActorDataIdx].mFlags.isOnBit(flag);
+}
+
+bool Object::isEnemyOrNpcOrActiveOrMapPassive() const {
+ if (mActorFlags8.isOn(ActorFlag8::EnemyOrNpcOrActiveOrAreaOrAirWall))
+ return true;
+
+ auto pa = PlacementMgr::instance()->mPlacementActors;
+ if (pa == nullptr)
+ return false;
+
+ return !checkActorDataFlag(pa, ActorData::Flag::MapPassiveOrFlag1);
+}
+
+bool Object::isNpcOrActiveOrMapPassiveOrFlag1() const {
+ auto actFlags = mActorFlags8;
+ if (actFlags.isZero())
+ return true;
+
+ auto pa = PlacementMgr::instance()->mPlacementActors;
+ if (pa == nullptr)
+ return false;
+
+ if (checkActorDataFlag(pa, ActorData::Flag::_16) ||
+ actFlags.isOn(ActorFlag8::EnemyOrNpcOrActiveOrAreaOrAirWall))
+ return false;
+
+ return checkActorDataFlag(pa, ActorData::Flag::MapPassiveOrFlag1);
+}
+
+bool Object::isMapPassive(const PlacementActors* pa) const {
+ if (mActorFlags8.isZero())
+ return true;
+
+ if (pa == nullptr)
+ return false;
+
+ if (pa->mActorData[mActorDataIdx].mFlags.isOnBit(ActorData::Flag::_16) ||
+ mActorFlags8.isOn(ActorFlag8::EnemyOrNpcOrActiveOrAreaOrAirWall))
+ return false;
+
+ return checkActorDataFlag(pa, ActorData::Flag::MapPassiveOrFlag1);
+}
+
+bool Object::isEnemyOrNpc(const PlacementActors* pa) const {
+ return checkActorDataFlag(pa, ActorData::Flag::EnemyOrNpc_DisableFlashback);
+}
+
+bool Object::isFlags8Cleared() const {
+ return mActorFlags8.isZero();
+}
+
+f32 Object::getDispDistance(const ActorData* data, bool get_diameter, u32 unused,
+ bool ignore_radius) const {
+ if (data->mFlags.isOnBit(ActorData::Flag::TraverseDistReset))
+ return 0.0;
+
+ f32 dist = getTraverseDist(data, get_diameter, unused, ignore_radius);
+ f32 mult = getDispDistanceMultiplier();
+
+ if (dist > 0.0)
+ return dist * mult;
+ else
+ return 100.0 * mult;
+}
+
+f32 Object::getDispDistance(const PlacementActors* pa, bool get_diameter,
+ bool ignore_radius) const {
+ auto* dat = &pa->mActorData[mActorDataIdx];
+
+ return getDispDistance(dat, get_diameter, 0, ignore_radius);
+}
+
+f32 Object::getDispDistance(bool get_diameter, bool ignore_radius) const {
+ auto pa = PlacementMgr::instance()->mPlacementActors;
+
+ return getDispDistance(pa, get_diameter, ignore_radius);
+}
+
+[[gnu::noinline]] f32 Object::getTraverseDist(const ActorData* data, bool get_diameter, u32,
+ bool ignore_radius) const {
+ using DFlag = ActorData::Flag;
+
+ f32 dist = 0.0;
+
+ if (mFlags.isOn(Flag::HasTraversePos) && !ignore_radius) {
+ mMubinIter.tryGetParamFloatByKey(&dist, "TraverseRadiusXZ");
+ if (get_diameter)
+ dist = dist * 2;
+ }
+
+ // TODO: inline here?
+ if (data->mFlags.isOnBit(DFlag::TraverseDistReset))
+ return dist + 0.0;
+
+ if (data->mFlags.isOnBit(DFlag::TraverseDist400) ||
+ data->mFlags.isOnBit(DFlag::TraverseDist200) ||
+ data->mFlags.isOnBit(DFlag::TraverseDist4000) ||
+ data->mFlags.isOnBit(DFlag::TraverseDist800))
+ return mTraverseDist + dist;
+
+ if (data->mFlags.isOffBit(DFlag::TraverseDist2000))
+ return mTraverseDist + dist;
+
+ return mTraverseDist;
+}
+
+f32 Object::getTraverseDistForLOD() const {
+ using DFlag = ActorData::Flag;
+
+ auto* data = &PlacementMgr::instance()->mPlacementActors->mActorData[mActorDataIdx];
+ f32 dist = 0.0;
+
+ if (data->mFlags.isOnBit(ActorData::Flag::TraverseDistReset))
+ return 0.0;
+
+ if (data->mFlags.isOnBit(ActorData::Flag::TraverseDistReset))
+ dist = 0.0;
+
+ else if (data->mFlags.isOnBit(DFlag::TraverseDist400) ||
+ data->mFlags.isOnBit(DFlag::TraverseDist200) ||
+ data->mFlags.isOnBit(DFlag::TraverseDist4000) ||
+ data->mFlags.isOnBit(DFlag::TraverseDist800))
+ dist = mTraverseDist + 0.0;
+
+ else if (data->mFlags.isOffBit(DFlag::TraverseDist2000))
+ dist = mTraverseDist + 0.0;
+ else
+ dist = mTraverseDist;
+
+ f32 mult = getDispDistanceMultiplier();
+
+ if (dist > 0.0)
+ return dist * mult;
+ else
+ return 100.0 * mult;
+}
+
+sead::Vector3f Object::getScale() const {
+ sead::Vector3f vec;
+
+ mMubinIter.getScale(&vec);
+ return vec;
+}
+
+const char* Object::getUnitConfigName() const {
+ auto* mgr = PlacementMgr::instance();
+
+ if (mgr != nullptr && mgr->mPlacementActors != nullptr)
+ return mgr->mPlacementActors->mActorData[mActorDataIdx].mActorName.cstr();
+
+ return getUnitConfigNameFromByaml();
+}
+
+const char* Object::getUnitConfigNameFromByaml() const {
+ const char* result;
+ if (!mMubinIter.tryGetParamStringByKey(&result, "UnitConfigName"))
+ result = "";
+
+ return result;
+}
+
+Object* Object::findPlacementLODLinkObject(const PlacementActors*) const {
+ if (!mLinkData)
+ return nullptr;
+
+ ObjectLink* result = mLinkData->mLinksToSelf.findLinkWithType(MapLinkDefType::PlacementLOD);
+ if (result)
+ return result->other_obj;
+
+ return nullptr;
+}
+
+Object* Object::findPlacementLODLinkObject() const {
+ if (!mLinkData)
+ return nullptr;
+
+ ObjectLink* result = mLinkData->mLinksToSelf.findLinkWithType(MapLinkDefType::PlacementLOD);
+ if (result)
+ return result->other_obj;
+
+ return nullptr;
+}
+
+const char* Object::getHashIdStringDebug() const {
+ act::ActorDebug::HashUnused t;
+
+ const char* terminator;
+
+ if (mMubinIter.tryGetParamUIntByKey(&t.hash, "HashId"))
+ terminator = act::ActorDebug::instance()->getNullStr(&t);
+ else
+ terminator = "";
+
+ return terminator;
+}
+
+const char* Object::getHashIdStringDebug_0() const {
+ act::ActorDebug::HashUnused t;
+
+ const char* terminator;
+
+ if (mMubinIter.tryGetParamUIntByKey(&t.hash, "HashId"))
+ terminator = act::ActorDebug::instance()->getNullStr(&t);
+ else
+ terminator = "";
+
+ return terminator;
+}
+
+void* Object::getRails() const {
+ if (!mLinkData)
+ return nullptr;
+
+ return mLinkData->mRails;
+}
+
+void* Object::getRails_0() const {
+ if (!mLinkData)
+ return nullptr;
+
+ return mLinkData->mRails;
+}
+
+bool Object::allocLinkData(sead::Heap* heap) {
+ mLinkData = new (heap) ObjectLinkData;
+
+ return mLinkData != nullptr;
+}
+
+bool Object::hasGenGroup() const {
+ if (!mLinkData)
+ return false;
+
+ return mLinkData->mGenGroup != nullptr;
+}
+
+void Object::incrementLinkNum() {
+ if (mNumLinksPointingToMe != 0xFF) {
+ mNumLinksPointingToMe += 1;
+ return;
+ }
+
+ auto name = sead::SafeString(getUnitConfigName());
+
+ if (name == "LinkTagNone") {
+ // More than 255 actors are specified in one generation group.
+ // If it is not a test, consult the programmer.
+ printDebugMsg(this,
+ "一つの生成グループに 255 以上のアクタが指定されています。"
+ "テストで無ければプログラマに相談",
+ nullptr);
+ return;
+ }
+
+ // We have exceeded the expected number of links.
+ // If it's not a test, talk to your programmer.
+ printDebugMsg(this, "リンクの想定数を越えました。テストで無ければプログラマに相談", nullptr);
+}
+
+void Object::decrementLinkNum() {
+ if (mNumLinksPointingToMe != 0)
+ --mNumLinksPointingToMe;
+}
+
+sead::Vector3f Object::getRotate() const {
+ sead::Vector3f result;
+ mMubinIter.getRotate(&result);
+
+ return result;
+}
+
+// NON_MATCHING: Vec3f copy incorrect
+void Object::getTraversePosAndLoadDistance(sead::Vector3f* traverse_pos, f32* load_dist) const {
+ if (mFlags.isOn(Flag::HasTraversePos)) {
+ mMubinIter.tryGetFloatArrayByKey(&traverse_pos->x, "TraversePos");
+ } else {
+ *traverse_pos = mTranslate;
+ }
+
+ *load_dist = getLoadDistance(false);
+}
+
+void Object::getUniqueName(const char** out) const {
+ if (mFlags.isOff(Flag::HasUniqueName) || !mMubinIter.tryGetParamStringByKey(out, "UniqueName"))
+ *out = "";
+}
+
+void Object::setTranslate(const sead::Vector3f& translate) {
+ mTranslate = translate;
+}
+
+} // namespace ksys::map
diff --git a/src/KingSystem/Map/mapObject.h b/src/KingSystem/Map/mapObject.h
index 648ad3a2..3f62b226 100644
--- a/src/KingSystem/Map/mapObject.h
+++ b/src/KingSystem/Map/mapObject.h
@@ -1,8 +1,15 @@
#pragma once
#include <basis/seadTypes.h>
+#include <heap/seadHeap.h>
#include <prim/seadTypedBitFlag.h>
+#include "KingSystem/ActorSystem/actActor.h"
+#include "KingSystem/ActorSystem/actActorLinkConstDataAccess.h"
+#include "KingSystem/ActorSystem/actDebug.h"
+#include "KingSystem/Map/mapDebug.h"
#include "KingSystem/Map/mapMubinIter.h"
+#include "KingSystem/Map/mapObjectLink.h"
+#include "KingSystem/Map/mapPlacementMgr.h"
#include "KingSystem/Utils/Types.h"
namespace ksys::act {
@@ -11,14 +18,30 @@ class BaseProc;
namespace ksys::map {
-class LinkData;
+class Object;
+
+class ObjectLinkData;
+struct ObjectLink;
+struct ObjectLinkArray;
+
+class LinkTag;
// FIXME: incomplete
class Object {
public:
// TODO: rename
- enum class Flag0 {
-
+ enum class Flag0 : u32 {
+ _2 = 0x2,
+ _4 = 0x4,
+ _8 = 0x8,
+ _10 = 0x10,
+ _20 = 0x20,
+ _80 = 0x80,
+ _8000 = 0x8000,
+ _40000 = 0x40000,
+ _80000 = 0x80000,
+ Freed = 0xC65067E6,
+ _80000000 = 0x80000000,
};
enum class Flag {
@@ -39,11 +62,6 @@ public:
IsTurnActorBowChargeAndHasBasicSigLink = 0x8000,
};
- // TODO: rename
- enum class ActorFlag8 {
-
- };
-
enum class HardModeFlag {
ActorCreated = 0x1,
/// This actor only spawns in master mode (hard mode).
@@ -57,6 +75,69 @@ public:
Object();
~Object();
+ void free();
+
+ bool getActorWithAccessor(act::ActorLinkConstDataAccess& accessor) const;
+ act::Actor* getActor() const;
+ void registerBaseProc(act::BaseProc* proc);
+ void setBaseProcDirect(act::BaseProc* proc);
+
+ bool isEnemyOrNpcOrActiveOrMapPassive() const;
+ bool isFlags8Cleared() const;
+ bool isNpcOrActiveOrMapPassiveOrFlag1() const;
+ bool isMapPassive(const PlacementActors* pa) const;
+ bool checkActorDataFlag(const PlacementActors* pa, ActorData::Flag flag) const;
+ bool isEnemyOrNpc(const PlacementActors* pa) const;
+
+ f32 getDispDistanceMultiplier() const {
+ f32 mult = 1.0;
+
+ if (act::ActorDebug::instance() != nullptr)
+ mult = act::ActorDebug::instance()->mDispDistanceMultiplier;
+
+ return mult;
+ }
+
+ f32 getDispDistance(const PlacementActors* pa, bool get_diameter, bool ignore_radius) const;
+ f32 getDispDistance(const ActorData* data, bool get_diameter, u32 unused,
+ bool ignore_radius) const;
+ f32 getDispDistance(bool get_diameter, bool ignore_radius) const;
+
+ f32 getTraverseDist(const ActorData* data, bool get_diameter, u32 unused,
+ bool ignore_radius) const;
+ f32 getTraverseDistForLOD() const;
+ sead::Vector3f getScale() const;
+
+ const char* getUnitConfigName() const;
+ const char* getUnitConfigNameFromByaml() const;
+
+ Object* findPlacementLODLinkObject(const PlacementActors* unused) const;
+ Object* findPlacementLODLinkObject() const;
+
+ const char* getHashIdStringDebug() const;
+ const char* getHashIdStringDebug_0() const;
+
+ void* getRails() const;
+ void* getRails_0() const;
+ bool allocLinkData(sead::Heap* heap);
+ bool hasGenGroup() const;
+ void incrementLinkNum();
+ void decrementLinkNum();
+
+ sead::Vector3f getRotate() const;
+ void getTraversePosAndLoadDistance(sead::Vector3f* traverse_pos, f32* load_dist) const;
+ void getUniqueName(const char** out) const;
+ void setTranslate(const sead::Vector3f& translate);
+
+ // TODO:
+ void initData(MubinIter* iter, u8 idx, u32 actor_data_idx, ActorData* data);
+ void initRevivalGameDataFlagAndMiscFlags(ActorData* data, bool zero);
+ act::BaseProc* getActor_0(bool a1) const;
+ LinkTag* x_10(bool a1) const;
+ f32 getLoadDistance(bool get_diameter) const;
+ Object* findSrcLODLinkObject() const;
+ bool isRevivalGameDataFlagOn() const;
+
auto getFlags0() const { return mFlags0; }
auto getFlags() const { return mFlags; }
auto getActorFlags8() const { return mActorFlags8; }
@@ -71,19 +152,17 @@ public:
const MubinIter& getMubinIter() const { return mMubinIter; }
act::BaseProc* getProc() const { return mProc; }
- LinkData* getLinkData() const { return mLinkData; }
+ ObjectLinkData* getLinkData() const { return mLinkData; }
u32 getRevivalGameDataFlagHash() const { return mRevivalGameDataFlagHash; }
u32 getHashId() const { return mHashId; }
const sead::Vector3f& getTranslate() const { return mTranslate; }
- void setTranslate(const sead::Vector3f& translate);
- auto getTraverseDist() const { return mTraverseDist; }
auto getTraverseDistInt() const { return mTraverseDistInt; }
private:
- sead::TypedBitFlag<Flag0, u32> mFlags0;
+ sead::TypedBitFlag<Flag0, sead::Atomic<u32>> mFlags0;
u16 mActorDataIdx = 0xffff;
sead::TypedBitFlag<Flag, u16> mFlags;
u8 mIdx = 0;
@@ -97,7 +176,7 @@ private:
void* _20 = nullptr;
MubinIter mMubinIter;
act::BaseProc* mProc = nullptr;
- LinkData* mLinkData = nullptr;
+ ObjectLinkData* mLinkData = nullptr;
u32 mRevivalGameDataFlagHash = 0xffffffff;
void* _50 = nullptr;
u32 mHashId = 0;
diff --git a/src/KingSystem/Map/mapObjectLink.cpp b/src/KingSystem/Map/mapObjectLink.cpp
new file mode 100644
index 00000000..b2ab0502
--- /dev/null
+++ b/src/KingSystem/Map/mapObjectLink.cpp
@@ -0,0 +1,21 @@
+#include "KingSystem/Map/mapObjectLink.h"
+
+namespace ksys::map {
+
+ObjectLinkData::ObjectLinkData() = default;
+
+act::BaseProc* ObjectLink::getObjectProc() const {
+ if (other_obj == nullptr)
+ return nullptr;
+
+ return other_obj->getActor_0(false);
+}
+
+bool ObjectLink::getObjectProcWithAccessor(act::ActorLinkConstDataAccess& accessor) const {
+ if (other_obj == nullptr)
+ return accessor.acquire(nullptr);
+ else
+ return other_obj->getActorWithAccessor(accessor);
+}
+
+} // namespace ksys::map
diff --git a/src/KingSystem/Map/mapObjectLink.h b/src/KingSystem/Map/mapObjectLink.h
new file mode 100644
index 00000000..09ef72e0
--- /dev/null
+++ b/src/KingSystem/Map/mapObjectLink.h
@@ -0,0 +1,98 @@
+#pragma once
+
+#include "KingSystem/Map/mapObject.h"
+
+namespace ksys::map {
+
+class Object;
+
+enum class MapLinkDefType {
+ BasicSig = 0,
+ AxisX = 1,
+ AxisY = 2,
+ AxisZ = 3,
+ NAxisX = 4,
+ NAxisY = 5,
+ NAxisZ = 6,
+ GimmickSuccess = 7,
+ VelocityControl = 8,
+ BasicSigOnOnly = 9,
+ Remains = 10,
+ DeadUp = 11,
+ LifeZero = 12,
+ Stable = 13,
+ ChangeAtnSig = 14,
+ Create = 15,
+ Delete = 16,
+ MtxCopyCreate = 17,
+ Freeze = 18,
+ ForbidAttention = 19,
+ SyncLink = 20,
+ CopyWaitRevival = 21,
+ OffWaitRevival = 22,
+ Recreate = 23,
+ AreaCol = 24,
+ SensorBlind = 25,
+ ForSale = 26,
+ ModelBind = 27,
+ PlacementLOD = 28,
+ DemoMember = 29,
+ PhysSystemGroup = 30,
+ StackLink = 31,
+ FixedCs = 32,
+ HingeCs = 33,
+ LimitHingeCs = 34,
+ SliderCs = 35,
+ PulleyCs = 36,
+ BAndSCs = 37,
+ BAndSLimitAngYCs = 38,
+ CogWheelCs = 39,
+ RackAndPinionCs = 40,
+ Reference = 41,
+ Invalid = 42,
+};
+
+struct ObjectLink {
+ act::BaseProc* getObjectProc() const;
+ bool getObjectProcWithAccessor(act::ActorLinkConstDataAccess& accessor) const;
+
+ Object* other_obj;
+ u32 type;
+ MubinIter iter;
+};
+KSYS_CHECK_SIZE_NX150(ObjectLink, 0x20);
+
+struct ObjectLinkArray {
+ ObjectLink* findLinkWithType(MapLinkDefType link_type);
+ u32 num_links = 0;
+ ObjectLink* links = nullptr;
+};
+KSYS_CHECK_SIZE_NX150(ObjectLinkArray, 0x10);
+
+class ObjectLinkData {
+public:
+ ObjectLinkData();
+
+ void release(Object* obj, bool a1);
+
+ Object* mCreateLinksSrcObj = nullptr;
+ Object* mDeleteLinksSrcObj = nullptr;
+ u32 mNumLinksReference = 0;
+
+ void* mLinksReference = nullptr;
+ ObjectLinkArray mLinksOther{};
+ ObjectLinkArray mLinksCs{};
+ ObjectLinkArray mLinksToSelf{};
+
+ u32 field_50 = 0;
+ bool field_54 = false;
+ bool mAppearFade = false;
+ bool mNoAutoDemoMember = false;
+ bool field_57 = false;
+
+ void* mGenGroup = nullptr;
+ void* mRails = nullptr;
+};
+KSYS_CHECK_SIZE_NX150(ObjectLinkData, 0x68);
+
+} // namespace ksys::map
diff --git a/src/KingSystem/Map/mapPlacementMgr.cpp b/src/KingSystem/Map/mapPlacementMgr.cpp
new file mode 100644
index 00000000..b6114392
--- /dev/null
+++ b/src/KingSystem/Map/mapPlacementMgr.cpp
@@ -0,0 +1,7 @@
+#include "KingSystem/Map/mapPlacementMgr.h"
+
+namespace ksys::map {
+
+SEAD_SINGLETON_DISPOSER_IMPL(PlacementMgr)
+
+} // namespace ksys::map
diff --git a/src/KingSystem/Map/mapPlacementMgr.h b/src/KingSystem/Map/mapPlacementMgr.h
new file mode 100644
index 00000000..adac1cc2
--- /dev/null
+++ b/src/KingSystem/Map/mapPlacementMgr.h
@@ -0,0 +1,119 @@
+#pragma once
+
+#include <container/seadSafeArray.h>
+#include <heap/seadDisposer.h>
+#include <prim/seadSafeString.h>
+#include <prim/seadTypedBitFlag.h>
+#include <prim/seadTypedLongBitFlag.h>
+#include <thread/seadAtomic.h>
+#include "KingSystem/Utils/Types.h"
+
+namespace ksys::map {
+
+// TODO: rename
+enum class ActorFlag8 {
+ EnemyOrNpcOrActiveOrAreaOrAirWall = 0x2,
+ MapPassiveOrFlag1 = 0x4,
+};
+
+class ActorData {
+public:
+ enum class Flag {
+ MapPassive = 0,
+ _1 = 1,
+ _2 = 2,
+ _3 = 3,
+ _4 = 4,
+ _5 = 5,
+ _6 = 6,
+ _7 = 7,
+ MapConstActive = 8,
+ TraverseDist200 = 9,
+ TraverseDist400 = 10,
+ TraverseDist800 = 11,
+ TraverseDistReset = 12,
+ TraverseDist2000 = 13,
+ TraverseDist4000 = 14,
+ _15 = 15,
+ _16 = 16,
+ RevivalEnable = 17,
+ RevivalForUsed = 18,
+ RevivalForDrop = 19,
+ RevivalRandom = 20,
+ RevivalBloodyMoon = 21,
+ RevivalUnderGodTimeOrNoneForUsed = 22,
+ EnableRemainsScene = 23,
+ _24 = 24,
+ EnemyOrNpc_DisableFlashback = 25,
+ _26 = 26,
+ LimitYDiff = 27,
+ IsGrassCut = 28,
+ HasFar = 29,
+ Fairy = 30,
+ UnderGodForest = 31,
+
+ EnemyOrNpc = 32,
+ MapConstPassive = 33,
+ RandomCreateNotRain = 34,
+ _35 = 35,
+ MessageDialogViewBoard = 36,
+ _37 = 37,
+ NpcOrNonGanonAndNonGuardianEnemy = 38,
+ IgnoreBoundingAtAreaCulling = 39,
+ _40 = 40,
+ EnemyHuge = 41,
+ Enemy = 42,
+ _43 = 43,
+ EnemyLookOrGrassCutTagOrFirePillarOrDgnWater = 44,
+ _45 = 45,
+ MapPassiveOrFlag1 = 46,
+ _47 = 47,
+ _48 = 48,
+ SheikSensorTargetDeadOrAlive = 49,
+ Dragon = 50,
+ TreeOrBush = 51,
+ GuardianC = 52,
+ _53 = 53,
+ HasStopTimerFlag = 54,
+ AllRadarOrZukanActor = 55,
+ NoCreateForStackLink = 56,
+ OnLowTree = 57,
+ _58 = 58,
+ _59 = 59,
+ _60 = 60,
+ _61 = 61,
+ _62 = 62,
+ _63 = 63,
+ };
+
+ sead::TypedLongBitFlag<64, Flag, sead::Atomic<u32>> mFlags;
+ sead::TypedBitFlag<ActorFlag8, u8> mActorFlags8;
+ u8 TEMP[0x13F];
+ sead::FixedSafeString<64> mActorName;
+};
+KSYS_CHECK_SIZE_NX150(ActorData, 0x1A0);
+
+class PlacementActors {
+public:
+ u8 TEMP1[0x538];
+ sead::SafeArray<ActorData, 6000> mActorData;
+ u8 TEMP2[0x46598];
+};
+KSYS_CHECK_SIZE_NX150(PlacementActors, 0x2A80D0);
+
+class PlacementMgr {
+ SEAD_SINGLETON_DISPOSER(PlacementMgr)
+public:
+ enum class MgrFlag {
+ _1000000 = 0x1000000,
+ };
+
+ u8 TEMP1[0x1D0];
+ PlacementActors* mPlacementActors;
+ u8 TEMP2[0x48C];
+ sead::TypedBitFlag<MgrFlag, sead::Atomic<u32>> mFlags;
+ u8 TEMP3[0x190];
+};
+KSYS_CHECK_SIZE_NX150(PlacementMgr, 0x818);
+
+} // namespace ksys::map