Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
tubba_heart_attack.c File Reference

Go to the source code of this file.

Enumerations

enum  MiniHeartState {
  HEART_STATE_INIT = 0 , HEART_STATE_APPEAR = 1 , HEART_STATE_SWARM = 2 , HEART_STATE_MISS = 20 ,
  HEART_STATE_WAIT = 3 , HEART_STATE_SQUEEZE = 4 , HEART_STATE_DISPERSE = 5 , HEART_STATE_VANISH = 6 ,
  HEART_STATE_DONE = 7
}
 

Functions

void tubba_heart_attack_init (EffectInstance *effect)
 
void tubba_heart_attack_update (EffectInstance *effect)
 
void tubba_heart_attack_render (EffectInstance *effect)
 
void tubba_heart_attack_appendGfx (void *effect)
 
EffectInstancetubba_heart_attack_main (s32 type, f32 arg1, f32 arg2, f32 arg3, f32 arg4, s32 duration)
 
 EFFECT_DEF_FLOATING_CLOUD_PUFF (floating_cloud_puff_main)
 
void func_E00CC9C8 (void)
 

Variables

Gfx D_09000400_3D2980 []
 
Gfx D_09000518_3D2A98 []
 
u8 AnimScalePct [] = { 94, 92, 100, 105, 107, 105, 100 }
 
u8 AppearScalePct [] = { 20, 40, 58, 73, 85, 92, 97, 100 }
 
u8 SwarmInterpPct []
 
u8 MissInterpPct []
 
u8 SqueezeInterpPct []
 
s8 HeartOffsetY [TUBBA_MINI_HEART_COUNT]
 

Enumeration Type Documentation

◆ MiniHeartState

Enumerator
HEART_STATE_INIT 
HEART_STATE_APPEAR 
HEART_STATE_SWARM 
HEART_STATE_MISS 
HEART_STATE_WAIT 
HEART_STATE_SQUEEZE 
HEART_STATE_DISPERSE 
HEART_STATE_VANISH 
HEART_STATE_DONE 

Definition at line 4 of file tubba_heart_attack.c.

4 {
14};
@ HEART_STATE_MISS
@ HEART_STATE_DONE
@ HEART_STATE_SWARM
@ HEART_STATE_SQUEEZE
@ HEART_STATE_VANISH
@ HEART_STATE_INIT
@ HEART_STATE_WAIT
@ HEART_STATE_APPEAR
@ HEART_STATE_DISPERSE

Function Documentation

◆ tubba_heart_attack_init()

void tubba_heart_attack_init ( EffectInstance * effect)

Definition at line 119 of file tubba_heart_attack.c.

119 {
120}

Referenced by tubba_heart_attack_main().

◆ tubba_heart_attack_update()

void tubba_heart_attack_update ( EffectInstance * effect)

Definition at line 124 of file tubba_heart_attack.c.

