summaryrefslogtreecommitdiff
path: root/include/toBeSorted/attention.h
blob: 17cb9b04d826fab6481a91fdd90e65fd193e68b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
#ifndef TOBESORTED_ATTENTION_H
#define TOBESORTED_ATTENTION_H

#include "common.h"
#include "d/a/obj/d_a_obj_base.h"
#include "m/m3d/m_anmchr.h"
#include "m/m3d/m_anmmatclr.h"
#include "m/m3d/m_anmtexpat.h"
#include "m/m3d/m_smdl.h"
#include "m/m_allocator.h"
#include "toBeSorted/d_emitter.h"
#include "toBeSorted/raii_ptr.h"

static const u32 OFF = 'off ';
static const u32 NONE = 'none';
static const u32 KEEP = 'keep';
static const u32 NEXT = 'next';
static const u32 ON = 'on  ';
static const u32 AWAY = 'away';

class InteractionMdl {
public:
    m3d::smdl_c mMdl;
    m3d::anmMatClr_c mAnmClr;
    m3d::anmTexPat_c mAnmTex;
    RaiiPtr<m3d::anmChr_c> mAnmChr;
    u8 field_0x78;
    u8 field_0x79;

    InteractionMdl() {}
    ~InteractionMdl() {}
};

enum InteractionType {
    /*  0 */ UNK_0,
    /*  1 */ PICK_UP,
    /*  2 */ OPEN,
    /*  3 */ UNK_3,
    /*  4 */ TALK,
    /*  5 */ EXAMINE_TALK,
    /*  6 */ EXAMINE_6,
    /*  7 */ UNK_7,
    /*  8 */ GET_IN,
    /*  9 */ READY_SWORD,
    /* 10 */ UNK_10,
    /* 11 */ UNK_11,
    /* 12 */ READ,
    /* 13 */ GRAB,
    /* 14 */ CATCH,
    /* 15 */ UNK_15,
    /* 16 */ UNK_16,
    /* 17 */ DIG,
    /* 18 */ UNK_18,
    /* 19 */ SIT,
    /* 20 */ UNK_20,

    UNK_0x58 = 0x58,
};

class AttentionInfo {
public:
    AttentionInfo() {}
    ~AttentionInfo() {}

    /* 0x00 */ u8 unk;
    /* 0x01 */ u8 mActorIdx;
    /* 0x02 */ u8 mInteractionType;
    /* 0x03 */ u8 field_0x03;
    /* 0x04 */ f32 field_0x04;
    /* 0x08 */ mVec3_c field_0x08;
};

class AttentionPool {
public:
    AttentionPool() {}
    ~AttentionPool() {}
    dAcRef_c<dAcObjBase_c> mRefs[8];
    AttentionInfo mInfos[8];
    s32 mNumUsedRefs;

    int fn_80096190(dAcObjBase_c *actor, u8 unk, InteractionType interactionType);
    bool insertTarget(
        dAcObjBase_c *actor, u32 unk1, mVec3_c *pos, InteractionType interactionType, u8 field_0x03, f32 field_0x04
    );

    dAcObjBase_c *getActor(s32 i) {
        // This only matches if the comparision is always true
        // Logic is hard sometimes I guess xD
        return i < mNumUsedRefs && mInfos[i].mActorIdx != -1 ? mRefs[mInfos[i].mActorIdx].get() : nullptr;
    }

    void clear() {
        for (int i = 0; i < 8; i++) {
            mInfos[i].unk = 0;
            mInfos[i].mActorIdx = -1;
            mInfos[i].field_0x04 = 0.0f;
            mInfos[i].field_0x03 = 0;
            mInfos[i].mInteractionType = 0;
            mRefs[i].unlink();
        }
        mNumUsedRefs = 0;
    }
};

class AttentionGroup {
public:
    AttentionGroup() {}
    ~AttentionGroup() {}

    AttentionPool mPools[2];
    u32 mWhichPool;

    AttentionPool *getOtherPool() {
        return &mPools[mWhichPool ^ 1];
    }

    AttentionPool *getPool() {
        return &mPools[mWhichPool];
    }

    void fn_800964B0();
};

struct InteractionTargetDef {
    s32 field_0x00;
    u32 field_0x04;
    u32 field_0x08;
    InteractionType interactType;
    u32 interactFlags;
    f32 field_0x14;
    f32 field_0x18;
    f32 field_0x1C;
    f32 field_0x20;
    f32 field_0x24;
    f32 field_0x28;
    f32 field_0x2C;
};

// TODO this may include more things from AttentionManager, see AttentionManager's dtor
class InteractionModels {
public:
    /* 0x00 */ UNKWORD field_0xA5C;
    /* 0x04 */ s32 mCurrentTargetInfoIdx;
    /* 0x08 */ u32 mState;
    /* 0x0C */ nw4r::g3d::ResFile mResFile;
    /* 0x10 */ InteractionMdl mMdls[2];
};

