1#include "Library/Area/SwitchKeepOnAreaGroup.h"
2
3#include "Library/Area/AreaObj.h"
4#include "Library/Area/AreaObjGroup.h"
5#include "Library/Area/SwitchAreaTargetInfo.h"
6#include "Library/Placement/PlacementFunction.h"
7#include "Library/Stage/StageSwitchUtil.h"
8
9namespace al {
10SwitchKeepOnAreaGroup::SwitchKeepOnAreaGroup(AreaObjGroup* areaObjGroup)
11 : mAreaObjGroup(areaObjGroup) {
12 mOnAreaObjSize = areaObjGroup->getSize();
13 if (mOnAreaObjSize > 0)
14 mOnAreaObjs = new AreaObj*[mOnAreaObjSize];
15}
16
17inline bool isAnyPosInVolume(AreaObj* areaObj, sead::Vector3f* targetPos, s32 targetPosCount) {
18 for (s32 j = 0; j < targetPosCount; j++)
19 if (areaObj->isInVolume(pos: targetPos[j]))
20 return true;
21
22 return false;
23}
24
25inline bool isAllPosInVolume(AreaObj* areaObj, sead::Vector3f* targetPos, s32 targetPosCount) {
26 __asm("");
27 for (s32 j = 0; j < targetPosCount; j++)
28 if (!areaObj->isInVolume(pos: targetPos[j]))
29 return false;
30
31 return true;
32}
33
34void SwitchKeepOnAreaGroup::update(const SwitchAreaTargetInfo* info) {
35 mOnAreaObjCount = 0;
36 s32 size = mAreaObjGroup->getSize();
37 for (s32 i = 0; i < size; i++) {
38 AreaObj* areaObj = mAreaObjGroup->getAreaObj(index: i);
39 bool shouldSkip = false;
40 for (s32 j = 0; j < mOnAreaObjCount; j++) {
41 if (isSameStageSwitch(user: areaObj, otherUser: mOnAreaObjs[j], linkName: "SwitchAreaOn")) {
42 shouldSkip = true;
43
44 break;
45 }
46 }
47
48 if (shouldSkip)
49 continue;
50
51 bool checkAllPos = false;
52 sead::Vector3f* targetPos = nullptr;
53 s32 targetPosCount = 0;
54 selectTargetPosArray(outCheckAllPos: &checkAllPos, outTargetPos: &targetPos, outTargetPosCount: &targetPosCount, areaObj, info);
55
56 if (targetPosCount != 0) {
57 bool result = checkAllPos ? isAllPosInVolume(areaObj, targetPos, targetPosCount) :
58 isAnyPosInVolume(areaObj, targetPos, targetPosCount);
59
60 if (result && isExternalCondition()) {
61 tryOnStageSwitch(user: areaObj, linkName: "SwitchAreaOn");
62 mOnAreaObjs[mOnAreaObjCount] = areaObj;
63 mOnAreaObjCount++;
64
65 continue;
66 }
67 }
68
69 tryOffStageSwitch(user: areaObj, linkName: "SwitchAreaOn");
70 }
71}
72
73void SwitchKeepOnAreaGroup::update(const sead::Vector3f& playerPos) {
74 sead::Vector3f pos = playerPos;
75 SwitchAreaTargetInfo info = {&pos, 1};
76
77 update(info: &info);
78}
79
80void SwitchKeepOnAreaGroup::selectTargetPosArray(bool* outCheckAllPos,
81 sead::Vector3f** outTargetPos,
82 s32* outTargetPosCount, const AreaObj* areaObj,
83 const SwitchAreaTargetInfo* info) {
84 s32 onCondition = 0;
85 tryGetArg(arg: &onCondition, placementInfo: *areaObj->getPlacementInfo(), key: "OnCondition");
86
87 switch (onCondition) {
88 case 0:
89 *outCheckAllPos = false;
90 *outTargetPos = info->getPlayerTargetPositions();
91 *outTargetPosCount = info->getPlayerTargetPositionCount();
92
93 break;
94 case 1:
95 *outCheckAllPos = true;
96 *outTargetPos = info->getPlayerTargetPositions();
97 *outTargetPosCount = info->getPlayerTargetPositionCount();
98
99 break;
100 case 2:
101 *outCheckAllPos = false;
102 *outTargetPos = info->getCameraLookAtPositions();
103 *outTargetPosCount = info->getCameraLookAtPositionCount();
104
105 break;
106 default:
107 break;
108 }
109}
110} // namespace al
111