124 {
126 EffectInstance* puffEffect;
127 s32 type = data->type;
128 s32 time;
129 f32 factor;
130 f32 angle;
131 f32 sin;
132 f32 cos;
133 Matrix4f mtx;
134 Matrix4f tempMtx;
135 s32 i;
136 s32 j;
137
138 if (effect->flags & FX_INSTANCE_FLAG_DISMISS) {
139 effect->flags &= ~FX_INSTANCE_FLAG_DISMISS;
140 data->timeLeft = 64;
141 }
142
143 if (data->timeLeft < 1000) {
144 data->timeLeft--;
145 }
146
147 data->lifetime++;
148
149 if (data->timeLeft < 0) {
150 remove_effect(effect);
151 return;
152 }
153
154 time = data->lifetime;
155
156 for (i = 0; i < TUBBA_MINI_HEART_COUNT; i++) {
157 f32 x = data->initialX[i];
158 f32 y = data->initialY[i];
159 f32 z = data->initialZ[i];
160
161 data->scaleY[i] = AnimScalePct[time % ARRAY_COUNT(AnimScalePct)] * 0.01f;
162 data->scaleX[i] = 2.0f - data->scaleY[i];
163
164 switch (data->state[i]) {
165 case HEART_STATE_INIT:
166 data->posX[i] = x;
167 data->posY[i] = y;
168 data->posZ[i] = z;
169 data->rotXY[i] += 0.0f;
170
171 if (data->appearDelay[i] != 0) {
172 data->appearDelay[i]--;
173 break;
174 }
175
176 data->state[i] = HEART_STATE_APPEAR;
177 data->scaleX[i] = data->scaleY[i] = AppearScalePct[data->stateTime[i]] * 0.01;
178 data->stateTime[i]++;
179 break;
181 data->scaleX[i] = data->scaleY[i] = AppearScalePct[data->stateTime[i]] * 0.01;
182 data->rotXY[i] += 0.0f;
183
184 data->stateTime[i]++;
185 if (data->stateTime[i] >= ARRAY_COUNT(AppearScalePct)) {
186 if (type == FX_HEART_SWARM_HIT) {
187 data->state[i] = HEART_STATE_SWARM;
188 } else {
189 data->state[i] = HEART_STATE_MISS;
190 }
191 data->stateTime[i] = 0;
192 }
193 break;
194 case HEART_STATE_MISS:
195 data->rotXY[i] += 0.0f;
196
197 factor = MissInterpPct[data->stateTime[i]] * 0.01;
198
199 data->scaleX[i] = data->scaleY[i] = 1.0f;
200 data->posX[i] = x + (data->finalX[i] - x) * factor;
201 data->posY[i] = y + (data->finalY[i] - y) * factor;
202 data->posZ[i] = z + (data->finalZ[i] - z) * factor;
203
204 data->stateTime[i]++;
205 if (data->stateTime[i] >= ARRAY_COUNT(MissInterpPct)) {
206 data->state[i] = HEART_STATE_DISPERSE;
207 data->stateTime[i] = 0;
208 data->shrinkVelX[i] = data->finalX[i] * 0.5;
209 data->shrinkVelY[i] = data->finalY[i] * 0.5;
210 data->shrinkVelZ[i] = data->finalZ[i] * 0.5;
211 }
212 break;
214 data->rotXY[i] += 0.0f;
215
216 factor = SwarmInterpPct[data->stateTime[i]] * 0.01;
217
218 data->scaleY[i] = 1.0f;
219 data->scaleX[i] = 1.0f;
220 data->posX[i] = x + (data->finalX[i] - x) * factor;
221 data->posY[i] = y + (data->finalY[i] - y) * factor;
222 data->posZ[i] = z + (data->finalZ[i] - z) * factor;
223
224 data->stateTime[i]++;
225 if (data->stateTime[i] >= ARRAY_COUNT(SwarmInterpPct)) {
226 data->state[i] = HEART_STATE_WAIT;
227 data->stateTime[i] = 0;
228 }
229 break;
230 case HEART_STATE_WAIT:
231 if (i == 24) {
232 for (j = 0; j < ARRAY_COUNT(data->state); j++) {
233 data->state[j] = HEART_STATE_SQUEEZE;
234 }
235 }
236 break;
238 factor = SqueezeInterpPct[data->stateTime[i]] * 0.01;
239 angle = i * 1080 / TUBBA_MINI_HEART_COUNT + (1.0f - factor) * 1080.0f * 0.5 * cos_deg(i * 180 / TUBBA_MINI_HEART_COUNT);
240 sin = sin_deg(angle);
241 cos = cos_deg(angle);
242
243 data->posX[i] = ((15.0f / factor) / factor) * sin;
244 data->posY[i] = HeartOffsetY[i] + 10;
245 data->posZ[i] = ((15.0f / factor) / factor) * cos;
246
247 data->stateTime[i]++;
248 if (data->stateTime[i] >= ARRAY_COUNT(SqueezeInterpPct)) {
249 data->state[i] = HEART_STATE_DISPERSE;
250 data->stateTime[i] = 0;
251 data->shrinkVelX[i] = data->finalX[i] * 0.5;
252 data->shrinkVelY[i] = data->finalY[i] * 0.5;
253 data->shrinkVelZ[i] = data->finalZ[i] * 0.5;
254 }
255 break;
257 data->posX[i] += data->shrinkVelX[i];
258 data->posY[i] += data->shrinkVelY[i];
259 data->posZ[i] += data->shrinkVelZ[i];
260 data->shrinkVelX[i] *= 0.99;
261 data->shrinkVelY[i] *= 0.99;
262 data->shrinkVelZ[i] *= 0.99;
263 data->shrinkVelY[i] += -0.1;
264
265 data->stateTime[i]++;
266 if (data->stateTime[i] >= 17) {
267 data->stateTime[i] = 0;
268 data->state[i] = HEART_STATE_VANISH;
269 }
270
271 data->rotZ[i] *= 0.9;
272 break;
274 load_effect(EFFECT_FLOATING_CLOUD_PUFF);
275 guRotateF(mtx, data->rotXY[i], 0.0f, 1.0f, 0.0f);
276 guTranslateF(tempMtx, data->posX[i], data->posY[i], data->posZ[i]);
277 guMtxCatF(tempMtx, mtx, mtx);
278
279 puffEffect = floating_cloud_puff_main(0, data->centerX + mtx[3][0], data->centerY + mtx[3][1], data->centerZ + mtx[3][2], 1.0f, 16);
280 puffEffect->data.floatingCloudPuff->unk_28 = 100;
281 puffEffect->data.floatingCloudPuff->unk_2C = 0;
282 puffEffect->data.floatingCloudPuff->unk_30 = 0;
283
284 data->state[i] = HEART_STATE_DONE;
285 break;
286 }
287 }
288}
f32 Matrix4f[4][4]
#define guRotateF
#define sin_deg
#define guTranslateF
#define guMtxCatF
#define remove_effect
#define load_effect
#define cos_deg
#define TUBBA_MINI_HEART_COUNT
Definition effects.h:1797
struct TubbaHeartAttackFXData * tubbaHeartAttack
Definition effects.h:2566
@ FX_HEART_SWARM_HIT
Definition effects.h:1800
struct FloatingCloudPuffFXData * floatingCloudPuff
Definition effects.h:2569
EffectData data
Definition effects.h:2605
@ FX_INSTANCE_FLAG_DISMISS
Definition enums.h:3517
EffectInstance * floating_cloud_puff_main(s32 arg0, f32 arg1, f32 arg2, f32 arg3, f32 arg4, s32 arg5)
#define ARRAY_COUNT(arr)
Definition macros.h:40
u8 SwarmInterpPct[]
u8 SqueezeInterpPct[]
u8 AppearScalePct[]
u8 AnimScalePct[]
u8 MissInterpPct[]
s8 HeartOffsetY[TUBBA_MINI_HEART_COUNT]

