Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
effect_65.c
Go to the documentation of this file.
1#include "common.h"
2#include "effects_internal.h"
3
4#define MAX_POINTS 30
5#define VTX_BUF_SIZE 2 * MAX_POINTS * sizeof(Vtx) / sizeof(Gfx)
6
10void effect_65_appendGfx(void* effect);
11
12extern Gfx D_09000400_3D15E0[];
13
15
17 s32 variation,
18 f32 posX,
19 f32 posY,
20 f32 posZ,
21 f32 scale,
22 s32 duration
23) {
25 EffectInstance* effect;
26 Effect65FXData* data;
27 s32 numParts = 1;
28 s32 i;
29
33 bp.unk_00 = 0;
34 bp.renderUI = NULL;
35 bp.effectID = EFFECT_65;
36
37 effect = create_effect_instance(&bp);
38 effect->numParts = numParts;
39 data = effect->data.unk_65 = general_heap_malloc(numParts * sizeof(*data));
40 ASSERT(effect->data.unk_65 != NULL);
41
42 data->variation = variation;
43 data->lifeTime = 0;
44 if (duration <= 0) {
45 data->timeLeft = 1000;
46 } else {
47 data->timeLeft = duration;
48 }
49 data->unk_04 = posX;
50 data->unk_08 = posY;
51 data->unk_0C = posZ;
52 data->scale = scale;
53
54 switch (variation) {
55 case 0:
56 data->primR = 255;
57 data->primG = 255;
58 data->primB = 255;
59 data->envR = 225;
60 data->envG = 225;
61 data->envB = 225;
62 data->alpha = 255;
63 break;
64 case 1:
65 data->primR = 255;
66 data->primG = 245;
67 data->primB = 230;
68 data->envR = 45;
69 data->envG = 35;
70 data->envB = 15;
71 data->alpha = 255;
72 break;
73 case 2:
74 data->primR = 255;
75 data->primG = 0;
76 data->primB = 0;
77 data->envR = 155;
78 data->envG = 125;
79 data->envB = 125;
80 data->alpha = 255;
81 break;
82 case 3:
83 data->primR = 255;
84 data->primG = 255;
85 data->primB = 255;
86 data->envR = 255;
87 data->envG = 65;
88 data->envB = 20;
89 data->alpha = 255;
90 break;
91 }
92
93 data->pos.x = posX;
94 data->pos.y = posY;
95 data->pos.z = posZ;
96
97 for (i = 0; i < MAX_POINTS; i++) {
98 data->pathPointEnabled[i] = FALSE;
99 }
100
101 data->lastPointIndex = 0;
102 data->pathX[0] = posX;
103 data->pathY[0] = posY;
104 data->pathZ[0] = posZ;
105 data->pathPointEnabled[0] = TRUE;
106 data->pathTimestamp[0] = 0;
107 data->pathLength[0] = 0;
108 data->pathJitterX = rand_int(30) + 10;
109 data->pathJitterY = 0;
110 data->pathJitterZ = 0;
111
112 return effect;
113}
114
116}
117
119 Effect65FXData* data = effect->data.unk_65;
120 s32 variation = data->variation;
121 s32 lifeTime;
122 f32 pathLength;
123 f32 posX;
124 f32 posY;
125 f32 posZ;
126 f32 lastPointX;
127 f32 lastPointY;
128 f32 lastPointZ;
129 f32 dist;
130 s32 idx;
131
132 if (effect->flags & FX_INSTANCE_FLAG_DISMISS) {
133 effect->flags &= ~FX_INSTANCE_FLAG_DISMISS;
134 data->timeLeft = 16;
135 }
136
137 if (data->timeLeft < 1000) {
138 data->timeLeft--;
139 }
140
141 data->lifeTime++;
142 if (data->timeLeft < 0) {
143 remove_effect(effect);
144 return;
145 }
146
147 lifeTime = data->lifeTime;
148
149 if (data->timeLeft < 16) {
150 data->alpha = data->timeLeft * 16;
151 }
152
153 if (variation == 3) {
154 data->pathJitterX += rand_int(10) - 5;
155 data->pathJitterY += rand_int(10) - 5;
156 data->pos.x += data->pathJitterX;
157 data->pos.y += data->pathJitterY;
158 data->pos.z += data->pathJitterZ;
159 }
160
161 idx = data->lastPointIndex % MAX_POINTS;
162
163 posX = data->pos.x;
164 posY = data->pos.y;
165 posZ = data->pos.z;
166
167 lastPointX = data->pathX[idx];
168 lastPointY = data->pathY[idx];
169 lastPointZ = data->pathZ[idx];
170
171 if (posX != lastPointX || posY != lastPointY || posZ != lastPointZ) {
172 // add new point to the trajectory
173 pathLength = data->pathLength[idx];
174
175 data->lastPointIndex++;
176 if (data->lastPointIndex >= MAX_POINTS) {
177 data->lastPointIndex = 0;
178 }
179
180 idx = data->lastPointIndex;
181
182 data->pathPointEnabled[idx] = TRUE;
183 data->pathX[idx] = posX;
184 data->pathY[idx] = posY;
185 data->pathZ[idx] = posZ;
186 data->pathTimestamp[idx] = lifeTime;
187
188 dist = SQ(posX - lastPointX) + SQ(posY - lastPointY) + SQ(posZ - lastPointZ);
189 if (dist != 0.0f) {
190 dist = sqrtf(dist);
191 }
192
193 data->pathLength[idx] = pathLength + dist;
194 }
195}
196
198 RenderTask renderTask;
199 RenderTask* retTask;
200
201 renderTask.appendGfx = effect_65_appendGfx;
202 renderTask.appendGfxArg = effect;
203 renderTask.dist = 10;
205
206 retTask = queue_render_task(&renderTask);
208}
209
210void effect_65_appendGfx(void* effect) {
211 Effect65FXData* data = ((EffectInstance*)effect)->data.unk_65;
212 Matrix4f mtx;
213 s32 lifeTime;
214 s32 variation;
215 f32 scale;
216 Vtx_t* vtxBuffer;
217 Vtx_t* vtx;
218 s32 firstPointIdx;
219 s32 baseTexOffset;
220 s32 phase;
221 f32 deltaY;
222 f32 deltaX;
223
224 f32 width;
225 f32 pathPointX;
226 f32 pathPointY;
227 f32 pathPointZ;
228 f32 deltaAngle;
229 f32 prevAngle;
230 f32 nextAngle;
231 f32 angle;
232 s32 primAlpha;
233 s32 texOffsetX;
234 s32 numPoints;
235 s32 pathPointLifetime;
236 s32 r, g, b, a;
237 f32 deltaZ;
238
239 s32 idx;
240 s32 next;
241 s32 prev;
242 s32 i;
243 s32 fadeOutPhase;
244
245 lifeTime = data->lifeTime;
246 primAlpha = data->alpha;
247 variation = data->variation;
248 scale = data->scale;
249
250 gDPPipeSync(gMainGfxPos++);
251 gSPSegment(gMainGfxPos++, 0x09, VIRTUAL_TO_PHYSICAL(((EffectInstance*)effect)->graphics->data));
252
253 guTranslateF(mtx, 0.0f, 0.0f, 0.0f);
255
256 gSPMatrix(gMainGfxPos++, &gDisplayContext->matrixStack[gMatrixListPos++], G_MTX_PUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
257 gSPDisplayList(gMainGfxPos++, D_E00CACB0[variation]);
258
259 if (variation >= 2) {
260 gDPSetCombineMode(gMainGfxPos++, PM_CC_4E, PM_CC_4F);
261 }
262
263 gDPSetPrimColor(gMainGfxPos++, 0, 0, data->primR, data->primG, data->primB, primAlpha);
264 gDPSetEnvColor(gMainGfxPos++, data->envR, data->envG, data->envB, 0);
265 gSPBranchList(gMainGfxPos, gMainGfxPos + 1 + VTX_BUF_SIZE);
266 gMainGfxPos++;
267
268 // reserve space in the display list for the vertices
269 vtxBuffer = (Vtx_t*)gMainGfxPos;
271
272 firstPointIdx = -1;
273 baseTexOffset = (lifeTime & 0x3F) << 5;
274
275 numPoints = 0;
276 for (i = 0; i < MAX_POINTS; i++) {
277 s32 a1 = i + 1;
278 s32 idx = (data->lastPointIndex + a1) % MAX_POINTS;
279 if (data->pathPointEnabled[idx]) {
280 numPoints++;
281 }
282 }
283
284 numPoints--;
285 if (numPoints > 0) {
286 phase = 0;
287 for (i = 0; i < MAX_POINTS; i++) {
288 s32 a1 = i + 1;
289 vtx = &vtxBuffer[i * 2];
290 fadeOutPhase = phase / numPoints;
291 idx = (data->lastPointIndex + a1) % MAX_POINTS;
292
293 a = sin_deg(fadeOutPhase) * 255.0f;
294 if (a > 200) {
295 a = 200;
296 }
297
298 if (!data->pathPointEnabled[idx]) {
299 continue;
300 }
301
302 if (firstPointIdx == -1) {
303 next = idx + 1;
304 if (next >= MAX_POINTS) {
305 next = 0;
306 }
307 firstPointIdx = i;
308 angle = -atan2(data->pathY[next], -data->pathX[next], data->pathY[idx], -data->pathX[idx]);
309 } else {
310 if (i != MAX_POINTS - 1) {
311 next = idx + 1;
312 prev = idx - 1;
313 if (next >= MAX_POINTS) {
314 next = 0;
315 }
316 if (prev < 0) {
317 prev = MAX_POINTS - 1;
318 }
319 nextAngle = -atan2(data->pathY[next], -data->pathX[next], data->pathY[idx], -data->pathX[idx]);
320 prevAngle = -atan2(data->pathY[idx], -data->pathX[idx], data->pathY[prev], -data->pathX[prev]);
321 deltaAngle = prevAngle - nextAngle;
322 if (deltaAngle > 180.0f) {
323 nextAngle += 360.0f;
324 } else if (deltaAngle < -180.0f) {
325 prevAngle += 360.0f;
326 }
327 angle = nextAngle + prevAngle;
328 angle *= 0.5;
329 }
330 }
331 pathPointX = data->pathX[idx];
332 pathPointY = data->pathY[idx];
333 pathPointZ = data->pathZ[idx];
334 pathPointLifetime = lifeTime - data->pathTimestamp[idx];
335 width = sin_deg((lifeTime - data->pathTimestamp[idx] * 80) * 4) * 3.0f + 16.0f + pathPointLifetime;
336
337 width *= scale;
338 if (variation >= 0) {
339 texOffsetX = (data->pathLength[idx] * 24.0f) + baseTexOffset;
340 } else {
341 texOffsetX = (data->pathLength[idx] * 24.0f) + baseTexOffset;
342 }
343
344 r = 255;
345 g = 255;
346 b = 255 - pathPointLifetime * 100;
347 if (b < 0) {
348 g = (f32) b * 0.8 + 255.0;
349 b = 0;
350 if (g < 0) {
351 r = (f32) g * 0.4 + 255.0;
352 g = 0;
353 if (r < 0) {
354 r = 0;
355 }
356 }
357 }
358
359 deltaX = width * sin_deg(angle);
360 deltaY = width * cos_deg(angle);
361 deltaZ = 0.0f;
362
363 vtx->ob[0] = pathPointX + deltaX;
364 vtx->ob[1] = pathPointY + deltaY;
365 vtx->ob[2] = pathPointZ + deltaZ;
366 vtx->tc[0] = texOffsetX;
367 vtx->tc[1] = 0x400;
368 vtx->cn[0] = r;
369 vtx->cn[1] = g;
370 vtx->cn[2] = b;
371 vtx->cn[3] = a;
372 vtx++;
373
374 vtx->ob[0] = pathPointX - deltaX;
375 vtx->ob[1] = pathPointY - deltaY;
376 vtx->ob[2] = pathPointZ + deltaZ;
377 vtx->tc[0] = texOffsetX;
378 vtx->tc[1] = 0;
379 vtx->cn[0] = r;
380 vtx->cn[1] = g;
381 vtx->cn[2] = b;
382 vtx->cn[3] = a;
383 vtx++;
384
385 phase += 180;
386 }
387
388 // gSPBranchList jumps to here (after the vertex array)
389 for (i = firstPointIdx; i < MAX_POINTS - 1; i++) {
390 gSPVertex(gMainGfxPos++, &vtxBuffer[i * 2], 4, 0);
391 gSP2Triangles(gMainGfxPos++, 0, 2, 1, 0, 1, 2, 3, 0);
392 }
393 }
394
395 gSPPopMatrix(gMainGfxPos++, G_MTX_MODELVIEW);
396}
Mtx matrixStack[0x200]
f32 Matrix4f[4][4]
void effect_65_update(EffectInstance *effect)
Definition effect_65.c:118
void effect_65_render(EffectInstance *effect)
Definition effect_65.c:197
void effect_65_appendGfx(void *effect)
Definition effect_65.c:210
#define VTX_BUF_SIZE
Definition effect_65.c:5
#define MAX_POINTS
Definition effect_65.c:4
Gfx D_09000400_3D15E0[]
void effect_65_init(EffectInstance *effect)
Definition effect_65.c:115
Gfx * D_E00CACB0[]
Definition effect_65.c:14
EffectInstance * effect_65_main(s32 variation, f32 posX, f32 posY, f32 posZ, f32 scale, s32 duration)
Definition effect_65.c:16
#define general_heap_malloc
#define queue_render_task
#define sqrtf
#define guMtxF2L
#define sin_deg
#define guTranslateF
#define remove_effect
#define rand_int
#define cos_deg
#define atan2
#define create_effect_instance
f32 pathY[30]
Definition effects.h:1789
struct Effect65FXData * unk_65
Definition effects.h:2565
f32 pathX[30]
Definition effects.h:1788
s32 pathTimestamp[30]
Definition effects.h:1791
f32 pathLength[30]
Definition effects.h:1794
s32 pathPointEnabled[30]
Definition effects.h:1792
f32 pathZ[30]
Definition effects.h:1790
EffectData data
Definition effects.h:2605
#define ASSERT(condition)
@ FX_INSTANCE_FLAG_DISMISS
Definition enums.h:3517
@ RENDER_TASK_FLAG_REFLECT_FLOOR
Definition enums.h:3318
@ RENDER_MODE_CLOUD_NO_ZCMP
Definition enums.h:3311
#define PM_CC_4F
Definition macros.h:485
#define PM_CC_4E
Definition macros.h:484
#define SQ(x)
Definition macros.h:166
#define VIRTUAL_TO_PHYSICAL(addr)
Definition macros.h:47
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 * appendGfxArg
void(* appendGfx)(void *)
Gfx * gMainGfxPos
Definition cam_main.c:15
u16 gMatrixListPos
Definition main_loop.c:45
DisplayContext * gDisplayContext
Definition cam_main.c:16