1#include "Library/LiveActor/ActorAreaFunction.h"
2
3#include "Library/Area/AreaInitInfo.h"
4#include "Library/Area/AreaObj.h"
5#include "Library/Area/AreaObjDirector.h"
6#include "Library/Area/AreaObjGroup.h"
7#include "Library/Area/AreaObjMtxConnecter.h"
8#include "Library/Area/AreaObjUtil.h"
9#include "Library/Area/IUseAreaObj.h"
10#include "Library/Area/SwitchKeepOnAreaGroup.h"
11#include "Library/Area/SwitchOnAreaGroup.h"
12#include "Library/Area/ValidatorBase.h"
13#include "Library/LiveActor/ActorFlagFunction.h"
14#include "Library/LiveActor/ActorInitInfo.h"
15#include "Library/LiveActor/ActorMovementFunction.h"
16#include "Library/LiveActor/ActorPoseUtil.h"
17#include "Library/LiveActor/ActorSceneInfo.h"
18#include "Library/LiveActor/LiveActor.h"
19#include "Library/Math/MathUtil.h"
20#include "Library/Placement/PlacementFunction.h"
21#include "Library/Player/PlayerUtil.h"
22
23namespace al {
24
25AreaObj* tryFindAreaObjPlayerOne(const PlayerHolder* holder, const char* name) {
26 s32 playerNum = getPlayerNumMax(holder);
27
28 AreaObj* selectedAreaObj = nullptr;
29 for (s32 i = 0; i < playerNum; i++) {
30 if (isPlayerDead(holder, i))
31 continue;
32 if (!isAreaTarget(actor: getPlayerActor(holder, i)))
33 continue;
34 const sead::Vector3f& playerPos = getPlayerPos(holder, i);
35 AreaObj* areaObj = tryFindAreaObj(areaUser: getPlayerActor(holder, i), name, position: playerPos);
36 if (areaObj &&
37 (!selectedAreaObj || selectedAreaObj->getPriority() < areaObj->getPriority())) {
38 selectedAreaObj = areaObj;
39 }
40 }
41
42 return selectedAreaObj;
43}
44
45AreaObj* tryFindAreaObjPlayerAll(const PlayerHolder* holder, const char* name) {
46 s32 playerNum = getPlayerNumMax(holder);
47 if (playerNum == 0)
48 return nullptr;
49
50 AreaObjGroup* areaGroup = tryFindAreaObjGroup(areaUser: getPlayerActor(holder, 0), name);
51 if (!areaGroup)
52 return nullptr;
53
54 s32 groupSize = areaGroup->getSize();
55 AreaObj* selectedAreaObj = nullptr;
56 for (s32 i = 0; i < groupSize; i++) {
57 AreaObj* areaObj = areaGroup->getAreaObj(index: i);
58 AreaObj* currentAreaObject = nullptr;
59 for (s32 j = 0; j < playerNum; j++) {
60 if (isPlayerDead(holder, j))
61 continue;
62
63 const sead::Vector3f& playerPos = getPlayerPos(holder, j);
64 currentAreaObject = areaObj;
65 if (!areaObj->isInVolume(pos: playerPos)) {
66 currentAreaObject = nullptr;
67 break;
68 }
69 }
70 if (currentAreaObject && (!selectedAreaObj || selectedAreaObj->getPriority() <
71 currentAreaObject->getPriority())) {
72 selectedAreaObj = currentAreaObject;
73 }
74 }
75 return selectedAreaObj;
76}
77
78AreaObj* createAreaObj(const ActorInitInfo& actorInitInfo, const char* name) {
79 AreaInitInfo areaInitInfo;
80 initAreaInitInfo(areaInfo: &areaInitInfo, actorInfo: actorInitInfo);
81 AreaObj* areaObj = new AreaObj(name);
82 areaObj->init(info: areaInitInfo);
83 return areaObj;
84}
85
86void initAreaInitInfo(AreaInitInfo* areaInitInfo, const ActorInitInfo& actorInitInfo) {
87 initAreaInitInfo(areaInfo: areaInitInfo, placementInfo: *actorInitInfo.placementInfo, actorInfo: actorInitInfo);
88}
89
90AreaObj* createLinkArea(const ActorInitInfo& initInfo, const char* name, const char* areaName) {
91 const PlacementInfo& actorPlacementInfo = *initInfo.placementInfo;
92 PlacementInfo placementInfo;
93 getLinksInfoByIndex(linkPlacementInfo: &placementInfo, placementInfo: actorPlacementInfo, linkName: name, index: 0);
94
95 AreaInitInfo areaInfo;
96 initAreaInitInfo(areaInfo: &areaInfo, placementInfo, actorInfo: initInfo);
97
98 AreaObj* areaObj = new AreaObj(areaName);
99 areaObj->init(info: areaInfo);
100 return areaObj;
101}
102
103void initAreaInitInfo(AreaInitInfo* areaInitInfo, const PlacementInfo& placementInfo,
104 const ActorInitInfo& actorInitInfo) {
105 areaInitInfo->set(placementInfo, stageSwitchDirector: actorInitInfo.stageSwitchDirector,
106 sceneObjHolder: actorInitInfo.actorSceneInfo.sceneObjHolder);
107}
108
109AreaObj* tryCreateLinkArea(const ActorInitInfo& initInfo, const char* name, const char* areaName) {
110 s32 linkChildNum = calcLinkChildNum(initInfo, linkName: name);
111 if (linkChildNum < 1)
112 return nullptr;
113
114 return createLinkArea(initInfo, name, areaName);
115}
116
117__attribute__((always_inline)) AreaObjGroup* createLinkAreaGroup(const ActorInitInfo& initInfo,
118 const char* name,
119 const char* groupName,
120 const char* areaName) {
121 s32 linkChildNum = calcLinkChildNum(initInfo, linkName: name);
122 if (linkChildNum < 1)
123 return nullptr;
124
125 AreaObjGroup* areaGroup = new AreaObjGroup(groupName, 0);
126 areaGroup->createBuffer(capacity: linkChildNum);
127 const PlacementInfo& actorPlacementInfo = *initInfo.placementInfo;
128
129 for (s32 i = 0; i < linkChildNum; i++) {
130 PlacementInfo placementInfo;
131 getLinksInfoByIndex(linkPlacementInfo: &placementInfo, placementInfo: actorPlacementInfo, linkName: name, index: i);
132
133 AreaInitInfo areaInfo;
134 initAreaInitInfo(areaInitInfo: &areaInfo, placementInfo, actorInitInfo: initInfo);
135
136 AreaObj* areaObj = new AreaObj(areaName);
137 areaObj->init(info: areaInfo);
138
139 areaGroup->registerAreaObj(newAreaObj: areaObj);
140 }
141 return areaGroup;
142}
143
144AreaObjGroup* createLinkAreaGroup(LiveActor* actor, const ActorInitInfo& initInfo, const char* name,
145 const char* groupName, const char* areaName) {
146 return createLinkAreaGroup(initInfo, name, groupName, areaName);
147}
148
149AreaObj* tryFindAreaObj(const LiveActor* actor, const char* name) {
150 if (!isAreaTarget(actor))
151 return nullptr;
152
153 return tryFindAreaObj(areaUser: actor, name, position: getTrans(actor));
154}
155
156bool isInAreaObj(const LiveActor* actor, const char* name) {
157 if (!isAreaTarget(actor))
158 return false;
159
160 return isInAreaObj(areaUser: actor, name, position: getTrans(actor));
161}
162
163bool isInDeathArea(const LiveActor* actor) {
164 if (!isAreaTarget(actor))
165 return false;
166
167 return isInDeathArea(areaUser: actor, position: getTrans(actor));
168}
169
170bool isInWaterArea(const LiveActor* actor) {
171 if (!isAreaTarget(actor))
172 return false;
173
174 return isInWaterArea(areaUser: actor, position: getTrans(actor));
175}
176
177bool isInPlayerControlOffArea(const LiveActor* actor) {
178 if (!isAreaTarget(actor))
179 return false;
180
181 return isInPlayerControlOffArea(areaUser: actor, position: getTrans(actor));
182}
183
184f32 calcWaterSinkDepth(const LiveActor* actor) {
185 return calcWaterSinkDepth(areaUser: actor, position: getTrans(actor));
186}
187
188void registerAreaHostMtx(const IUseAreaObj* areaObj, const sead::Matrix34f* mtx,
189 const ActorInitInfo& initInfo) {
190 areaObj->getAreaObjDirector()->getMtxConnecterHolder()->registerParentMtx(
191 parentMtx: mtx, placementInfo: *initInfo.placementInfo, validatorBase: nullptr);
192}
193
194void registerAreaHostMtx(const IUseAreaObj* areaObj, const sead::Matrix34f* mtx,
195 const ActorInitInfo& initInfo, const ValidatorBase& validator) {
196 areaObj->getAreaObjDirector()->getMtxConnecterHolder()->registerParentMtx(
197 parentMtx: mtx, placementInfo: *initInfo.placementInfo, validatorBase: validator.fnc_8());
198}
199
200void registerAreaHostMtx(const LiveActor* actor, const ActorInitInfo& initInfo) {
201 registerAreaHostMtx(areaObj: actor, mtx: actor->getBaseMtx(), initInfo);
202}
203
204void registerAreaHostMtx(const LiveActor* actor, const ActorInitInfo& initInfo,
205 const ValidatorBase& validator) {
206 registerAreaHostMtx(areaObj: actor, mtx: actor->getBaseMtx(), initInfo, validator);
207}
208
209void registerAreaSyncHostMtx(const IUseAreaObj* areaObj, const sead::Matrix34f* mtx,
210 const ActorInitInfo& initInfo) {
211 areaObj->getAreaObjDirector()->getMtxConnecterHolder()->registerSyncParentMtx(
212 parentMtx: mtx, placementInfo: *initInfo.placementInfo, validatorBase: nullptr);
213}
214
215void registerAreaSyncHostMtx(const IUseAreaObj* areaObj, const sead::Matrix34f* mtx,
216 const ActorInitInfo& initInfo, const ValidatorBase& validator) {
217 areaObj->getAreaObjDirector()->getMtxConnecterHolder()->registerSyncParentMtx(
218 parentMtx: mtx, placementInfo: *initInfo.placementInfo, validatorBase: validator.fnc_8());
219}
220
221void registerAreaSyncHostMtx(const LiveActor* actor, const ActorInitInfo& initInfo) {
222 registerAreaSyncHostMtx(areaObj: actor, mtx: actor->getBaseMtx(), initInfo);
223}
224
225void registerAreaSyncHostMtx(const LiveActor* actor, const ActorInitInfo& initInfo,
226 const ValidatorBase& validator) {
227 registerAreaSyncHostMtx(areaObj: actor, mtx: actor->getBaseMtx(), initInfo, validator);
228}
229
230bool tryReviseVelocityInsideAreaObj(sead::Vector3f* nearestEdgePos, LiveActor* actor,
231 AreaObjGroup* areaGroup, const AreaObj* areaObj) {
232 if (!areaGroup || !areaObj)
233 return false;
234
235 if (!isInAreaObj(group: areaGroup, position: getTrans(actor))) {
236 calcNearestAreaObjEdgePos(outNearestEdgePos: nearestEdgePos, areaObj, position: getTrans(actor));
237 setTrans(actor, trans: *nearestEdgePos);
238 setVelocityZero(actor);
239 return true;
240 }
241
242 f32 velMagnitude = getVelocity(actor).length();
243 sead::Vector3f nextPosition = getTrans(actor) + getVelocity(actor);
244 if (isInAreaObj(group: areaGroup, position: nextPosition))
245 return false;
246
247 calcNearestAreaObjEdgePos(outNearestEdgePos: nearestEdgePos, areaObj, position: nextPosition);
248 sead::Vector3f newVelocity = *nearestEdgePos - getTrans(actor);
249 if (newVelocity.length() > velMagnitude)
250 setLength(vec: &newVelocity, length: velMagnitude);
251 setVelocity(actor, vel: newVelocity);
252 return true;
253}
254
255SwitchKeepOnAreaGroup* tryCreateSwitchKeepOnAreaGroup(LiveActor* actor,
256 const ActorInitInfo& initInfo) {
257 AreaObjGroup* areaGroup =
258 createLinkAreaGroup(actor, initInfo, name: "AreaSwitchKeepOn", groupName: "子供スイッチキープエリアグループ",
259 areaName: "子供スイッチキープエリア");
260 if (!areaGroup)
261 return nullptr;
262
263 return new SwitchKeepOnAreaGroup(areaGroup);
264}
265
266SwitchOnAreaGroup* tryCreateSwitchOnAreaGroup(LiveActor* actor, const ActorInitInfo& initInfo) {
267 AreaObjGroup* areaGroup = createLinkAreaGroup(
268 actor, initInfo, name: "AreaSwitchOn", groupName: "子供スイッチOnエリアグループ", areaName: "子供スイッチOnエリア");
269 if (!areaGroup)
270 return nullptr;
271
272 return new SwitchOnAreaGroup(areaGroup);
273}
274
275} // namespace al
276