1#include "Layout/Compass.h"
2
3#include "Library/Area/AreaObjUtil.h"
4#include "Library/Camera/CameraDirector.h"
5#include "Library/Camera/CameraUtil.h"
6#include "Library/Layout/LayoutActionFunction.h"
7#include "Library/Layout/LayoutInitInfo.h"
8#include "Library/LiveActor/ActorPoseUtil.h"
9#include "Library/Math/MathUtil.h"
10#include "Library/Nerve/NerveSetupUtil.h"
11#include "Library/Nerve/NerveUtil.h"
12#include "Library/Player/PlayerUtil.h"
13
14#include "Layout/MapLayout.h"
15#include "System/GameDataFunction.h"
16#include "System/GameDataHolderAccessor.h"
17
18namespace {
19NERVE_IMPL(Compass, Appear);
20NERVE_IMPL(Compass, End);
21NERVE_IMPL(Compass, Wait);
22
23NERVES_MAKE_NOSTRUCT(Compass, Appear, End, Wait);
24} // namespace
25
26namespace {
27bool isAreaMadness(al::AreaObj* area) {
28 bool isMadness = false;
29 return al::tryGetAreaObjArg(outArg: &isMadness, areaObj: area, key: "IsMadness") && isMadness;
30}
31} // namespace
32
33Compass::Compass(const char* name, const al::LayoutInitInfo& info,
34 const al::PlayerHolder* playerHolder)
35 : al::LayoutActor(name), mPlayerHolder(playerHolder) {
36 al::initLayoutActor(this, info, "TestCompass", nullptr);
37 initNerve(&Appear, 0);
38
39 mSceneCamInfo = getCameraDirector()->getSceneCameraInfo();
40 kill();
41}
42
43void Compass::appear() {
44 if (GameDataFunction::isMainStage(accessor: this)) {
45 al::LayoutActor::appear();
46 al::setNerve(user: this, nerve: &Appear);
47 field_14c = 0.0f;
48
49 al::LiveActor* player = al::tryGetPlayerActor(mPlayerHolder, 0);
50
51 if (player != nullptr) {
52 al::AreaObj* area = al::tryFindAreaObj(areaUser: player, name: "CompassArea", position: al::getTrans(actor: player));
53
54 if (area != nullptr && isAreaMadness(area))
55 return;
56 }
57
58 sead::Vector3f camDir{0.0f, 0.0f, 0.0f};
59
60 if (!al::tryCalcCameraLookDirH(lookDirH: &camDir, info: mSceneCamInfo, upDir: sead::Vector3f::ey, viewIdx: 0))
61 return;
62
63 sead::Vector3f northDir{0.0f, 0.0f, 0.0f};
64
65 if (!rs::tryCalcMapNorthDir(&northDir, this))
66 return;
67
68 f32 angle = al::calcAngleOnPlaneDegree(a: northDir, b: camDir, vertical: -sead::Vector3f::ey);
69 angle = al::modf(a: angle + 360.0f, b: 360.0f) + 0.0f;
70
71 f32 maxFrame = al::getActionFrameMax(layout: this, actionName: "Direction", paneName: "State");
72 f32 frame = al::normalize(x: angle, min: 0.0f, max: maxFrame);
73 al::startFreezeAction(layout: this, actionName: "Direction", frame, paneName: "State");
74 } else {
75 al::LiveActor* player = al::tryGetPlayerActor(mPlayerHolder, 0);
76
77 if (player == nullptr || !al::isInAreaObj(areaUser: player, name: "CompassArea", position: al::getTrans(actor: player)))
78 return;
79
80 al::LayoutActor::appear();
81 al::setNerve(user: this, nerve: &Appear);
82 field_14c = 0.0f;
83 }
84}
85
86void Compass::end() {
87 if (!al::isNerve(user: this, nerve: &End))
88 al::setNerve(user: this, nerve: &End);
89}
90
91void Compass::exeAppear() {
92 if (al::isFirstStep(user: this))
93 al::startAction(layout: this, actionName: "Appear", paneName: nullptr);
94
95 updateLayout();
96 al::setNerveAtActionEnd(layout: this, nerve: &Wait);
97}
98
99// void Compass::updateLayout();
100
101void Compass::exeWait() {
102 if (al::isFirstStep(user: this))
103 al::startAction(layout: this, actionName: "Wait", paneName: nullptr);
104
105 updateLayout();
106}
107
108void Compass::exeEnd() {
109 if (al::isFirstStep(user: this))
110 al::startAction(layout: this, actionName: "End", paneName: nullptr);
111
112 updateLayout();
113
114 if (al::isActionEnd(layout: this, paneName: nullptr))
115 kill();
116}
117