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
|
#include "libultraship/libultraship.h"
#include "2s2h/GameInteractor/GameInteractor.h"
extern "C" {
#include "z64.h"
#include "functions.h"
#include "overlays/actors/ovl_En_Slime/z_en_slime.h"
extern PlayState* gPlayState;
void EnItem00_Draw(Actor* thisx, PlayState* play);
}
bool ItemShouldSpinWhen3D(Actor* actor) {
EnItem00* enItem00 = (EnItem00*)actor;
// Exclude actors that already have spin normally, or shouldn't spin ever
if ((actor->params <= ITEM00_RUPEE_RED) || ((actor->params == ITEM00_RECOVERY_HEART) && (enItem00->unk152 < 0)) ||
(actor->params == ITEM00_HEART_PIECE) || (actor->params == ITEM00_HEART_CONTAINER) ||
(actor->params == ITEM00_RUPEE_HUGE) || (actor->params == ITEM00_RUPEE_PURPLE) ||
(actor->params == ITEM00_SHIELD_HERO) || (actor->params == ITEM00_MAP) || (actor->params == ITEM00_COMPASS)) {
return false;
}
return true;
}
void EnItem00_3DItemsDraw(Actor* actor, PlayState* play) {
EnItem00* enItem00 = (EnItem00*)actor;
if (!(enItem00->unk14E & enItem00->unk150)) {
switch (enItem00->actor.params) {
case ITEM00_RUPEE_GREEN:
Matrix_Scale(25.0f, 25.0f, 25.0f, MTXMODE_APPLY);
GetItem_Draw(play, GID_RUPEE_GREEN);
break;
case ITEM00_RUPEE_BLUE:
Matrix_Scale(25.0f, 25.0f, 25.0f, MTXMODE_APPLY);
GetItem_Draw(play, GID_RUPEE_BLUE);
break;
case ITEM00_RUPEE_RED:
Matrix_Scale(25.0f, 25.0f, 25.0f, MTXMODE_APPLY);
GetItem_Draw(play, GID_RUPEE_RED);
break;
case ITEM00_RUPEE_HUGE:
Matrix_Scale(17.5f, 17.5f, 17.5f, MTXMODE_APPLY);
GetItem_Draw(play, GID_RUPEE_HUGE);
break;
case ITEM00_RUPEE_PURPLE:
Matrix_Scale(17.5f, 17.5f, 17.5f, MTXMODE_APPLY);
GetItem_Draw(play, GID_RUPEE_PURPLE);
break;
case ITEM00_HEART_PIECE:
Matrix_Scale(16.0f, 16.0f, 16.0f, MTXMODE_APPLY);
GetItem_Draw(play, GID_HEART_PIECE);
break;
case ITEM00_HEART_CONTAINER:
Matrix_Scale(16.0f, 16.0f, 16.0f, MTXMODE_APPLY);
GetItem_Draw(play, GID_HEART_CONTAINER);
break;
case ITEM00_RECOVERY_HEART:
Matrix_Scale(16.0f, 16.0f, 16.0f, MTXMODE_APPLY);
GetItem_Draw(play, GID_RECOVERY_HEART);
break;
case ITEM00_BOMBS_A:
case ITEM00_BOMBS_B:
case ITEM00_BOMBS_0:
Matrix_Scale(8.0f, 8.0f, 8.0f, MTXMODE_APPLY);
GetItem_Draw(play, GID_BOMB);
break;
case ITEM00_ARROWS_10:
Matrix_Scale(7.0f, 7.0f, 7.0f, MTXMODE_APPLY);
GetItem_Draw(play, GID_ARROWS_SMALL);
break;
case ITEM00_ARROWS_30:
Matrix_Scale(7.0f, 7.0f, 7.0f, MTXMODE_APPLY);
GetItem_Draw(play, GID_ARROWS_MEDIUM);
break;
case ITEM00_ARROWS_40:
case ITEM00_ARROWS_50:
Matrix_Scale(7.0f, 7.0f, 7.0f, MTXMODE_APPLY);
GetItem_Draw(play, GID_ARROWS_LARGE);
break;
case ITEM00_MAGIC_JAR_SMALL:
Matrix_Scale(8.0f, 8.0f, 8.0f, MTXMODE_APPLY);
GetItem_Draw(play, GID_MAGIC_JAR_SMALL);
break;
case ITEM00_MAGIC_JAR_BIG:
Matrix_Scale(8.0f, 8.0f, 8.0f, MTXMODE_APPLY);
GetItem_Draw(play, GID_MAGIC_JAR_BIG);
break;
case ITEM00_DEKU_STICK:
Matrix_Scale(7.5f, 7.5f, 7.5f, MTXMODE_APPLY);
GetItem_Draw(play, GID_DEKU_STICK);
break;
case ITEM00_SMALL_KEY:
Matrix_Scale(8.0f, 8.0f, 8.0f, MTXMODE_APPLY);
GetItem_Draw(play, GID_KEY_SMALL);
break;
case ITEM00_DEKU_NUTS_1:
case ITEM00_DEKU_NUTS_10:
Matrix_Scale(9.0f, 9.0f, 9.0f, MTXMODE_APPLY);
GetItem_Draw(play, GID_DEKU_NUTS);
break;
case ITEM00_SHIELD_HERO:
GetItem_Draw(play, GID_SHIELD_HERO);
break;
case ITEM00_MAP:
GetItem_Draw(play, GID_DUNGEON_MAP);
break;
case ITEM00_COMPASS:
GetItem_Draw(play, GID_COMPASS);
break;
}
}
}
void DrawSlime3DItem(Actor* actor, bool* should) {
*should = false;
EnSlime* slime = (EnSlime*)actor;
// Rotate 3D item with chu body
Matrix_RotateYS(slime->actor.shape.rot.y, MTXMODE_APPLY);
Matrix_Scale(0.25f, 0.25f, 0.25f, MTXMODE_APPLY);
switch (slime->actor.params) {
case EN_SLIME_TYPE_RED:
GetItem_Draw(gPlayState, GID_RECOVERY_HEART);
break;
case EN_SLIME_TYPE_GREEN:
GetItem_Draw(gPlayState, GID_MAGIC_JAR_SMALL);
break;
case EN_SLIME_TYPE_YELLOW:
GetItem_Draw(gPlayState, GID_ARROWS_SMALL);
break;
}
}
void Register3DItemDrops() {
static HOOK_ID actorInitHookID = 0;
static HOOK_ID actorUpdateHookID = 0;
static HOOK_ID slimeVBHookID = 0;
GameInteractor::Instance->UnregisterGameHookForID<GameInteractor::OnActorInit>(actorInitHookID);
GameInteractor::Instance->UnregisterGameHookForID<GameInteractor::OnActorUpdate>(actorUpdateHookID);
GameInteractor::Instance->UnregisterGameHookForID<GameInteractor::ShouldVanillaBehavior>(slimeVBHookID);
actorInitHookID = 0;
actorUpdateHookID = 0;
slimeVBHookID = 0;
if (gPlayState != NULL) {
Actor* actor = gPlayState->actorCtx.actorLists[ACTORCAT_MISC].first;
while (actor != NULL) {
if (actor->id == ACTOR_EN_ITEM00) {
if (CVarGetInteger("gEnhancements.Graphics.3DItemDrops", 0)) {
actor->draw = EnItem00_3DItemsDraw;
} else {
actor->draw = EnItem00_Draw;
// Reset rotation for bill-boarded sprites
if (ItemShouldSpinWhen3D(actor)) {
actor->shape.rot.y = 0;
}
}
}
actor = actor->next;
}
}
if (!CVarGetInteger("gEnhancements.Graphics.3DItemDrops", 0)) {
return;
}
actorInitHookID = GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorInit>(
ACTOR_EN_ITEM00, [](Actor* actor) { actor->draw = EnItem00_3DItemsDraw; });
actorUpdateHookID = GameInteractor::Instance->RegisterGameHookForID<GameInteractor::OnActorUpdate>(
ACTOR_EN_ITEM00, [](Actor* actor) {
// Add spin to normally bill-boarded items
if (ItemShouldSpinWhen3D(actor)) {
actor->shape.rot.y += 0x3C0;
}
});
slimeVBHookID = REGISTER_VB_SHOULD(VB_DRAW_SLIME_BODY_ITEM, {
Actor* actor = va_arg(args, Actor*);
DrawSlime3DItem(actor, should);
});
}
|