Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <ultra64.h>
- #include "sm64.h"
- #include "display.h"
- #include "memory.h"
- #include "ingame_menu.h"
- #include "envfx_snow.h"
- #include "envfx_bubbles.h"
- #include "engine/surface_collision.h"
- #include "engine/math_util.h"
- #include "engine/behavior_script.h"
- #include "audio/interface_2.h"
- #include "obj_behaviors.h"
- /** This file implements environment effects that are not snow:
- * Flowers (unused), lava bubbles and jetsream/whirlpool bubbles.
- * Refer to 'envfx_snow.c' for more info about environment effects.
- * Note that the term 'bubbles' is used as a collective name for
- * effects in this file even though flowers aren't bubbles. For the
- * sake of concise naming, flowers fall under bubbles.
- */
- s16 gEnvFxBubbleConfig[10];
- static Gfx *sGfxCursor; // points to end of display list for bubble particles
- static s32 sBubbleParticleCount;
- static s32 sBubbleParticleMaxCount;
- UNUSED s32 D_80330690 = 0;
- UNUSED s32 D_80330694 = 0;
- /// Template for a bubble particle triangle
- Vtx_t gBubbleTempVtx[3] =
- {
- {
- {0, 0, 0},
- 0,
- {1544, 964},
- {0xFF, 0xFF, 0xFF, 0xFF}
- },
- {
- {0, 0, 0},
- 0,
- {522, -568},
- {0xFF, 0xFF, 0xFF, 0xFF}
- },
- {
- {0, 0, 0},
- 0,
- {-498, 964},
- {0xFF, 0xFF, 0xFF, 0xFF}
- },
- };
- extern void *flower_bubbles_textures_ptr_0B002008;
- extern void *lava_bubble_ptr_0B006020;
- extern void *bubble_ptr_0B006848;
- extern void *tiny_bubble_dl_0B006AB0;
- extern void *tiny_bubble_dl_0B006D38;
- extern void *tiny_bubble_dl_0B006D68;
- /** Check whether the particle with the given index is
- * laterally within distance of point (x, z). Used to
- * kill flower and bubble particles.
- */
- s32 particle_is_laterally_close(s32 index, s32 x, s32 z, s32 distance) {
- s32 xPos = (gEnvFxBuffer + index)->xPos;
- s32 zPos = (gEnvFxBuffer + index)->zPos;
- if (sqr(xPos - x) + sqr(zPos - z) > sqr(distance))
- return 0;
- return 1;
- }
- /** Generate a uniform random number in range [-2000, -1000[ or [1000, 2000[
- * Used to position flower particles
- */
- s32 random_flower_offset() {
- s32 result = RandomFloat() * 2000.0f - 1000.0f;
- if (result < 0 )
- result -= 1000;
- else
- result += 1000;
- return result;
- }
- /** Update flower particles. Flowers are scattered randomly in front of the
- * camera, and can land on any ground
- */
- void envfx_update_flower(Vec3s centerPos) {
- s32 i;
- f32 *floorPlane; // Unused, but contains normal and offset of floor triangle
- s32 timer = gGlobalTimer;
- s16 centerX = centerPos[0];
- UNUSED s16 centerY = centerPos[1];
- s16 centerZ = centerPos[2];
- for (i = 0; i < sBubbleParticleMaxCount; i++) {
- (gEnvFxBuffer + i)->isAlive = particle_is_laterally_close(i, centerX, centerZ, 3000);
- if ((gEnvFxBuffer + i)->isAlive == 0) {
- (gEnvFxBuffer + i)->xPos = random_flower_offset() + centerX;
- (gEnvFxBuffer + i)->zPos = random_flower_offset() + centerZ;
- (gEnvFxBuffer + i)->yPos = func_803814B8((gEnvFxBuffer + i)->xPos, 10000.0f, (gEnvFxBuffer + i)->zPos, &floorPlane);
- (gEnvFxBuffer + i)->isAlive = 1;
- (gEnvFxBuffer + i)->animFrame = RandomFloat() * 5.0f;
- } else if ((timer & 0x03) == 0) {
- (gEnvFxBuffer + i)->animFrame += 1;
- if ((gEnvFxBuffer + i)->animFrame > 5)
- (gEnvFxBuffer + i)->animFrame = 0;
- }
- }
- }
- /** Update the position of a lava bubble to be somewhere around centerPos
- * Uses find_floor to find the height of lava, if no floor or a non-lava
- * floor is found the bubble y is set to -10000, which is why you can see
- * occasional lava bubbles far below the course in Lethal Lava Land.
- * In the second Bowser fight arena, the visual lava is above the lava
- * floor so lava-bubbles are not normally visible, only if you bring the
- * camera below the lava plane.
- */
- void envfx_set_lava_bubble_position(s32 index, Vec3s centerPos) {
- struct Surface *surface;
- s16 floorY;
- s16 centerX, centerY, centerZ;
- centerX = centerPos[0];
- centerY = centerPos[1];
- centerZ = centerPos[2];
- (gEnvFxBuffer + index)->xPos = RandomFloat() * 6000.0f - 3000.0f + centerX;
- (gEnvFxBuffer + index)->zPos = RandomFloat() * 6000.0f - 3000.0f + centerZ;
- if ((gEnvFxBuffer + index)->xPos > 8000)
- (gEnvFxBuffer + index)->xPos = 16000 - (gEnvFxBuffer + index)->xPos;
- if ((gEnvFxBuffer + index)->xPos < -8000)
- (gEnvFxBuffer + index)->xPos = -16000 - (gEnvFxBuffer + index)->xPos;
- if ((gEnvFxBuffer + index)->zPos > 8000)
- (gEnvFxBuffer + index)->zPos = 16000 - (gEnvFxBuffer + index)->zPos;
- if ((gEnvFxBuffer + index)->zPos < -8000)
- (gEnvFxBuffer + index)->zPos = -16000 - (gEnvFxBuffer + index)->zPos;
- floorY = find_floor((gEnvFxBuffer + index)->xPos, centerY + 500, (gEnvFxBuffer + index)->zPos, &surface);
- if (surface == NULL) {
- (gEnvFxBuffer + index)->yPos = -10000;
- return;
- }
- if (surface->type == SURFACE_LAVA) {
- (gEnvFxBuffer + index)->yPos = floorY;
- }
- else {
- (gEnvFxBuffer + index)->yPos = -10000;
- }
- }
- /** Update lava bubble animation and give the bubble a new position if the
- * animation is over.
- */
- void envfx_update_lava(Vec3s centerPos) {
- s32 i;
- s32 timer = gGlobalTimer;
- s8 chance;
- UNUSED s16 centerX, centerY, centerZ;
- centerX = centerPos[0];
- centerY = centerPos[1];
- centerZ = centerPos[2];
- for (i = 0; i < sBubbleParticleMaxCount; i++) {
- if ((gEnvFxBuffer + i)->isAlive == 0) {
- envfx_set_lava_bubble_position(i, centerPos);
- (gEnvFxBuffer + i)->isAlive = 1;
- }
- else if ((timer & 0x01) == 0) {
- (gEnvFxBuffer + i)->animFrame += 1;
- if ((gEnvFxBuffer + i)->animFrame > 8) {
- (gEnvFxBuffer + i)->isAlive = 0;
- (gEnvFxBuffer + i)->animFrame = 0;
- }
- }
- }
- if ((chance = (s32)(RandomFloat() * 16.0f)) == 8)
- SetSound(0x300D0081, D_803320E0);
- }
- /** Rotate the input x, y and z around the rotation origin of the whirlpool
- * according to the pitch and yaw of the whirlpool.
- */
- void envfx_rotate_around_whirlpool(s32 *x, s32 *y, s32 *z) {
- s32 vecX = *x - gEnvFxBubbleConfig[ENVFX_STATE_DEST_X];
- s32 vecY = *y - gEnvFxBubbleConfig[ENVFX_STATE_DEST_Y];
- s32 vecZ = *z - gEnvFxBubbleConfig[ENVFX_STATE_DEST_Z];
- f32 cosPitch = coss(gEnvFxBubbleConfig[ENVFX_STATE_PITCH]);
- f32 sinPitch = sins(gEnvFxBubbleConfig[ENVFX_STATE_PITCH]);
- f32 cosMYaw = coss(-gEnvFxBubbleConfig[ENVFX_STATE_YAW]);
- f32 sinMYaw = sins(-gEnvFxBubbleConfig[ENVFX_STATE_YAW]);
- f32 rotatedX = vecX * cosMYaw - sinMYaw * cosPitch * vecY - sinPitch * sinMYaw * vecZ;
- f32 rotatedY = vecX * sinMYaw + cosPitch * cosMYaw * vecY - sinPitch * cosMYaw * vecZ;
- f32 rotatedZ = vecY * sinPitch + cosPitch * vecZ;
- *x = gEnvFxBubbleConfig[ENVFX_STATE_DEST_X] + (s32)rotatedX;
- *y = gEnvFxBubbleConfig[ENVFX_STATE_DEST_Y] + (s32)rotatedY;
- *z = gEnvFxBubbleConfig[ENVFX_STATE_DEST_Z] + (s32)rotatedZ;
- }
- /** Check whether a whirlpool bubble is alive. A bubble respawns when it is too
- * low or close to the center.
- */
- s32 envfx_is_whirlpool_bubble_alive(s32 index) {
- s32 UNUSED sp4;
- if ((gEnvFxBuffer + index)->bubbleY < gEnvFxBubbleConfig[ENVFX_STATE_DEST_Y] - 100)
- return 0;
- if ((gEnvFxBuffer + index)->angleAndDist[1] < 10)
- return 0;
- return 1;
- }
- /** Update whirlpool particles. Whirlpool particles start high and far from
- * the center and get sucked into the sink in a spiraling motion.
- */
- void envfx_update_whirlpool(void) {
- s32 i;
- for (i = 0; i < sBubbleParticleMaxCount; i++) {
- (gEnvFxBuffer + i)->isAlive = envfx_is_whirlpool_bubble_alive(i);
- if ((gEnvFxBuffer + i)->isAlive == 0) {
- (gEnvFxBuffer + i)->angleAndDist[1] = RandomFloat() * 1000.0f;
- (gEnvFxBuffer + i)->angleAndDist[0] = RandomFloat() * 65536.0f;
- (gEnvFxBuffer + i)->xPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_X] + sins((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1];
- (gEnvFxBuffer + i)->zPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_Z] + coss((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1];
- (gEnvFxBuffer + i)->bubbleY = gEnvFxBubbleConfig[ENVFX_STATE_SRC_Y] + (RandomFloat() * 100.0f - 50.0f);
- (gEnvFxBuffer + i)->yPos = (i + gEnvFxBuffer)->bubbleY;
- (gEnvFxBuffer + i)->unusedBubbleVar = 0;
- (gEnvFxBuffer + i)->isAlive = 1;
- envfx_rotate_around_whirlpool(&(gEnvFxBuffer + i)->xPos, &(gEnvFxBuffer + i)->yPos, &(gEnvFxBuffer + i)->zPos);
- }
- else {
- (gEnvFxBuffer + i)->angleAndDist[1] -= 40;
- (gEnvFxBuffer + i)->angleAndDist[0] += (s16) (3000 - (gEnvFxBuffer + i)->angleAndDist[1] * 2) + 0x400;
- (gEnvFxBuffer + i)->xPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_X] + sins((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1];
- (gEnvFxBuffer + i)->zPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_Z] + coss((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1];
- (gEnvFxBuffer + i)->bubbleY -= -((s16)(gEnvFxBuffer + i)->angleAndDist[1] / 100) + 40;
- (gEnvFxBuffer + i)->yPos = (i + gEnvFxBuffer)->bubbleY;
- envfx_rotate_around_whirlpool(&(gEnvFxBuffer + i)->xPos, &(gEnvFxBuffer + i)->yPos, &(gEnvFxBuffer + i)->zPos);
- }
- }
- }
- /** Check whether a jetstream bubble should respawn. Happens if it is laterally
- * 1000 units away from the source or 1500 units above it.
- */
- s32 envfx_is_jestream_bubble_alive(s32 index) {
- UNUSED s32 unk;
- if (!particle_is_laterally_close(index, gEnvFxBubbleConfig[ENVFX_STATE_SRC_X], gEnvFxBubbleConfig[ENVFX_STATE_SRC_Z], 1000)
- || gEnvFxBubbleConfig[ENVFX_STATE_SRC_Y] + 1500 < (gEnvFxBuffer + index)->yPos)
- return 0;
- return 1;
- }
- /** Update the positions of jestream bubble particles.
- * They move up and outwards.
- */
- void envfx_update_jetstream(void) {
- s32 i;
- for (i = 0; i < sBubbleParticleMaxCount; i++) {
- (gEnvFxBuffer + i)->isAlive = envfx_is_jestream_bubble_alive(i);
- if ((gEnvFxBuffer + i)->isAlive == 0) {
- (gEnvFxBuffer + i)->angleAndDist[1] = RandomFloat() * 300.0f;
- (gEnvFxBuffer + i)->angleAndDist[0] = RandomU16();
- (gEnvFxBuffer + i)->xPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_X] + sins((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1];
- (gEnvFxBuffer + i)->zPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_Z] + coss((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1];
- (gEnvFxBuffer + i)->yPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_Y] + (RandomFloat() * 400.0f - 200.0f);
- }
- else {
- (gEnvFxBuffer + i)->angleAndDist[1] += 10;
- (gEnvFxBuffer + i)->xPos += sins((gEnvFxBuffer + i)->angleAndDist[0]) * 10.0f;
- (gEnvFxBuffer + i)->zPos += coss((gEnvFxBuffer + i)->angleAndDist[0]) * 10.0f;
- (gEnvFxBuffer + i)->yPos -= ((gEnvFxBuffer + i)->angleAndDist[1] / 30) - 50;
- }
- }
- }
- /** Initialize bubble (or flower) effect by allocating a buffer to store
- * the state of each particle and setting the initial and max count.
- * Analogous to init_snow_particles, but for bubbles.
- */
- s32 envfx_init_bubble(s32 mode) {
- s32 i;
- switch (mode) {
- case ENVFX_MODE_NONE:
- return 0;
- case ENVFX_FLOWERS:
- sBubbleParticleCount = 30;
- sBubbleParticleMaxCount = 30;
- break;
- case ENVFX_LAVA_BUBBLES:
- sBubbleParticleCount = 15;
- sBubbleParticleMaxCount = 15;
- break;
- case ENVFX_WHIRLPOOL_BUBBLES:
- sBubbleParticleCount = 60;
- break;
- case ENVFX_JETSTREAM_BUBBLES:
- sBubbleParticleCount = 60;
- break;
- }
- gEnvFxBuffer = (struct EnvFxParticle *)mem_pool_alloc(D_8033A124, sBubbleParticleCount * sizeof(struct EnvFxParticle));
- if (!gEnvFxBuffer)
- return 0;
- bzero(gEnvFxBuffer, sBubbleParticleCount * sizeof(struct EnvFxParticle));
- bzero(gEnvFxBubbleConfig, sizeof(gEnvFxBubbleConfig));
- if (mode == ENVFX_LAVA_BUBBLES) {
- //! Dead code
- if (0) { }
- for (i = 0; i < sBubbleParticleCount; i++) {
- (gEnvFxBuffer + i)->animFrame = RandomFloat() * 7.0f;
- }
- if (0) { }
- }
- gEnvFxMode = mode;
- return 1;
- }
- /** Update particles depending on mode.
- * Also sets the given vertices to the correct shape for each mode,
- * though they are not being rotated yet.
- */
- void envfx_bubbles_update_switch(s32 mode, Vec3s camTo, Vec3s vertex1, Vec3s vertex2, Vec3s vertex3) {
- switch(mode) {
- case ENVFX_FLOWERS:
- envfx_update_flower(camTo);
- vertex1[0] = 50;
- vertex1[1] = 0;
- vertex1[2] = 0;
- vertex2[0] = 0;
- vertex2[1] = 75;
- vertex2[2] = 0;
- vertex3[0] = -50;
- vertex3[1] = 0;
- vertex3[2] = 0;
- break;
- case ENVFX_LAVA_BUBBLES:
- envfx_update_lava(camTo);
- vertex1[0] = 100;
- vertex1[1] = 0;
- vertex1[2] = 0;
- vertex2[0] = 0;
- vertex2[1] = 150;
- vertex2[2] = 0;
- vertex3[0] = -100;
- vertex3[1] = 0;
- vertex3[2] = 0;
- break;
- case ENVFX_WHIRLPOOL_BUBBLES:
- envfx_update_whirlpool();
- vertex1[0] = 40;
- vertex1[1] = 0;
- vertex1[2] = 0;
- vertex2[0] = 0;
- vertex2[1] = 60;
- vertex2[2] = 0;
- vertex3[0] = -40;
- vertex3[1] = 0;
- vertex3[2] = 0;
- break;
- case ENVFX_JETSTREAM_BUBBLES:
- envfx_update_jetstream();
- vertex1[0] = 40;
- vertex1[1] = 0;
- vertex1[2] = 0;
- vertex2[0] = 0;
- vertex2[1] = 60;
- vertex2[2] = 0;
- vertex3[0] = -40;
- vertex3[1] = 0;
- vertex3[2] = 0;
- break;
- }
- }
- /** Append 15 vertices to 'gfx', which is enough for 5 bubbles starting at
- * 'index'. The 3 input vertices represent the roated triangle around (0,0,0)
- * that will be translated to bubble positions to draw the bubble image
- */
- void append_bubble_vertex_buffer(Gfx *gfx, s32 index, Vec3s vertex1, Vec3s vertex2, Vec3s vertex3, Vtx *template) {
- s32 i = 0;
- Vtx *vertBuf = (Vtx *)alloc_display_list(15 * sizeof(Vtx));
- if (vertBuf == NULL)
- return;
- for (i = 0; i < 15; i += 3) {
- vertBuf[i] = template[0];
- vertBuf[i].v.ob[0] = vertex1[0] + (gEnvFxBuffer + (index + i / 3))->xPos;
- vertBuf[i].v.ob[1] = vertex1[1] + (gEnvFxBuffer + (index + i / 3))->yPos;
- vertBuf[i].v.ob[2] = vertex1[2] + (gEnvFxBuffer + (index + i / 3))->zPos;
- vertBuf[i + 1] = template[1];
- vertBuf[i + 1].v.ob[0] = vertex2[0] + (gEnvFxBuffer + (index + i / 3))->xPos;
- vertBuf[i + 1].v.ob[1] = vertex2[1] + (gEnvFxBuffer + (index + i / 3))->yPos;
- vertBuf[i + 1].v.ob[2] = vertex2[2] + (gEnvFxBuffer + (index + i / 3))->zPos;
- vertBuf[i + 2] = template[2];
- vertBuf[i + 2].v.ob[0] = vertex3[0] + (gEnvFxBuffer + (index + i / 3))->xPos;
- vertBuf[i + 2].v.ob[1] = vertex3[1] + (gEnvFxBuffer + (index + i / 3))->yPos;
- vertBuf[i + 2].v.ob[2] = vertex3[2] + (gEnvFxBuffer + (index + i / 3))->zPos;
- }
- gSPVertex(gfx, VIRTUAL_TO_PHYSICAL(vertBuf), 15, 0);
- }
- /** Appends to the enfvx display list a command setting the appropriate texture
- * for a specific particle. The display list is not passed as parameter but uses
- * the global sGfxCursor instead.
- */
- void envfx_set_bubble_texture(s32 mode, s16 index) {
- void **imageArr;
- s16 frame = (gEnvFxBuffer + index)->animFrame;
- switch(mode) {
- case ENVFX_FLOWERS:
- imageArr = (void **)segmented_to_virtual(&flower_bubbles_textures_ptr_0B002008);
- frame = (gEnvFxBuffer + index)->animFrame;
- break;
- case ENVFX_LAVA_BUBBLES:
- imageArr = (void **)segmented_to_virtual(&lava_bubble_ptr_0B006020);
- frame = (gEnvFxBuffer + index)->animFrame;
- break;
- case ENVFX_WHIRLPOOL_BUBBLES:
- case ENVFX_JETSTREAM_BUBBLES:
- imageArr = (void **)segmented_to_virtual(&bubble_ptr_0B006848);
- frame = 0;
- break;
- }
- gDPSetTextureImage(sGfxCursor++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, *(imageArr + frame));
- gSPDisplayList(sGfxCursor++, &tiny_bubble_dl_0B006D68);
- }
- /** Updates the bubble particle positions, then generates and returns a display
- * list drawing them.
- */
- Gfx *envfx_update_bubble_particles(s32 mode, UNUSED Vec3s marioPos, Vec3s camFrom, Vec3s camTo) {
- s32 i;
- s16 radius, pitch, yaw;
- Vec3s vertex1;
- Vec3s vertex2;
- Vec3s vertex3;
- Gfx *gfxStart;
- gfxStart = (Gfx *)alloc_display_list(((sBubbleParticleMaxCount / 5) * 10 + sBubbleParticleMaxCount + 3) * sizeof(Gfx));
- if (gfxStart == NULL)
- return NULL;
- sGfxCursor = gfxStart;
- orbit_from_positions(camTo, camFrom, &radius, &pitch, &yaw);
- envfx_bubbles_update_switch(mode, camTo, vertex1, vertex2, vertex3);
- rotate_triangle_vertices(vertex1, vertex2, vertex3, pitch, yaw);
- gSPDisplayList(sGfxCursor++, &tiny_bubble_dl_0B006D38);
- for (i = 0; i < sBubbleParticleMaxCount; i += 5) {
- gDPPipeSync(sGfxCursor++);
- envfx_set_bubble_texture(mode, i);
- append_bubble_vertex_buffer(sGfxCursor++, i, vertex1, vertex2, vertex3, (Vtx *)gBubbleTempVtx);
- gSP1Triangle(sGfxCursor++, 0, 1, 2, 0);
- gSP1Triangle(sGfxCursor++, 3, 4, 5, 0);
- gSP1Triangle(sGfxCursor++, 6, 7, 8, 0);
- gSP1Triangle(sGfxCursor++, 9, 10, 11, 0);
- gSP1Triangle(sGfxCursor++, 12, 13, 14, 0);
- }
- gSPDisplayList(sGfxCursor++, &tiny_bubble_dl_0B006AB0);
- gSPEndDisplayList(sGfxCursor++);
- return gfxStart;
- }
- /** Set the maximum particle count from the gEnvFxBubbleConfig variable,
- * which is set by the whirlpool or jetstream behavior.
- */
- void envfx_set_max_bubble_particles(s32 mode) {
- switch (mode) {
- case ENVFX_WHIRLPOOL_BUBBLES:
- sBubbleParticleMaxCount = gEnvFxBubbleConfig[ENVFX_STATE_PARTICLECOUNT];
- break;
- case ENVFX_JETSTREAM_BUBBLES:
- sBubbleParticleMaxCount = gEnvFxBubbleConfig[ENVFX_STATE_PARTICLECOUNT];
- break;
- }
- }
- /** Update bubble-like environment effects. Assumes the mode is larger than 10,
- * lower modes are snow effects which are updated in a different function.
- * Returns a display list drawing the particles.
- */
- Gfx *envfx_update_bubbles(s32 mode, Vec3s marioPos, Vec3s camTo, Vec3s camFrom) {
- Gfx *gfx;
- if (gEnvFxMode == 0 && !envfx_init_bubble(mode))
- return NULL;
- envfx_set_max_bubble_particles(mode);
- if (sBubbleParticleMaxCount == 0)
- return NULL;
- switch (mode) {
- case ENVFX_FLOWERS:
- gfx = envfx_update_bubble_particles(ENVFX_FLOWERS, marioPos, camFrom, camTo);
- break;
- case ENVFX_LAVA_BUBBLES:
- gfx = envfx_update_bubble_particles(ENVFX_LAVA_BUBBLES, marioPos, camFrom, camTo);
- break;
- case ENVFX_WHIRLPOOL_BUBBLES:
- gfx = envfx_update_bubble_particles(ENVFX_WHIRLPOOL_BUBBLES, marioPos, camFrom, camTo);
- break;
- case ENVFX_JETSTREAM_BUBBLES:
- gfx = envfx_update_bubble_particles(ENVFX_JETSTREAM_BUBBLES, marioPos, camFrom, camTo);
- break;
- default:
- return NULL;
- }
- return gfx;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement