summaryrefslogtreecommitdiff
path: root/include/entity.h
blob: ca4bd10d0630a28efadd9f6ac3900f39ec817e4e (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
257
258
259
260
261
262
263
264
265
266
267
268
// clang-format off
#ifndef ENTITY_H
#define ENTITY_H

#include "global.h"
#include "sprite.h"

typedef enum {
    PLAYER = 1,
    ENEMY = 3,
    PROJECTILE = 4,
    OBJECT = 6,
    NPC = 7,
    PLAYER_ITEM = 8,
    MANAGER = 9,
} EntityType;

typedef struct {
    void* entity1;
    void* entity2;
    u8 filler[14];
} UnkStruct;

typedef struct {
    s8 offset_x;
    s8 offset_y;
    u8 unk2[4];
    u8 width;
    u8 height;
} Hitbox;

typedef struct {
    s8 offset_x;
    s8 offset_y;
    u8 unknown[4];
    u8 width;
    u8 height;
    u8 depth;
    u8 unknown2[3];
} Hitbox3D;

typedef struct Entity {
    /*0x00*/ struct Entity* prev;
    /*0x04*/ struct Entity* next;
    /*0x08*/ u8 kind; // was: type
    /*0x09*/ u8 id; // was: subtype
    /*0x0a*/ u8 type; // was: form
    /*0x0b*/ u8 type2; // was: parameter
    /*0x0c*/ u8 action;
    /*0x0d*/ u8 subAction;
    /*0x0e*/ u8 actionDelay;
    /*0x0f*/ u8 field_0xf;
    /*0x10*/ u8 flags;
    /*0x11*/ u8 scriptedScene : 4;
    /*    */ u8 scriptedScene2 : 4;
    /*0x12*/ s16 spriteIndex;
    /*0x14*/ u8 animationState;
    /*0x15*/ u8 direction;
    /*0x16*/ u8 field_0x16;
    /*0x17*/ u8 field_0x17;
    /*0x18*/ union {
    /*    */     u8 raw;
    /*    */     struct {
    /*    */         u32 draw        : 2; // 1-2
    /*    */         u32 ss2         : 1; //   4
    /*    */         u32 ss3         : 1; //   8
    /*    */         u32 shadow      : 2; //0x10-0x20
    /*    */         u32 flipX       : 1; //0x40
    /*    */         u32 flipY       : 1; //0x80
    /*    */     } PACKED b;
    /*    */ } PACKED spriteSettings;
    /*0x19*/ struct {
    /*    */     u32 b0         : 2; // 1-2
    /*    */     u32 alphaBlend : 2; // 4-8
    /*    */     u32 b2         : 2; //0x10
    /*    */     u32 b3         : 2; //0x40
    /*    */ } PACKED spriteRendering;
    /*0x1a*/ union {
    /*    */    u8 raw;
    /*    */    struct {
    /*    */        u8 b0 : 4;
    /*    */        u8 b4 : 4;
    /*    */    } PACKED b;
    /*    */ } PACKED palette;
    /*0x1b*/ struct {
    /*    */     u32 b0    : 1;
    /*    */     u32 b1    : 5; //0x10
    /*    */     u32 flipY : 2; //0x40
    /*    */ } PACKED spriteOrientation;
    /*0x1c*/ u8 field_0x1c;
    /*0x1d*/ u8 field_0x1d;
    /*0x1e*/ u8 frameIndex;
    /*0x1f*/ u8 lastFrameIndex;
    /*0x20*/ s32 field_0x20;
    /*0x24*/ s16 speed;
    /*0x26*/ u8 spriteAnimation[3];
    /*0x29*/ struct {
    /*    */     u8 b0 : 3; // 1-4
    /*    */     u8 b1 : 3; //   8
    /*    */     u8 b2 : 2; //0x40
    /*    */ } PACKED spritePriority;
    /*0x2a*/ u16 collisions;
    /*0x2c*/ union SplitWord x;
    /*0x30*/ union SplitWord y;
    /*0x34*/ union SplitWord height; // todo
    /*0x38*/ u8 collisionLayer;
    /*0x39*/ s8 interactType;
    /*0x3a*/ u8 field_0x3a;
    /*0x3b*/ u8 flags2;
    /*0x3c*/ u8 field_0x3c;
    /*0x3d*/ s8 iframes;
    /*0x3e*/ u8 field_0x3e;
    /*0x3f*/ u8 damageType;
    /*0x40*/ u8 field_0x40;
    /*0x41*/ u8 bitfield;
    /*0x42*/ u8 field_0x42;
    /*0x43*/ u8 field_0x43;
    /*0x44*/ u8 field_0x44;
    /*0x45*/ u8 currentHealth;
    /*0x46*/ u16 field_0x46;
    /*0x48*/ Hitbox* hitbox;
    /*0x4c*/ struct Entity* field_0x4c;
    /*0x50*/ struct Entity* parent;
    /*0x54*/ struct Entity* attachedEntity;
    /*0x58*/ u8 animIndex;
    /*0x59*/ u8 frameDuration;
    /*0x5a*/ union {
    /*    */     u8 all;
    /*    */     struct {
    /*    */         u8 f0 : 1;
    /*    */         u8 f1 : 5;
    /*    */         u8 f2 : 1; //0x40
    /*    */         u8 f3 : 1; //0x80
    /*    */    } PACKED b;
    /*    */ } PACKED frames;
    /*0x5b*/ u8 frameSpriteSettings;
    /*0x5c*/ Frame* animPtr;
    /*0x60*/ u16 spriteVramOffset;
    /*0x62*/ u8 spriteOffsetX;
    /*0x63*/ s8 spriteOffsetY;
    /*0x64*/ u32* myHeap;
    /*0x68*/ union SplitHWord field_0x68;
    /*0x6a*/ union SplitHWord field_0x6a;
    /*0x6c*/ union SplitHWord field_0x6c;
    /*0x6e*/ union SplitHWord field_0x6e;
    /*0x70*/ union SplitWord field_0x70;
    /*0x74*/ union SplitHWord field_0x74;
    /*0x76*/ union SplitHWord field_0x76;
    /*0x78*/ union SplitHWord field_0x78;
    /*0x7a*/ union SplitHWord field_0x7a;
    /*0x7c*/ union SplitWord field_0x7c;
    /*0x80*/ union SplitHWord field_0x80;
    /*0x82*/ union SplitHWord field_0x82;
    /*0x84*/ union SplitHWord cutsceneBeh;
    /*0x86*/ union SplitHWord field_0x86;
} Entity;

typedef struct LinkedList {
    Entity* last;
    Entity* first;
} LinkedList;

extern LinkedList gEntityLists[9];
extern LinkedList gUnk_03003D90;

extern LinkedList gUnk_03003DA0;

#define TILE(x, y)                                      \
    (((((x) - gRoomControls.roomOriginX) >> 4) & 0x3fU) | \
     ((((y) - gRoomControls.roomOriginY) >> 4) & 0x3fU) << 6)

#define COORD_TO_TILE(entity) \
    TILE((entity)->x.HALF.HI, (entity)->y.HALF.HI)

#define COORD_TO_TILE_OFFSET(entity, xOff, yOff) \
    TILE((entity)->x.HALF.HI - (xOff), (entity)->y.HALF.HI - (yOff))

enum {
    DirectionNorth  = 0x00,
    DirectionEast   = 0x08,
    DirectionSouth  = 0x10,
    DirectionWest   = 0x18,
};

#define DirectionRound(expr) ((expr) & 0x18)
#define DirectionRoundUp(expr) DirectionRound((expr) + 4)
#define DirectionIsHorizontal(expr) ((expr) & 0x08)
#define DirectionIsVertical(expr) ((expr) & 0x10)
#define DirectionTurnAround(expr) (DirectionRoundUp(expr) ^ 0x10)
#define DirectionToAnimationState(expr) (DirectionRoundUp(expr) >> 3)
#define DirectionFromAnimationState(expr) ((expr) << 3)

#define Direction8Round(expr) ((expr) & 0x1c)
#define Direction8RoundUp(expr) Direction8Round((expr) + 2)
#define Direction8TurnAround(expr) (Direction8RoundUp(expr) ^ 0x10)
#define Direction8ToAnimationState(expr) (Direction8RoundUp(expr) >> 2)
#define Direction8FromAnimationState(expr) (((expr) << 2)

Entity* GetEmptyEntity(void);
extern Entity* CreateEnemy(u32 id, u32 type);
extern Entity* CreateNPC(u32 id, u32 type, u32 type2);
extern Entity* CreateObject(u32 id, u32 type, u32 type2);
extern Entity* CreateObjectWithParent(Entity* parent, u32 id, u32 type, u32 type2);
extern Entity* CreateFx(Entity* parent, u32 type, u32 type2);

extern void InitializeAnimation(Entity*, u32);
extern void InitAnimationForceUpdate(Entity*, u32);
extern void UpdateAnimationSingleFrame(Entity*);
extern void UpdateSpriteForCollisionLayer(Entity*);
extern void GetNextFrame(Entity*);
extern u32 LoadExtraSpriteData(Entity*, SpriteLoadData*);
extern void SetExtraSpriteFrame(Entity*, u32, u32);
extern void SetSpriteSubEntryOffsetData1(Entity*, u32, u32);
extern void SetSpriteSubEntryOffsetData2(Entity*, u32, u32);

extern u32 GetFacingDirection(Entity*, Entity*);

/**
 * @brief Delete the entity currently in execution.
 */
void DeleteThisEntity(void);

/**
 * @brief Delete an entity.
 */
void DeleteEntity(Entity*);

/**
 * @brief Append entity to linked list.
 */
void AppendEntityToList(Entity* entity, u32 listIndex);

/**
 * @brief Prepend entity to linked list.
 */
void PrependEntityToList(Entity* entity, u32 listIndex);

/**
 * @brief Find an entity for a given kind and ID.
 * @return Entity* First result or NULL if none found
 */
Entity* FindEntityByID(u32 kind, u32 id, u32 listIndex);

/**
 * @brief Search all lists for an entity of same kind and id.
 * @return Entity* First result or NULL if none found
 */
Entity* DeepFindEntityByID(u32 kind, u32 id);

/**
 * @brief Search all lists for entity of same kind and id.
 * @return bool32 Duplicate was entity found
 */
bool32 EntityHasDuplicateID(Entity* ent);

/**
 * @brief Find an entity of same kind and id in list.
 * @return Entity* First result or NULL if none found
 */
Entity* FindNextDuplicateID(Entity* ent, int listIndex);

/**
 * @brief Find Entity with full identifiers.
 * @return Entity* First result or NULL if none found
 */
Entity* FindEntity(u32 kind, u32 id, u32 listIndex, u32 type, u32 type2);

#endif