#include "ac_ball.h" #include "m_actor_shadow.h" #include "m_common_data.h" #include "m_debug.h" #include "m_field_info.h" #include "m_lib.h" #include "m_name_table.h" #include "m_npc.h" #include "m_player_lib.h" #include "m_quest.h" #include "m_random_field.h" #include "m_roll_lib.h" #include "sys_matrix.h" #include "m_collision_bg.h" extern Gfx act_ball_b_model[]; extern Gfx act_ball_d_model[]; extern Gfx act_ball_s_model[]; Gfx* ball_model_tbl[] = { act_ball_b_model, act_ball_d_model, act_ball_s_model, }; static void aBALL_actor_ct(ACTOR* actor, GAME* game); static void aBALL_actor_dt(ACTOR* actor, GAME* game); static void aBALL_actor_move(ACTOR* actor, GAME* game); static void aBALL_actor_draw(ACTOR* actor, GAME* game); ACTOR_PROFILE Ball_Profile = { mAc_PROFILE_BALL, ACTOR_PART_BG, ACTOR_STATE_NO_MOVE_WHILE_CULLED, ETC_BALL, ACTOR_OBJ_BANK_KEEP, sizeof(BALL_ACTOR), &aBALL_actor_ct, &aBALL_actor_dt, &aBALL_actor_move, &aBALL_actor_draw, NULL, }; BALL_ACTOR* Global_Actor_p; ClObjPipeData_c aBALL_CoInfoData = { { 0x39, 0x20, ClObj_TYPE_PIPE }, // collision data { 1 }, // element data // Pipe specs { 13, // radius 30, // height -10, // offset { 0, 0, 0 }, // center }, }; StatusData_c aBALL_StatusData = { 0, 13, 30, -10, 100, }; static void aBALL_process_ground_init(ACTOR*, GAME*); static void aBALL_process_air_water(ACTOR*, GAME*); static void aBALL_process_ground_water(ACTOR*, GAME*); static void aBALL_process_ground(ACTOR*, GAME*); static void aBALL_process_air(ACTOR*, GAME*); static void aBALL_process_air_water_init(ACTOR* actor, GAME*); static void aBALL_process_ground_water_init(ACTOR* actor, GAME*); static int aBALL_Random_pos_set(xyz_t* pos) { int x_max; int z_max; int random_x; int random_z; int ut_x; int ut_z; int i; int j; x_max = mFI_GetBlockXMax(); z_max = mFI_GetBlockZMax(); random_x = RANDOM_F(x_max); random_z = RANDOM_F(z_max); for (i = 0; i < x_max; i++) { for (j = 0; j < z_max; j++) { if ((mFI_CheckBlockKind_OR(random_x, random_z, mRF_BLOCKKIND_PLAYER | mRF_BLOCKKIND_SHOP | mRF_BLOCKKIND_STATION | mRF_BLOCKKIND_POOL | mRF_BLOCKKIND_OCEAN | mRF_BLOCKKIND_ISLAND | mRF_BLOCKKIND_OFFING) == 0) && (mNpc_GetMakeUtNuminBlock_hard_area(&ut_x, &ut_z, random_x, random_z, 2)) == TRUE) { mFI_BkandUtNum2CenterWpos(pos, random_x, random_z, ut_x, ut_z); return TRUE; } if (random_z == z_max - 1) { random_z = 0; } else { random_z += 1; } } if (random_x == x_max - 1) { random_x = 0; } else { random_x += 1; } } return FALSE; } static void aBALL_actor_ct(ACTOR* actor, GAME* game) { BALL_ACTOR* ball = (BALL_ACTOR*)actor; GAME_PLAY* play = (GAME_PLAY*)game; Global_Actor_p = ball; if ((0.0f == Common_Get(ball_pos).x) && (0.0f == Common_Get(ball_pos).y) && (0.0f == Common_Get(ball_pos).z)) { if (aBALL_Random_pos_set(&actor->world.position) == 0) { actor->world.position = actor->home.position; } actor->world.position.y = mCoBG_GetBgY_AngleS_FromWpos(NULL, actor->world.position, 0.0f); Common_Set(ball_type, RANDOM(3.0f)); Common_Set(ball_pos, actor->world.position); ball->type = Common_Get(ball_type); } else { actor->world.position = Common_Get(ball_pos); ball->type = Common_Get(ball_type); } Common_Get(clip).ball_redma_proc = NULL; Shape_Info_init(actor, 0.0f, &mAc_ActorShadowEllipse, 9.0f, 17.0f); ClObjPipe_ct(game, &ball->ball_pipe); ClObjPipe_set5(game, &ball->ball_pipe, actor, &aBALL_CoInfoData); CollisionCheck_Status_set3(&actor->status_data, &aBALL_StatusData); ball->unk206 = 3; aBALL_process_ground_init(actor, game); ball->collider = NULL; actor->max_velocity_y = -20.0f; actor->gravity = 0.3f; actor->speed = 0.0f; ball->ball_max_speed = 0.0f; ball->ball_acceleration = 0.06f; ball->ball_speed = 0.0f; actor->scale.x = 0.01f; actor->scale.y = 0.01f; actor->scale.z = 0.01f; ball->angle.x = qrand(); ball->angle.y = qrand(); ball->angle.z = qrand(); ball->unk20A = 0; ball->unk20C = 0; } static void aBALL_actor_dt(ACTOR* actor, GAME* game) { BALL_ACTOR* ball = (BALL_ACTOR*)actor; if ((ball->unk208 & 1) || (ball->unk208 & 2) || (mRlib_Set_Position_Check(actor) == 0)) { Common_Set(ball_pos, ZeroVec); } else { Common_Set(ball_pos, actor->world.position); } Common_Get(clip).ball_redma_proc = NULL; ClObjPipe_dt(game, &ball->ball_pipe); } static void aBALL_position_move(BALL_ACTOR* actor) { xyz_t pos; s_xyz angle; pos = actor->actor_class.world.position; mCoBG_GetBgY_AngleS_FromWpos(&angle, pos, 0.0f); if ((actor->actor_class.bg_collision_check.result.on_ground) || (actor->actor_class.bg_collision_check.result.is_in_water)) { chase_f(&actor->actor_class.speed, actor->ball_max_speed, actor->ball_acceleration); } if (!(actor->unk208 & 2)) { mRlib_spdF_Angle_to_spdXZ(&actor->actor_class.position_speed, &actor->actor_class.speed, &actor->actor_class.world.angle.y); chase_f(&actor->actor_class.position_speed.y, actor->actor_class.max_velocity_y, actor->actor_class.gravity); mRlib_position_move_for_sloop(&actor->actor_class, &angle); if (actor->actor_class.world.position.z < 840.0f) { actor->actor_class.world.position.z = 840.0f; } } } static void aBALL_BGcheck(BALL_ACTOR* actor) { f32 speed_y; s16 hit_angle; s16 rot; xyz_t pos_speed; f32 sin; f32 cos; f32 speed; f32 speed_factor; f32 sincos; speed_y = actor->actor_class.position_speed.y; if (((actor->process_proc == aBALL_process_air_water) || (actor->process_proc == aBALL_process_ground_water)) || (actor->actor_class.bg_collision_check.result.unit_attribute == 11 || actor->actor_class.bg_collision_check.result.unit_attribute == 22)) { mCoBG_BgCheckControll(&actor->bgpos, &actor->actor_class, 12.0f, -12.0f, 0, 1, 0); if ((actor->actor_class.bg_collision_check.result.unit_attribute == 11 || actor->actor_class.bg_collision_check.result.unit_attribute == 22) && (actor->actor_class.bg_collision_check.result.on_ground)) { f32 bg_y = actor->bgpos.y; bg_y *= (0.1f + GETREG(TAKREG, 7) * 0.01f); actor->actor_class.world.position.y += bg_y; } actor->actor_class.world.position.x += actor->bgpos.x; actor->actor_class.world.position.z += actor->bgpos.z; actor->actor_class.world.position.x += actor->bgpos.x; actor->actor_class.world.position.z += actor->bgpos.z; } else { mCoBG_BgCheckControll(&actor->bgpos, &actor->actor_class, 12.0f, -12.0f, 0, 0, 0); mRlib_Station_step_modify_to_wall(&actor->actor_class); } if (((actor->process_proc == aBALL_process_air) || (actor->process_proc == aBALL_process_air_water)) && actor->actor_class.bg_collision_check.result.on_ground) { if (actor->unk206 < 3) { actor->unk206++; if (actor->actor_class.bg_collision_check.result.is_in_water) { actor->actor_class.position_speed.y = 0.2f; } else { actor->actor_class.position_speed.y = 0.7f * -speed_y; } } } if (actor->actor_class.bg_collision_check.result.hit_wall & 1) { hit_angle = mRlib_Get_HitWallAngleY(&actor->actor_class); rot = actor->actor_class.world.angle.y - (hit_angle + 0x8000); if (ABS(rot) < 0x4000) { pos_speed = actor->actor_class.position_speed; sin = sin_s(hit_angle); cos = cos_s(hit_angle); sincos = sin * cos; speed = -((pos_speed.z * cos) + (pos_speed.x * sin)); speed_factor = (speed * 0.07f) + 1.2f; if (speed > 1.0f) { sAdo_OngenTrgStartSpeed(speed, 0x8026, &actor->actor_class.world.position); } actor->actor_class.position_speed.z = ((1.0f - (speed_factor * cos * cos)) * pos_speed.z) - (pos_speed.x * speed_factor * sincos); actor->actor_class.position_speed.x = (-pos_speed.z * speed_factor * sincos) + (pos_speed.x * (1.0f - (speed_factor * sin * sin))); mRlib_spdXZ_to_spdF_Angle(&actor->actor_class.position_speed, &actor->actor_class.speed, &actor->actor_class.world.angle.y); } } } static void aBALL_OBJcheck(BALL_ACTOR* actor, GAME*) { int wade; ACTOR* collided; xyz_t pos_speed; s16 angle; f32 sin; f32 cos; f32 fact; f32 colliderSpeed; f32 collidedSpeed; f32 abs; f32 newSins; f32 newCos; f32 newSpeedX; f32 newSpeedZ; f32 newFact; f32 speedFactor; int speedAngle; xyz_t collisionSpeed; xyz_t collision; wade = mFI_GetPlayerWade(); if (actor->ball_pipe.collision_obj.collision_flags0 & 2) { collided = actor->ball_pipe.collision_obj.collided_actor; actor->ball_pipe.collision_obj.collision_flags0 &= ~2; if (mQst_CheckSoccerTarget(collided) != 0) { mQst_NextSoccer(collided); actor->actor_class.speed = 0.0f; actor->actor_class.position_speed = ZeroVec; } else if ((collided != NULL) && (!(actor->unk208 & 2)) && (wade != 1) && (wade != 2)) { if (actor->collider != collided) { pos_speed = collided->position_speed; actor->collider = collided; actor->unk20C = GETREG(TAKREG, 15) + 30; angle = atans_table(actor->actor_class.world.position.z - collided->world.position.z, actor->actor_class.world.position.x - collided->world.position.x); sin = sin_s(angle); cos = cos_s(angle); colliderSpeed = (sin * actor->actor_class.position_speed.x) + (cos * actor->actor_class.position_speed.z); fact = sqrtf((pos_speed.x * pos_speed.x) + (pos_speed.z * pos_speed.z)); xyz_t_mult_v(&pos_speed, ((24.0f / 180.0f) * fact) * 0.9f + 0.1f); collidedSpeed = (sin * pos_speed.x) + (cos * pos_speed.z); abs = ABS(colliderSpeed + collidedSpeed); newSins = abs * sin_s(angle); newCos = abs * cos_s(angle); newSpeedX = actor->actor_class.position_speed.x + newSins; newSpeedZ = actor->actor_class.position_speed.z + newCos; newFact = sqrtf((newSpeedX * newSpeedX) + (newSpeedZ * newSpeedZ)); newFact = CLAMP_MAX(newFact, 11.0f); speedFactor = newFact / 11.0f; if (actor->actor_class.bg_collision_check.result.on_ground) { /* TODO: this is fakematch right? */ if (!actor->actor_class.speed) { f32 angle = ((speedFactor * 90.0f) + (speedFactor * 35.0f) * fqrand2()); speedAngle = DEG2SHORT_ANGLE(angle); actor->actor_class.speed = cos_s(speedAngle) * newFact; actor->actor_class.position_speed.y = sin_s(speedAngle) * newFact; } else { actor->actor_class.speed = newFact * 0.75f; } } else { actor->actor_class.speed = newFact * 0.75f; } actor->actor_class.world.angle.y = atans_table(newSpeedZ, newSpeedX); actor->actor_class.speed *= 0.9f; sAdo_OngenTrgStartSpeed(actor->actor_class.speed, 0x25, &actor->actor_class.world.position); actor->unk20C = GETREG(TAKREG, 15) + 30; } else { collision = actor->actor_class.status_data.collision_vec; xyz_t_add(&actor->actor_class.position_speed, &collision, &collisionSpeed); if ((wade != 1) && (wade != 2)) { actor->actor_class.speed = sqrtf((collisionSpeed.x * collisionSpeed.x) + (collisionSpeed.z * collisionSpeed.z)); actor->actor_class.speed = CLAMP_MAX(actor->actor_class.speed, 11.0f); actor->actor_class.world.angle.y = atans_table(collisionSpeed.z, collisionSpeed.x); } } } else { if (actor->unk20C <= 0) { actor->collider = NULL; } else { actor->unk20C--; } } } else { if (actor->unk20C <= 0) { actor->collider = NULL; } else { actor->unk20C--; } } } static void aBALL_House_Tree_Rev_Check(BALL_ACTOR* actor) { if (mRlib_HeightGapCheck_And_ReversePos(&actor->actor_class) != 1) { actor->unk208 |= 1; Actor_delete(&actor->actor_class); } } static void aBALL_process_air_init(ACTOR* actor, GAME* game) { BALL_ACTOR* ball = (BALL_ACTOR*)actor; f32 angle; angle = mCoBG_GetBgY_AngleS_FromWpos(NULL, actor->world.position, 0.0f); actor->shape_info.draw_shadow = 1; if ((ball->process_proc == aBALL_process_ground) && ((actor->world.position.y - angle) > 20.0f)) { sAdo_OngenTrgStart(0x43D, &actor->world.position); } ball->process_proc = aBALL_process_air; } static void aBALL_process_air(ACTOR* actor, GAME* game) { BALL_ACTOR* ball = (BALL_ACTOR*)actor; ball->ball_acceleration = 0.0f; add_calc0(&ball->ball_y, 0.5f, 100.0f); actor->max_velocity_y = -20.0f; actor->gravity = 0.3f; ball->ball_speed = actor->speed; if (actor->bg_collision_check.result.on_ground) { if (actor->bg_collision_check.result.is_in_water) { aBALL_process_ground_water_init(actor, game); } else { aBALL_process_ground_init(actor, game); } } else if (actor->bg_collision_check.result.is_in_water) { aBALL_process_air_water_init(actor, game); } } static void aBALL_process_ground_init(ACTOR* actor, GAME* game) { BALL_ACTOR* ball = (BALL_ACTOR*)actor; actor->shape_info.draw_shadow = 1; if (actor->position_speed.y > 0.0f) { ball->process_proc = aBALL_process_air; } else { ball->process_proc = aBALL_process_ground; } } static void aBALL_process_ground(ACTOR* actor, GAME* game) { BALL_ACTOR* ball = (BALL_ACTOR*)actor; f32 temp; xyz_t norm; s16 angle_rate; s16 angle; f32 distance; f32 speed_x; f32 speed_z; s16 effect_type; mCoBG_GetBgNorm_FromWpos(&norm, actor->world.position); if (mRlib_Get_ground_norm_inHole(actor, &norm, &distance, &angle, &angle_rate, 1.0f) != 0) { f32 dist; f32 distance_add; distance_add = (distance - 40.0f) - 5.0f; dist = 0.0f; if (distance_add < 0.0f) { dist = distance_add; } dist *= 25.0f; add_calc(&ball->ball_y, dist, 0.5f, 200.0f, 5.0f); actor->position_speed.x *= 0.83666f; actor->position_speed.z *= 0.83666f; if (distance < 1.0f) { speed_x = ABS(actor->position_speed.x); if (speed_x < 1.0f) { speed_z = ABS(actor->position_speed.z); if (speed_z < 1.0f) { ball->unk208 |= 2; ball->ball_pipe.attribute.pipe.height = 20; ball->ball_pipe.attribute.pipe.radius = 18; actor->status_data.weight = MASSTYPE_HEAVY; actor->speed = 0.0f; return; } } } } else { mRlib_Get_norm_Clif(actor, &norm); add_calc0(&ball->ball_y, 0.5f, 100.0f); } if (!F32_IS_ZERO(norm.x) || !F32_IS_ZERO(norm.z)) { if (Math3d_normalizeXyz_t(&norm)) { actor->position_speed.x += 1.35f * norm.x; actor->position_speed.z += 1.35f * norm.z; mRlib_spdXZ_to_spdF_Angle(&actor->position_speed, &ball->ball_max_speed, &actor->world.angle.y); ball->ball_max_speed = (ball->ball_max_speed < 8.0f) ? ball->ball_max_speed : 8.0f; ball->ball_acceleration = 0.05f; } } else { ball->ball_max_speed = 0.0f; ball->ball_acceleration = 0.06f; } actor->max_velocity_y = -20.0f; actor->gravity = 0.3f; ball->ball_speed = actor->speed; if ((actor->bg_collision_check.result.is_in_water) || (actor->bg_collision_check.result.unit_attribute) == 11) { if (actor->bg_collision_check.result.on_ground != 0) { aBALL_process_ground_water_init(actor, game); } else { ball->unk206 = 0; aBALL_process_air_water_init(actor, game); } } else if (actor->bg_collision_check.result.on_ground == 0) { ball->unk206 = 0; aBALL_process_air_init(actor, game); return; } if (!(game->frame_counter & 7) && (actor->bg_collision_check.result.unit_attribute) == 9) { if (actor->speed > 1.0f) { if (actor->speed > 4.0f) { effect_type = 1; } else { effect_type = 0; } Common_Get(clip).effect_clip->effect_make_proc(0x33, actor->world.position, 1, actor->world.angle.y, game, actor->npc_id, 0, effect_type); } } } static void aBALL_set_spd_relations_in_water(ACTOR* actor, GAME* game) { static s16 angl_add_table[] = { 0x100, 0x400, }; BALL_ACTOR* ball = (BALL_ACTOR*)actor; xyz_t pos_flow; f32 height; s16 angle; int apply_angle; height = mCoBG_GetWaterHeight_File(actor->world.position, "ac_ball.c", 0x361); add_calc0(&ball->ball_y, 0.5f, 100.0f); mCoBG_GetWaterFlow(&pos_flow, actor->bg_collision_check.result.unit_attribute); angle = atans_table(pos_flow.z, pos_flow.x); apply_angle = ABS((s16)(actor->world.angle.y - angle)); chase_angle(&actor->world.angle.y, angle, angl_add_table[apply_angle > 0x4000]); if (actor->world.position.y < height) { actor->max_velocity_y = 1.0f; } else { actor->max_velocity_y = -1.0f; } if (ball->timer < 0x20) { if (!(game->frame_counter & 3) && (ball->timer < 0x10) || !(game->frame_counter & 7)) { Common_Get(clip).effect_clip->effect_make_proc(0x45, actor->world.position, 1, actor->world.angle.y, game, actor->npc_id, 1, 0); } ball->timer++; } actor->gravity = 0.1f; ball->ball_max_speed = 1.0f; ball->ball_acceleration = 0.1f; } static void aBALL_process_air_water_init(ACTOR* actor, GAME* game) { BALL_ACTOR* ball = (BALL_ACTOR*)actor; actor->shape_info.draw_shadow = 0; ball->process_proc = aBALL_process_air_water; } static void aBALL_process_air_water(ACTOR* actor, GAME* game) { BALL_ACTOR* ball = (BALL_ACTOR*)actor; GAME_PLAY* play = (GAME_PLAY*)game; f32 ball_speed; aBALL_set_spd_relations_in_water(actor, game); add_calc0(&ball->ball_y, 0.5f, 100.0f); ball_speed = ball->ball_speed; ball_speed -= 0.5f; if (ball_speed < 0.0f) { ball_speed = 0.0f; } ball->ball_speed = ball_speed; if (Common_Get(clip).gyo_clip != NULL) { Common_Get(clip).gyo_clip->ballcheck_gyoei_proc(&actor->world.position, 20.0f, 1); } if (actor->bg_collision_check.result.on_ground) { if (actor->bg_collision_check.result.is_in_water) { aBALL_process_ground_water_init(actor, game); } else if (actor->bg_collision_check.result.unit_attribute != 11) { aBALL_process_ground_init(actor, game); } } else if (!actor->bg_collision_check.result.is_in_water) { aBALL_process_air_init(actor, game); } } static void aBALL_process_ground_water_init(ACTOR* actor, GAME* game) { BALL_ACTOR* ball = (BALL_ACTOR*)actor; actor->shape_info.draw_shadow = 0; ball->timer = 0; ball->process_proc = aBALL_process_ground_water; } static void aBALL_process_ground_water(ACTOR* actor, GAME* game) { BALL_ACTOR* ball = (BALL_ACTOR*)actor; u32 currentUT; xyz_t* pos; f32 height; currentUT = actor->bg_collision_check.result.unit_attribute; aBALL_set_spd_relations_in_water(actor, game); ball->ball_speed = actor->speed; if (Common_Get(clip).gyo_clip != NULL) { Common_Get(clip).gyo_clip->ballcheck_gyoei_proc(&actor->world.position, 20.0f, 1); } if (actor->bg_collision_check.result.on_ground) { if (!(actor->bg_collision_check.result.is_in_water) && (currentUT != 11) && currentUT != 22) { aBALL_process_ground_init(actor, game); } } else if (!ball->actor_class.bg_collision_check.result.is_in_water) { aBALL_process_air_init(actor, game); } else { aBALL_process_air_water_init(actor, game); } if (currentUT == 11 || currentUT == 22) { pos = &ball->bgpos; actor->world.position.y += (0.5f * pos->y); if (currentUT == 22) { height = ABS(pos->y); if (height < 1.0f) { aBALL_process_ground_init(actor, game); } } } } static void aBALL_calc_axis(ACTOR* actor) { BALL_ACTOR* ball = (BALL_ACTOR*)actor; s16 angle; f32 speed_fact; angle = (actor->speed * 434.81952f); if (ball->process_proc == aBALL_process_air_water || ball->process_proc == aBALL_process_ground_water) { speed_fact = ((-1.0f) - actor->position_speed.y) / (-2.0f); angle *= sin_s(DEG2SHORT_ANGLE2(30.0f + (60.0f * speed_fact))); } mRlib_Roll_Matrix_to_s_xyz(actor, &ball->angle, angle); } static int aBALL_player_angle_distance_check(ACTOR* actor, PLAYER_ACTOR* player) { f32 distance; s16 angle; int abs_angle; distance = search_position_distance(&actor->world.position, &player->actor_class.world.position); angle = player->actor_class.shape_info.rotation.y - search_position_angleY(&player->actor_class.world.position, &actor->world.position); if (distance < 60.0f) { abs_angle = ABS(angle); if (abs_angle < 0x2000) { return 1; } } return 0; } static void aBALL_status_check(ACTOR* actor, GAME* game) { BALL_ACTOR* ball = (BALL_ACTOR*)actor; GAME_PLAY* play = (GAME_PLAY*)game; PLAYER_ACTOR* player; PLAYER_ACTOR* player2; int i; if (ball->unk208 & 4) { player = GET_PLAYER_ACTOR(play); ball->unk208 &= ~4; if (aBALL_player_angle_distance_check(actor, player) || F32_IS_ZERO(actor->speed)) { actor->world.angle.y = player->actor_class.shape_info.rotation.y; actor->speed = 2.0f; actor->position_speed.y = 4.5f; if (ball->unk208 & 2) { ball->ball_pipe.attribute.pipe.height = 30; ball->ball_pipe.attribute.pipe.radius = 13; ball->unk208 &= ~2; actor->status_data.weight = 0x64; } } } if (ball->unk208 & 8) { ball->unk208 &= ~8; if (!(ball->unk208 & 2)) { player2 = GET_PLAYER_ACTOR(play); if (aBALL_player_angle_distance_check(actor, player2) || F32_IS_ZERO(actor->speed)) { actor->world.angle.y = player2->actor_class.shape_info.rotation.y + 0x2000; actor->speed = 4.5f; actor->position_speed.y = 3.0f; } } } if (!(ball->unk208 & 1)) { if (actor->bg_collision_check.result.is_in_water) { sAdo_OngenTrgStart(0x27, &actor->world.position); ball->unk208 |= 1; if (Common_Get(clip).gyo_clip != NULL) { Common_Get(clip).gyo_clip->ballcheck_gyoei_proc(&actor->world.position, 20.0f, 0); } ball->ball_pipe.attribute.pipe.height = 10; Common_Get(clip).effect_clip->effect_make_proc(0x3A, actor->world.position, 1, 0, game, actor->npc_id, 1, 0); for (i = 2; i < 6; i++) { Common_Get(clip).effect_clip->effect_make_proc(0x3B, actor->world.position, 1, actor->world.angle.y, game, actor->npc_id, 0, i | FTR1_START); } } } } static void aBALL_actor_move(ACTOR* actor, GAME* game) { BALL_ACTOR* ball = (BALL_ACTOR*)actor; GAME_PLAY* play = (GAME_PLAY*)game; aBALL_House_Tree_Rev_Check(ball); if (!(actor->state_bitfield & 0x40)) { if (actor->bg_collision_check.result.is_in_water || (ball->unk208 & 2)) { Actor_delete(actor); } if (actor->speed == 0.0f) { return; } } Common_Set(ball_pos, actor->world.position); aBALL_position_move(ball); ball->process_proc(actor, game); aBALL_BGcheck(ball); aBALL_OBJcheck(ball, game); CollisionCheck_Uty_ActorWorldPosSetPipeC(&ball->actor_class, &ball->ball_pipe); CollisionCheck_setOC(game, &play->collision_check, &ball->ball_pipe.collision_obj); aBALL_calc_axis(actor); aBALL_status_check(actor, game); } static void aBALL_actor_draw(ACTOR* actor, GAME* game) { BALL_ACTOR* ball = (BALL_ACTOR*)actor; GRAPH* graph; Gfx* gfx; graph = game->graph; OPEN_DISP(graph); gfx = NOW_POLY_OPA_DISP; Matrix_translate(0.0f, ball->ball_y, 0.0f, 1); Matrix_rotateXYZ(ball->angle.x, ball->angle.y, ball->angle.z, 1); gDPPipeSync(gfx++); gSPMatrix(gfx++, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(gfx++, ball_model_tbl[ball->type]); NOW_POLY_OPA_DISP = gfx; CLOSE_DISP(graph); }