static void eEL_InitUnchar(u8* unchar_p, int count, u8 val) { int i; for (i = 0; i < count; i++) { *unchar_p++ = val; } } static void eEL_VectorRoteteY(xyz_t* vec, f32 angle) { xyz_t src = *vec; f32 cos = cosf_table(angle); f32 sin = sinf_table(angle); vec->x = src.x * cos + src.z * sin; vec->z = -src.x * sin + src.z * cos; } static s16 eEL_RandomFirstSpeed(xyz_t* speed, f32 y, f32 max_z, f32 max_x) { xyz_t vec = { 0.0f, 1.0f, 0.0f }; f32 angle = 0.0f; vec.y = y; if (max_z != 0.0f) { f32 rnd_z = RANDOM_F(max_z) - max_z * 0.5f; angle = rnd_z; sMath_RotateZ(&vec, DEG2RAD(rnd_z)); } if (max_x != 0.0f) { f32 rnd_x = RANDOM_F(max_x) - max_x * 0.5f; sMath_RotateX(&vec, DEG2RAD(rnd_x)); } if (speed != NULL) { *speed = vec; } return RAD2SHORT_ANGLE2(DEG2RAD(angle)); } static void eEL_SetContiniousEnv(eEC_Effect_c* effect, s16 unused, s16 timer) { if (effect->state == eEC_STATE_NORMAL) { if (effect->timer <= 1) { effect->state = eEC_STATE_CONTINUOUS; effect->timer = timer; } } else if (effect->state == eEC_STATE_CONTINUOUS) { if (effect->timer <= 1) { effect->state = eEC_STATE_CONTINUOUS; effect->timer = timer; } } } static f32 eEL_CalcAdjust(s16 now, s16 start, s16 end, f32 start_val, f32 end_val) { if (start == end) { return start_val; } if (now <= start) { return start_val; } if (now >= end) { return end_val; } return start_val + (f32)(now - start) * ((end_val - start_val) / (f32)(end - start)); } static void eEL_AutoMatrixXlu(GAME* game, xyz_t* pos, xyz_t* scale) { GAME_PLAY* play = (GAME_PLAY*)game; Mtx* mtx = (Mtx*)GRAPH_ALLOC_TYPE(game->graph, Mtx, 1); f32 adj_scale; OPEN_DISP(game->graph); _texture_z_light_fog_prim_xlu(game->graph); adj_scale = 1.0f + ((f32)(int)GETREG(MYKREG, 27)) * 0.01f; suMtxMakeTS(mtx, scale->x * adj_scale, scale->y * adj_scale, scale->z * adj_scale, pos->x, pos->y, pos->z); gSPMatrix(NEXT_POLY_XLU_DISP, mtx, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPMatrix(NEXT_POLY_XLU_DISP, play->billboard_mtx_p, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW); CLOSE_DISP(game->graph); } static void eEL_AutoMatrixXlu_Offset(GAME* game, xyz_t* pos, xyz_t* scale, xyz_t* offset) { GAME_PLAY* play = (GAME_PLAY*)game; f32 adj_scale; OPEN_DISP(game->graph); _texture_z_light_fog_prim_xlu(game->graph); Matrix_translate(pos->x, pos->y, pos->z, 0); Matrix_mult(&play->billboard_matrix, 1); Matrix_translate(offset->x + (f32)(int)GETREG(MYKREG, 24), offset->y + (f32)(int)GETREG(MYKREG, 25), offset->z + (f32)(int)GETREG(MYKREG, 26), 1); adj_scale = 1.0f + ((f32)(int)GETREG(MYKREG, 27)) * 0.01f; Matrix_scale(scale->x * adj_scale, scale->y * adj_scale, scale->z * adj_scale, 1); gSPMatrix(NEXT_POLY_XLU_DISP, _Matrix_to_Mtx_new(game->graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); CLOSE_DISP(game->graph); } static void eEC_MorphCombine(u8* const result, eEC_morph_data_c* const morph_data, s16 now_timer) { int i; for (i = 0; i < 9; i++) { if (morph_data[i].morph_flag) { result[i] = eEL_CalcAdjust(now_timer, morph_data[i].start_frame << 1, morph_data[i].end_frame << 1, morph_data[i].start_val, morph_data[i].end_val); } else { result[i] = morph_data[i].start_val; } } } static int eEL_SpecialBlockCenterPos(xyz_t* pos, u32 block_kind) { int bx; int bz; *pos = ZeroVec; if (mFI_BlockKind2BkNum(&bx, &bz, block_kind) && mFI_BkNum2WposXZ(&pos->x, &pos->z, bx, bz)) { pos->x += mFI_BK_WORLDSIZE_X_F / 2; pos->z += mFI_BK_WORLDSIZE_Z_F / 2; return TRUE; } else { return FALSE; } } static eEC_light_data_c eEL_light_data; static const eEC_light_data_c eEC_light_default = { 0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, 0, 0, 0 }; static int eEL_EffectLightStatus(rgba_t* color, int* shadow_flag) { color->r = eEC_ctrl_work.light_info.lights.diffuse.color[0]; color->g = eEC_ctrl_work.light_info.lights.diffuse.color[1]; color->b = eEC_ctrl_work.light_info.lights.diffuse.color[2]; color->a = 0; *shadow_flag = eEL_light_data.shadow_flag; return eEL_light_data.light_state; } static void eEL_InitEffectLight(void) { eEL_light_data = eEC_light_default; eEL_light_data.n_frames = 10; } static void eEL_CalcEffectLight_Set(GAME* game) { int r; int g; int b; if (eEL_light_data.ctr > eEL_light_data.n_frames) { eEL_InitEffectLight(); eEC_ctrl_work.light_info.lights.diffuse.color[0] = 0; eEC_ctrl_work.light_info.lights.diffuse.color[1] = 0; eEC_ctrl_work.light_info.lights.diffuse.color[2] = 0; eEL_light_data.light_state = eEC_LIGHT_COLOR_DISABLED; } else { if (eEL_light_data.ctr < eEL_light_data.max_frame) { r = (int)eEC_CLIP->calc_adjust_proc(eEL_light_data.ctr, 0, eEL_light_data.max_frame, eEL_light_data.start_color.r, eEL_light_data.target_color.r); g = (int)eEC_CLIP->calc_adjust_proc(eEL_light_data.ctr, 0, eEL_light_data.max_frame, eEL_light_data.start_color.g, eEL_light_data.target_color.g); b = (int)eEC_CLIP->calc_adjust_proc(eEL_light_data.ctr, 0, eEL_light_data.max_frame, eEL_light_data.start_color.b, eEL_light_data.target_color.b); eEL_light_data.light_state = eEC_LIGHT_COLOR_INCREASING; } else { r = (int)eEC_CLIP->calc_adjust_proc(eEL_light_data.ctr, eEL_light_data.max_frame, eEL_light_data.n_frames, eEL_light_data.target_color.r, 0.0f); g = (int)eEC_CLIP->calc_adjust_proc(eEL_light_data.ctr, eEL_light_data.max_frame, eEL_light_data.n_frames, eEL_light_data.target_color.g, 0.0f); b = (int)eEC_CLIP->calc_adjust_proc(eEL_light_data.ctr, eEL_light_data.max_frame, eEL_light_data.n_frames, eEL_light_data.target_color.b, 0.0f); if (eEL_light_data.ctr == eEL_light_data.max_frame) { eEL_light_data.light_state = eEC_LIGHT_COLOR_MAXIMUM; } else { eEL_light_data.light_state = eEC_LIGHT_COLOR_DECREASING; } } eEC_ctrl_work.light_info.lights.diffuse.color[0] = r; eEC_ctrl_work.light_info.lights.diffuse.color[1] = g; eEC_ctrl_work.light_info.lights.diffuse.color[2] = b; eEL_light_data.ctr++; } } static void eEL_RegistEffectLight(rgba_t color, s16 max_frames, s16 n_frames, int shadow_flag) { eEL_light_data.start_color.r = eEC_ctrl_work.light_info.lights.diffuse.color[0]; eEL_light_data.start_color.g = eEC_ctrl_work.light_info.lights.diffuse.color[1]; eEL_light_data.start_color.b = eEC_ctrl_work.light_info.lights.diffuse.color[2]; eEL_light_data.ctr = 0; eEL_light_data.target_color = color; eEL_light_data.max_frame = max_frames; eEL_light_data.n_frames = n_frames; eEL_light_data.shadow_flag = shadow_flag; } static void eEL_DecideLightPower(rgba_t* result_color, rgba_t base_color, xyz_t pos, GAME* game, f32 max_power, f32 min_power, f32 max_dist) { GAME_PLAY* play = (GAME_PLAY*)game; PLAYER_ACTOR* player = GET_PLAYER_ACTOR(play); if (player != NULL) { xyz_t player_pos = player->actor_class.world.position; f32 dist = search_position_distance(&pos, &player_pos); f32 power; if (dist > max_dist) { power = min_power; } else { power = (max_power - min_power) * (1.0f - dist / max_dist); power += min_power; } result_color->r = (int)(base_color.r * power); result_color->g = (int)(base_color.g * power); result_color->b = (int)(base_color.b * power); result_color->a = 255; } else { *result_color = base_color; } } static int mEL_CheckLookAtBlock(xyz_t pos) { xyz_t* lookat = Camera2_getCenterPos_p(); int effect_bx; int effect_bz; int lookat_bx; int lookat_bz; if (mFI_Wpos2BlockNum(&effect_bx, &effect_bz, pos) && mFI_Wpos2BlockNum(&lookat_bx, &lookat_bz, *lookat)) { if (effect_bx == lookat_bx && effect_bz == lookat_bz) { return TRUE; } } return FALSE; }