diff --git a/data/uking_functions.csv b/data/uking_functions.csv index d2f5c3bc7..6857f9bf9 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -73599,11 +73599,11 @@ Address,Quality,Size,Name 0x0000007100d375e4,U,000076,LazyTraverseList::dtor 0x0000007100d37630,U,000132,LazyTraverseList::updateFlags 0x0000007100d376b4,U,000216, -0x0000007100d3778c,U,000204,LinkTag::construct +0x0000007100d3778c,O,000204,_ZN4ksys3act7LinkTag9constructERKNS0_8BaseProc9CreateArgEPN4sead4HeapE 0x0000007100d37858,U,000280,LinkTag::calc 0x0000007100d37970,U,000064,LinkTag::dtor 0x0000007100d379b0,U,000072,LinkTag::dtorDelete -0x0000007100d379f8,U,001656,LinkTag::init2 +0x0000007100d379f8,W,001656,_ZN4ksys3act7LinkTag4initEv 0x0000007100d38070,U,000256,isLinkTagNAndOrNOr 0x0000007100d38170,U,000308,map::isFlagSet 0x0000007100d382a4,U,000056,LinkTag::finalizeInit @@ -73620,7 +73620,7 @@ Address,Quality,Size,Name 0x0000007100d3905c,U,000064,LinkTag::shouldSkipJobPush_ 0x0000007100d3909c,U,000132,LinkTag::prePushJob2 0x0000007100d39120,U,000172, -0x0000007100d391cc,U,000596,LinkTag::updateIsFlagSetFlag +0x0000007100d391cc,W,000596,_ZN4ksys3act7LinkTag19updateIsFlagSetFlagEbbb 0x0000007100d39420,U,000052, 0x0000007100d39454,U,000588,isAreaOrLinkTagOrOtherTag 0x0000007100d396a0,U,000584,LinkTag::isTriggered @@ -73631,8 +73631,8 @@ Address,Quality,Size,Name 0x0000007100d39d60,U,000132, 0x0000007100d39de4,U,000072, 0x0000007100d39e2c,U,000028, -0x0000007100d39e48,U,000204,LinkTag::rtti1 -0x0000007100d39f14,U,000092,LinkTag::rtti2 +0x0000007100d39e48,O,000204,_ZNK4ksys3act7LinkTag27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007100d39f14,O,000092,_ZNK4ksys3act7LinkTag18getRuntimeTypeInfoEv 0x0000007100d39f70,O,000004,_ZN4ksys3act8BaseProc18onDeleteRequested_ENS1_12DeleteReasonE 0x0000007100d39f74,O,000004,_ZN4ksys3act8BaseProc17onSleepRequested_ENS1_15SleepWakeReasonE 0x0000007100d39f78,O,000004,_ZN4ksys3act8BaseProc18onWakeUpRequested_ENS1_15SleepWakeReasonE diff --git a/src/KingSystem/ActorSystem/CMakeLists.txt b/src/KingSystem/ActorSystem/CMakeLists.txt index fe74e4217..8f5bd3770 100644 --- a/src/KingSystem/ActorSystem/CMakeLists.txt +++ b/src/KingSystem/ActorSystem/CMakeLists.txt @@ -99,6 +99,8 @@ target_sources(uking PRIVATE actInstParamPack.cpp actInstParamPack.h actLifeRecoveryInfo.h + actLinkTag.cpp + actLinkTag.h actPlayerInfo.cpp actPlayerInfo.h actTag.h diff --git a/src/KingSystem/ActorSystem/actLinkTag.cpp b/src/KingSystem/ActorSystem/actLinkTag.cpp new file mode 100644 index 000000000..fd1ff8c7f --- /dev/null +++ b/src/KingSystem/ActorSystem/actLinkTag.cpp @@ -0,0 +1,155 @@ +#include "KingSystem/ActorSystem/actLinkTag.h" + +#include "KingSystem/Map/mapObject.h" +#include "KingSystem/Map/mapObjectLink.h" +#include "KingSystem/System/SystemTimers.h" + +namespace ksys::act { + +LinkTag* LinkTag::construct(const BaseProc::CreateArg& arg, sead::Heap* heap) { + return new (heap, std::nothrow) LinkTag(arg); +} + +LinkTag::LinkTag(const BaseProc::CreateArg& arg) : BaseProc(arg), mJob(this, &LinkTag::calc) { + mJobHandlers[3] = &mJob; +} + +bool LinkTag::init() { + if (mName == "LinkTagOr") + mLinkTagType = Type::Or; + else if (mName == "LinkTagNOr") + mLinkTagType = Type::NOr; + else if (mName == "LinkTagNAnd") + mLinkTagType = Type::NAnd; + else if (mName == "LinkTagXOr") + mLinkTagType = Type::XOr; + else if (mName == "LinkTagAnd") + mLinkTagType = Type::And; + else if (mName == "LinkTagCount") + mLinkTagType = Type::Count; + else if (mName == "LinkTagPulse") + mLinkTagType = Type::Pulse; + else if (mName == "LinkTagNone") + mLinkTagType = Type::None; + + if (mName == "LinkTagNAnd" || mName == "LinkTagNOr") + mFlags.set(LinkTagFlag::_4); + + int noChangeSignalValue = 0; + mMubinIter.tryGetParamIntByKey(&noChangeSignalValue, "NoChangeSignal"); + if (noChangeSignalValue != 0) + mFlags.set(LinkTagFlag::_40); + + int saveFlagOnOffTypeValue = 0; + if (mMubinIter.tryGetParamIntByKey(&saveFlagOnOffTypeValue, "SaveFlagOnOffType")) { + if (saveFlagOnOffTypeValue == 2) + mFlags.set(LinkTagFlag::_200); + else if (saveFlagOnOffTypeValue == 1) + mFlags.set(LinkTagFlag::_100); + } + + bool flagSet = false; + isFlagSet(&flagSet, 0, mMapObj); + updateIsFlagSetFlag(flagSet, 1, 1); + if (flagSet) { + mFlags.set(LinkTagFlag::_10); + mTriggeredLinkFlags.makeAllOne(); + mFlags.set(LinkTagFlag::_30); + } else { + mFlags.reset(LinkTagFlag::_10); + mTriggeredLinkFlags.makeAllZero(); + mFlags.reset(LinkTagFlag::_30); + } + return true; +} + +void LinkTag::updateIsFlagSetFlag(bool isFlagSet, bool a3, bool a4) { + if (!mMapObj) + return; + + /*if (isFlagSet) + mFlags.set(LinkTagFlag::_8); + else + mFlags.reset(LinkTagFlag::_8);*/ + mFlags.change(LinkTagFlag::_8, isFlagSet); + + if (mFlags.isOff(LinkTagFlag::_40) || a3) { + mMapObj->getFlags0().change(map::Object::Flag0::_100, isFlagSet); + + if (mFlags.isOff(LinkTagFlag::_40)) { + int frameCounter = SystemTimers::instance()->mFrameCounter; + auto mapLinkData = mMapObj->getLinkData(); + if (mapLinkData) { + auto mapLinks = mapLinkData->mLinksOther.links; + if (isFlagSet != mMapObj->getFlags().isOn(map::Object::Flag::IsLinkTagNAndOrNOr)) { + for (int i = 0; i < mapLinks.size(); i++) { + auto& mapLink = mapLinks[i]; + if (mapLink.other_obj) { + if (mapLink.type == map::MapLinkDefType::Create || + mapLink.type == map::MapLinkDefType::MtxCopyCreate) { + if (_1E8 == frameCounter) { + mapLink.other_obj->getFlags0().reset( + map::Object::Flag0::_10000000); + } + } else if (mapLink.type == map::MapLinkDefType::Delete && + (mapLink.other_obj->getFlags0().isOff( + map::Object::Flag0::_20000000))) { + mapLink.other_obj->getFlags0().set(map::Object::Flag0::_20000000); + _1E8 = frameCounter; + } + } + } + } else { + for (int i = 0; i < mapLinks.size(); i++) { + auto& mapLink = mapLinks[i]; + if (mapLink.other_obj) { + switch (mapLink.type) { + case map::MapLinkDefType::Create: + case map::MapLinkDefType::MtxCopyCreate: + if (mapLink.other_obj->getFlags0().isOff( + map::Object::Flag0::_10000000)) { + mapLink.other_obj->getFlags0().set( + map::Object::Flag0::_10000000); + _1E8 = frameCounter; + } + break; + case map::MapLinkDefType::Delete: + if (_1E8 == frameCounter) + mapLink.other_obj->getFlags0().reset( + map::Object::Flag0::_10000000); + break; + } + } + } + } + } + } + } + + if (a4) { + mFlags.reset(LinkTagFlag::_800); + } + if (isFlagSet != mMapObj->getFlags().isOn(map::Object::Flag::IsLinkTagNAndOrNOr)) { + if (mFlags.isOff(LinkTagFlag::_800)) { + mFlags.set(LinkTagFlag::_800); + } + mFlags.set(LinkTagFlag::_400); + } + if (mFlags.isOn(LinkTagFlag::_800)) { + mFlags.set(LinkTagFlag::_C00); + } + + if (!a3) { + auto mapLinkData = mMapObj->getLinkData(); + if (mapLinkData) { + if (mapLinkData->isGenGroupInitState3() && + (mapLinkData->findLinkWithType(map::MapLinkDefType::Create) || + mapLinkData->findLinkWithType(map::MapLinkDefType::Delete) || + mapLinkData->findLinkWithType(map::MapLinkDefType::MtxCopyCreate))) { + mapLinkData->sub_7100D4FA90(); + } + } + } +} + +} // namespace ksys::act diff --git a/src/KingSystem/ActorSystem/actLinkTag.h b/src/KingSystem/ActorSystem/actLinkTag.h new file mode 100644 index 000000000..e8978acd9 --- /dev/null +++ b/src/KingSystem/ActorSystem/actLinkTag.h @@ -0,0 +1,66 @@ +#pragma once + +#include +#include +#include +#include "KingSystem/ActorSystem/actBaseProc.h" +#include "KingSystem/ActorSystem/actBaseProcJobHandler.h" +#include "KingSystem/Map/mapMubinIter.h" +#include "KingSystem/Utils/Types.h" + +namespace ksys::map { +class Object; +} // namespace ksys::map + +namespace ksys::act { + +class LinkTag : public BaseProc { + SEAD_RTTI_OVERRIDE(LinkTag, BaseProc) + +public: + enum class Type : u8 { And, Or, NAnd, NOr, XOr, Count, Pulse, None }; + enum class JobFlag {}; + enum class LinkTagFlag : u16 { + _4 = 0x4, + _8 = 0x8, + _10 = 0x10, + _20 = 0x20, + _40 = 0x40, + _100 = 0x100, + _200 = 0x200, + _400 = 0x400, + _800 = 0x800, + + _30 = _10 | _20, + _C00 = _400 | _800 + }; + + static LinkTag* construct(const BaseProc::CreateArg& arg, sead::Heap* heap); + + explicit LinkTag(const BaseProc::CreateArg& arg); + void calc(); + bool init(); + void updateIsFlagSetFlag(bool isFlagSet, bool a3, bool a4); + + // this doesn't even belong in this namespace, but is used as a placeholder for init() + void isFlagSet(bool* isSet, int unk, map::Object* object); + + BaseProcJobHandlerT mJob; + sead::LongBitFlag<96> mTriggeredLinkFlags; + Type mLinkTagType = Type::And; + u8 _1dd = 0xFF; + sead::Atomic _1de = 0; + u8 _1df = 0xFF; + sead::TypedBitFlag mFlags; + u8 mTagCount = 0; + u8 _1E3 = 0; + u32 mCounter = 0; + int _1E8 = 0; + sead::TypedBitFlag> mJobFlags; + u32 mHashId = 0; + map::MubinIter mMubinIter; + map::Object* mMapObj = nullptr; +}; +KSYS_CHECK_SIZE_NX150(LinkTag, 0x210); + +} // namespace ksys::act diff --git a/src/KingSystem/Map/mapObject.h b/src/KingSystem/Map/mapObject.h index 10e9d3c54..3b7d198d5 100644 --- a/src/KingSystem/Map/mapObject.h +++ b/src/KingSystem/Map/mapObject.h @@ -49,6 +49,8 @@ class Object { _400000 = 0x400000, _2000000 = 0x2000000, _4000000 = 0x4000000, + _10000000 = 0x10000000, + _20000000 = 0x20000000, _40000000 = 0x40000000, _80000000 = 0x80000000, ResetOnUnlinkFailed = _100 | _2000, @@ -176,6 +178,7 @@ class Object { Object* findSrcLODLinkObject() const; const auto& getFlags0() const { return mFlags0; } + auto& getFlags0() { return mFlags0; } const auto& getFlags() const { return mFlags; } const auto& getActorFlags8() const { return mActorFlags8; } const auto& getHardModeFlags() const { return mHardModeFlags; } diff --git a/src/KingSystem/Map/mapObjectLink.h b/src/KingSystem/Map/mapObjectLink.h index 382aa804d..d71c6ac4a 100644 --- a/src/KingSystem/Map/mapObjectLink.h +++ b/src/KingSystem/Map/mapObjectLink.h @@ -112,6 +112,11 @@ class ObjectLinkData { return checkDeleteLinkObjRevival() || checkCreateLinkObjRevival(); } + // TODO requires implementation: 0x7100D4FA70 + bool isGenGroupInitState3() const; + // TODO requires implementation: 0x7100D4FA90 + void sub_7100D4FA90(); + Object* mCreateLinksSrcObj = nullptr; Object* mDeleteLinksSrcObj = nullptr;