#include "Library/Area/SwitchKeepOnAreaGroup.h" #include "Library/Area/AreaObj.h" #include "Library/Area/AreaObjGroup.h" #include "Library/Area/SwitchAreaTargetInfo.h" #include "Library/Placement/PlacementFunction.h" #include "Library/Stage/StageSwitchUtil.h" namespace al { SwitchKeepOnAreaGroup::SwitchKeepOnAreaGroup(AreaObjGroup* areaObjGroup) : mAreaObjGroup(areaObjGroup) { mOnAreaObjSize = areaObjGroup->getSize(); if (mOnAreaObjSize > 0) mOnAreaObjs = new AreaObj*[mOnAreaObjSize]; } inline bool isAnyPosInVolume(AreaObj* areaObj, sead::Vector3f* targetPos, s32 targetPosCount) { for (s32 j = 0; j < targetPosCount; j++) if (areaObj->isInVolume(targetPos[j])) return true; return false; } inline bool isAllPosInVolume(AreaObj* areaObj, sead::Vector3f* targetPos, s32 targetPosCount) { __asm(""); for (s32 j = 0; j < targetPosCount; j++) if (!areaObj->isInVolume(targetPos[j])) return false; return true; } void SwitchKeepOnAreaGroup::update(const SwitchAreaTargetInfo* info) { mOnAreaObjCount = 0; s32 size = mAreaObjGroup->getSize(); for (s32 i = 0; i < size; i++) { AreaObj* areaObj = mAreaObjGroup->getAreaObj(i); bool shouldSkip = false; for (s32 j = 0; j < mOnAreaObjCount; j++) { if (isSameStageSwitch(areaObj, mOnAreaObjs[j], "SwitchAreaOn")) { shouldSkip = true; break; } } if (shouldSkip) continue; bool checkAllPos = false; sead::Vector3f* targetPos = nullptr; s32 targetPosCount = 0; selectTargetPosArray(&checkAllPos, &targetPos, &targetPosCount, areaObj, info); if (targetPosCount != 0) { bool result = checkAllPos ? isAllPosInVolume(areaObj, targetPos, targetPosCount) : isAnyPosInVolume(areaObj, targetPos, targetPosCount); if (result && isExternalCondition()) { tryOnStageSwitch(areaObj, "SwitchAreaOn"); mOnAreaObjs[mOnAreaObjCount] = areaObj; mOnAreaObjCount++; continue; } } tryOffStageSwitch(areaObj, "SwitchAreaOn"); } } void SwitchKeepOnAreaGroup::update(const sead::Vector3f& playerPos) { sead::Vector3f pos = playerPos; SwitchAreaTargetInfo info = {&pos, 1}; update(&info); } void SwitchKeepOnAreaGroup::selectTargetPosArray(bool* outCheckAllPos, sead::Vector3f** outTargetPos, s32* outTargetPosCount, const AreaObj* areaObj, const SwitchAreaTargetInfo* info) { s32 onCondition = 0; tryGetArg(&onCondition, *areaObj->getPlacementInfo(), "OnCondition"); switch (onCondition) { case 0: *outCheckAllPos = false; *outTargetPos = info->getPlayerTargetPositions(); *outTargetPosCount = info->getPlayerTargetPositionCount(); break; case 1: *outCheckAllPos = true; *outTargetPos = info->getPlayerTargetPositions(); *outTargetPosCount = info->getPlayerTargetPositionCount(); break; case 2: *outCheckAllPos = false; *outTargetPos = info->getCameraLookAtPositions(); *outTargetPosCount = info->getCameraLookAtPositionCount(); break; default: break; } } } // namespace al