class AttentionManager {
    mHeapAllocator_c mAllocator;
    /* 0x01C */ AttentionGroup mGroups[5];
    /* 0xA58 */ bool mTargeted;
    /* 0xA59 */ bool mHoldingZ;
    /* 0xA5A */ u8 field_0xA58[0xA5C - 0xA5A];
    /* 0xA5C */ InteractionModels mModels;
    /* 0xB64 */ u8 mHasTarget;
    /* 0xB65 */ u8 field_0xB65[0xB68 - 0xB65];
    /* 0xB68 */ UNKWORD field_0xB68;
    /* 0xB6C */ dEmitter_c mEffect1;
    /* 0xBA0 */ dEmitter_c mEffect2;
    /* 0xBD4 */ u8 field_0xBD4;
    /* 0xBD5 */ u8 field_0xBD5;

public:
    AttentionManager();
    /* vt at 0xBDC */ virtual ~AttentionManager();

    static AttentionManager *GetInstance() {
        return sInstance;
    }

private:
    /* 0xBDC */ u8 field_0xBDC;

public:
    static AttentionManager *sInstance;
    enum Flags_e {
        FLAGS_0,
        FLAGS_1,
        FLAGS_2,
        FLAGS_3,
    };
    bool create();
    bool createHeap();
    bool execute();
    bool draw();

    void addTarget(dAcObjBase_c &actor, const InteractionTargetDef &def, u32, mVec3_c *);

    void addPickUpTarget(dAcObjBase_c &actor, f32 field_0x14);
    void addSitTarget(dAcObjBase_c &actor, f32 field_0x14, Flags_e flags);

    void addTalkTarget_unused(dAcObjBase_c &actor);

    void
    addExamineTalkTarget(dAcObjBase_c &actor, u32 flags, f32 field_0x14, f32 ignored, f32 field_0x20, f32 field_0x24);
    void addExamineTalkTarget(dAcObjBase_c &actor, u32 flags, f32 field_0x14, f32 field_0x20, f32 field_0x24);

    void addCatchTarget(dAcObjBase_c &actor, u32 flags, f32 field_0x14, f32 field_0x24_neg, f32 field_0x20_neg);

    void addCatchLikeTarget(
        dAcObjBase_c &actor, InteractionType interactionType, u32 flags, f32 field_0x14, f32 field_0x24_neg,
        f32 field_0x20_neg
    );

    void addUnk3Target(dAcObjBase_c &actor, u32 flags, f32 field_0x14, f32 field_0x24_neg, f32 field_0x20_neg);

    void
    addUnk3Target(dAcObjBase_c &actor, u32 flags, f32 arg5, f32 field_0x14, f32 field_0x24_neg, f32 field_0x20_neg);
    void addUnk3Target(
        dAcObjBase_c &actor, u32 arg2, mVec3_c *arg3, u32 flags, f32 arg5, f32 field_0x14, f32 field_0x24_neg,
        f32 field_0x20_neg
    );

    void addNpcTalkTarget(dAcObjBase_c &actor, u32 flags, f32 field_0x14, f32 ignored, f32 field_0x20, f32 field_0x24);

    void
    addUnk7Target(dAcObjBase_c &actor, u32 flags, f32 arg5, f32 field_0x14, f32 field_0x24_neg, f32 field_0x20_neg);

    void addReadTarget(dAcObjBase_c &actor, u32 flags, f32 field_0x14, f32 ignored, f32 field_0x20, f32 field_0x24);
    void addReadTarget2(dAcObjBase_c &actor, u32 flags, f32 field_0x14, f32 field_0x20, f32 field_0x24);

    bool checkLink2() const;

    dAcObjBase_c *getTargetedActor() {
        if (!isInNormalGameState() || !mTargeted) {
            return nullptr;
        }
        return getTargetedActorUnchecked();
    }

    dAcObjBase_c *getTargetedActorUnchecked() {
        return mGroups[1].getOtherPool()->getActor(mModels.mCurrentTargetInfoIdx);
    }

private:
    bool isInNormalGameState() const;
    bool checkZButtonPressed() const;
    bool checkZButtonHeld() const;
    bool checkLink1() const;
    bool switchTarget(s32 target);
    bool playTargetAnim(s32 target);

    bool isZButtonPressed() const;
    bool isZButtonHeld() const;
    bool checkUnknown() const;

    bool collisionCheck0(const mVec3_c &a, const mVec3_c &b);
    bool collisionCheck1(const mVec3_c &a, const mVec3_c &b);
    bool collisionCheck2(const mVec3_c &a, const mVec3_c &b);

    bool fn_80096B40(dAcObjBase_c *actor);
    f32 targetScore(dAcObjBase_c *target, dAcObjBase_c *origin);
};

#endif