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
|
/**
* @file mask.c
* @ingroup Objects
*
* @brief Mask object
*/
#include "functions.h"
#include "object.h"
typedef struct {
/*0x00*/ Entity base;
/*0x68*/ u8 unused1[16];
/*0x78*/ u16 unk_78;
/*0x7a*/ u16 unk_7a;
/*0x7c*/ u16 unk_7c;
/*0x7e*/ u16 unk_7e;
/*0x80*/ u8 unused2[6];
/*0x86*/ u16 unk_86;
} MaskEntity;
void Mask_Init(MaskEntity* this);
void Mask_Action1(MaskEntity* this);
void Mask_Action2(MaskEntity* this);
void Mask_Delete(MaskEntity* this);
void Mask(MaskEntity* this) {
static void (*const Mask_Actions[])(MaskEntity*) = {
Mask_Init,
Mask_Action1,
Mask_Action2,
Mask_Delete,
};
Mask_Actions[super->action](this);
}
void Mask_Init(MaskEntity* this) {
if (super->type2 & 0xC0) {
if (CheckFlags(this->unk_86)) {
s32 field_0x0a;
switch (super->type2 & 0xC0) {
case 0x40:
field_0x0a = gRoomTransition.stairs_idx;
switch (field_0x0a) {
case 0x44D ... 0x44F:
case 0x182:
DeleteThisEntity();
break;
default:
ClearFlag(this->unk_86);
}
break;
case 0x80:
DeleteThisEntity();
break;
}
}
}
super->action = 1;
super->zVelocity = Q_16_16(1.5);
this->unk_78 = ((Random() & 7) << 10) | 0x2000;
super->subtimer = super->timer >> 1;
super->timer = 0;
super->frameIndex = super->type2 & 0x3f;
this->unk_7e = COORD_TO_TILE(super);
this->unk_7c = GetTileIndex(this->unk_7e, 1);
this->unk_7a = sub_080B1B44(this->unk_7e, 1);
SetBottomTile(0x4022, this->unk_7e, 1);
}
// Probably related to knocking it down
void Mask_Action1(MaskEntity* this) {
// Check for the first frame of bonking animation
if (gPlayerEntity.base.action != PLAYER_BOUNCE) {
return;
}
if (gPlayerEntity.base.animationState != 0) {
return;
}
// Check if link is close enough to the mask
if (super->y.HALF.HI + 40 < gPlayerEntity.base.y.HALF.HI) {
return;
}
if (super->x.HALF.HI - gPlayerEntity.base.x.HALF.HI >= super->subtimer ||
super->x.HALF.HI - gPlayerEntity.base.x.HALF.HI <= -super->subtimer) {
return;
}
// Presumably, make the mask fall
SetBottomTile(this->unk_7c, this->unk_7e, 1);
sub_08000148(this->unk_7a, this->unk_7e, 1);
super->action = 2;
super->z.HALF.HI -= 0x20;
super->y.HALF.HI += 0x20;
super->spriteRendering.b3 = 2;
}
// Probably falling down
void Mask_Action2(MaskEntity* this) {
if (super->timer == 1) {
super->action = 3;
super->timer = 0;
switch (super->type2 & 0xC0) {
case 0x80:
EnqueueSFX(SFX_SECRET);
case 0x40:
SetFlag(this->unk_86);
break;
}
CreateFx(super, FX_POT_SHATTER, 0);
CreateRandomItemDrop(super, 3);
} else {
BounceUpdate(super, this->unk_78);
if (super->z.HALF.HI == 0) {
super->timer++;
}
}
}
void Mask_Delete(MaskEntity* this) {
DeleteThisEntity();
}
|