Referenced by tubba_heart_attack_main().

◆ tubba_heart_attack_render()

void tubba_heart_attack_render ( EffectInstance * effect)

Definition at line 290 of file tubba_heart_attack.c.

290 {
291 RenderTask renderTask;
292 RenderTask* retTask;
293
295 renderTask.appendGfxArg = effect;
296 renderTask.dist = 10;
298
299 retTask = queue_render_task(&renderTask);
301}
#define queue_render_task
@ RENDER_TASK_FLAG_REFLECT_FLOOR
Definition enums.h:3318
@ RENDER_MODE_CLOUD_NO_ZCMP
Definition enums.h:3311
void * appendGfxArg
void(* appendGfx)(void *)
void tubba_heart_attack_appendGfx(void *effect)

Referenced by tubba_heart_attack_main().

◆ tubba_heart_attack_appendGfx()

void tubba_heart_attack_appendGfx ( void * effect)

Definition at line 306 of file tubba_heart_attack.c.

306 {
307 TubbaHeartAttackFXData* data = ((EffectInstance*)effect)->data.tubbaHeartAttack;
308 Camera* camera = &gCameras[gCurrentCameraID];
309 s32 alpha = data->primA;
310 Matrix4f sp18;
311 Matrix4f sp58;
312 s32 i;
313
314 gDPPipeSync(gMainGfxPos++);
315 gSPSegment(gMainGfxPos++, 0x09, VIRTUAL_TO_PHYSICAL(((EffectInstance*)effect)->graphics->data));
316
317 guTranslateF(sp18, data->centerX, data->centerY, data->centerZ);
318 guScaleF(sp58, data->overallScale, data->overallScale, data->overallScale);
319 guMtxCatF(sp58, sp18, sp18);
321
322 gSPMatrix(gMainGfxPos++, &gDisplayContext->matrixStack[gMatrixListPos++], G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
323 gDPSetPrimColor(gMainGfxPos++, 0, 0, data->primR, data->primG, data->primB, alpha);
324 gDPSetEnvColor(gMainGfxPos++, 0, 0, 0, 0);
325 gSPDisplayList(gMainGfxPos++, D_09000400_3D2980);
326
327 for (i = 0; i < TUBBA_MINI_HEART_COUNT; i++) {
328 if (data->state[i] != HEART_STATE_INIT && data->state[i] != HEART_STATE_DONE) {
329 guRotateF(sp18, data->rotXY[i], 0.0f, 1.0f, 0.0f);
330 guTranslateF(sp58, data->posX[i], data->posY[i], data->posZ[i]);
331 guMtxCatF(sp58, sp18, sp18);
332 guRotateF(sp58, -data->rotXY[i], 0.0f, 1.0f, 0.0f);
333 guMtxCatF(sp58, sp18, sp18);
334 guRotateF(sp58, data->rotZ[i], 0.0f, 0.0f, 1.0f);
335 guMtxCatF(sp58, sp18, sp18);
336 guScaleF(sp58, data->scaleX[i], data->scaleY[i], 1.0f);
337 guMtxCatF(sp58, sp18, sp18);
339
340 gSPMatrix(gMainGfxPos++, &gDisplayContext->matrixStack[gMatrixListPos++], G_MTX_PUSH | G_MTX_MUL | G_MTX_MODELVIEW);
341 gSPMatrix(gMainGfxPos++, camera->mtxBillboard, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW);
342 gSPDisplayList(gMainGfxPos++, D_09000518_3D2A98);
343 gSPPopMatrix(gMainGfxPos++, G_MTX_MODELVIEW);
344 }
345 }
346
347 gSPPopMatrix(gMainGfxPos++, G_MTX_MODELVIEW);
348}
Mtx matrixStack[0x200]
#define guMtxF2L
#define guScaleF
#define VIRTUAL_TO_PHYSICAL(addr)
Definition macros.h:47
Mtx * mtxBillboard
Gfx D_09000518_3D2A98[]
Gfx D_09000400_3D2980[]
Camera gCameras[4]
Definition cam_main.c:17
Gfx * gMainGfxPos
Definition cam_main.c:15
u16 gMatrixListPos
Definition main_loop.c:45
s32 gCurrentCameraID
Definition cam_math.c:4
DisplayContext * gDisplayContext
Definition cam_main.c:16

Referenced by tubba_heart_attack_render().

◆ tubba_heart_attack_main()

EffectInstance * tubba_heart_attack_main ( s32 type,
f32 arg1,
f32 arg2,
f32 arg3,
f32 arg4,
s32 duration )

Definition at line 56 of file tubba_heart_attack.c.

63 {
65 EffectInstance* effect;
67 s32 numParts = 1;
68 s32 i;
69
73 bp.unk_00 = 0;
74 bp.renderUI = NULL;
75 bp.effectID = EFFECT_TUBBA_HEART_ATTACK;
76
77 effect = create_effect_instance(&bp);
78 effect->numParts = numParts;
79 data = effect->data.tubbaHeartAttack = general_heap_malloc(numParts * sizeof(*data));
80 ASSERT(effect->data.tubbaHeartAttack != NULL);
81
82 data->type = type;
83 data->lifetime = 0;
84 if (duration <= 0) {
85 data->timeLeft = 1000;
86 } else {
87 data->timeLeft = duration;
88 }
89 data->primA = 255;
90 data->centerX = arg1;
91 data->centerY = arg2;
92 data->centerZ = arg3;
93 data->overallScale = arg4;
94 data->primR = 70;
95 data->primG = 180;
96 data->primB = 120;
97
98 for (i = 0; i < TUBBA_MINI_HEART_COUNT; i++) {
99 f32 sin = sin_deg(i * 1080 / TUBBA_MINI_HEART_COUNT);
100 f32 cos = cos_deg(i * 1080 / TUBBA_MINI_HEART_COUNT);
101
102 data->rotZ[i] = rand_int(359) - 180;
103 data->finalX[i] = sin * 15.0f;
104 data->finalY[i] = HeartOffsetY[i] + 10;
105 data->finalZ[i] = cos * 15.0f;
106 data->initialX[i] = sin * 120.0f;
107 data->initialY[i] = HeartOffsetY[i] * 8 + 40;
108 data->initialZ[i] = cos * 120.0f;
109 data->appearDelay[i] = i * 2 + 1;
110 data->shrinkVelY[i] = 0;
111 data->state[i] = HEART_STATE_INIT;
112 data->stateTime[i] = 0;
113 data->rotXY[i] = 0;
114 }
115
116 return effect;
117}
#define general_heap_malloc
#define rand_int
#define create_effect_instance
#define ASSERT(condition)
void(* renderUI)(EffectInstance *effectInst)
Definition effects.h:2655
void(* init)(EffectInstance *effectInst)
Definition effects.h:2652
void(* update)(EffectInstance *effectInst)
Definition effects.h:2653
void(* renderWorld)(EffectInstance *effectInst)
Definition effects.h:2654
void tubba_heart_attack_update(EffectInstance *effect)
void tubba_heart_attack_init(EffectInstance *effect)
void tubba_heart_attack_render(EffectInstance *effect)

◆ EFFECT_DEF_FLOATING_CLOUD_PUFF()

EFFECT_DEF_FLOATING_CLOUD_PUFF ( floating_cloud_puff_main )

◆ func_E00CC9C8()

void func_E00CC9C8 ( void )

Definition at line 303 of file tubba_heart_attack.c.

303 {
304}

Variable Documentation

◆ D_09000400_3D2980

Gfx D_09000400_3D2980[]
extern

◆ D_09000518_3D2A98

Gfx D_09000518_3D2A98[]
extern

◆ AnimScalePct

u8 AnimScalePct[] = { 94, 92, 100, 105, 107, 105, 100 }

Definition at line 19 of file tubba_heart_attack.c.

19{ 94, 92, 100, 105, 107, 105, 100 };

Referenced by tubba_heart_attack_update().

◆ AppearScalePct

u8 AppearScalePct[] = { 20, 40, 58, 73, 85, 92, 97, 100 }

Definition at line 21 of file tubba_heart_attack.c.

21{ 20, 40, 58, 73, 85, 92, 97, 100 };

Referenced by tubba_heart_attack_update().

◆ SwarmInterpPct

u8 SwarmInterpPct[]
Initial value:
= {
0, 2, 5, 9, 14, 20, 27, 35, 44, 54,
64, 74, 84, 94, 100
}

Definition at line 23 of file tubba_heart_attack.c.

23 {
24 0, 2, 5, 9, 14, 20, 27, 35, 44, 54,
25 64, 74, 84, 94, 100
26};

Referenced by tubba_heart_attack_update().

◆ MissInterpPct

u8 MissInterpPct[]
Initial value:
= {
0, 10, 20, 30, 40, 50, 60, 70, 80, 90,
100, 109, 117, 124, 130, 135, 139, 142, 144, 145
}

Definition at line 28 of file tubba_heart_attack.c.

28 {
29 0, 10, 20, 30, 40, 50, 60, 70, 80, 90,
30 100, 109, 117, 124, 130, 135, 139, 142, 144, 145
31};

Referenced by tubba_heart_attack_update().

◆ SqueezeInterpPct

u8 SqueezeInterpPct[]
Initial value:
= {
100, 100, 100, 100, 100, 100, 100, 100, 101, 102,
102, 103, 103, 104, 104, 104, 107, 107, 110, 110,
118, 118, 126, 126, 134, 142, 145, 145, 145, 142,
134, 126, 126, 118, 118, 110, 110, 105, 105, 105,
102, 103, 103, 104, 104, 104, 107, 107, 110, 110,
118, 118, 126, 126, 134, 142, 145, 145, 145, 142,
134, 126, 126, 118, 118, 110, 110, 105, 105, 105
}

Definition at line 33 of file tubba_heart_attack.c.

33 {
34 100, 100, 100, 100, 100, 100, 100, 100, 101, 102,
35 102, 103, 103, 104, 104, 104, 107, 107, 110, 110,
36 118, 118, 126, 126, 134, 142, 145, 145, 145, 142,
37 134, 126, 126, 118, 118, 110, 110, 105, 105, 105,
38 102, 103, 103, 104, 104, 104, 107, 107, 110, 110,
39 118, 118, 126, 126, 134, 142, 145, 145, 145, 142,
40 134, 126, 126, 118, 118, 110, 110, 105, 105, 105
41};

Referenced by tubba_heart_attack_update().

◆ HeartOffsetY

s8 HeartOffsetY[TUBBA_MINI_HEART_COUNT]
Initial value:
= {
-5, -5, -5, -4, -4,
-4, -3, -3, -2, -2,
-1, -1, 0, 0, 1,
2, 2, 3, 3, 4,
4, 4, 5, 5, 5,
}

Definition at line 43 of file tubba_heart_attack.c.

43 {
44 -5, -5, -5, -4, -4,
45 -4, -3, -3, -2, -2,
46 -1, -1, 0, 0, 1,
47 2, 2, 3, 3, 4,
48 4, 4, 5, 5, 5,
49};

Referenced by tubba_heart_attack_main(), and tubba_heart_attack_update().