Implement & link ac_airplane.c

This commit is contained in:
Cuyler36
2023-06-23 01:03:42 -04:00
parent b1a9b19323
commit a17be189b6
12 changed files with 577 additions and 5 deletions
+4
View File
@@ -143,6 +143,10 @@ ac_sample.c:
.rodata: [0x80643860, 0x80643868]
.data: [0x8065FA40, 0x8065FAA0]
.bss: [0x812F96A0, 0x812F96E0]
ac_airplane.c:
.text: [0x8040F614, 0x804104AC]
.rodata: [0x80643868, 0x80643918]
.data: [0x8065FAA0, 0x8065FB68]
ac_animal_logo.c:
.text: [0x804104AC, 0x804117D4]
.rodata: [0x80643918, 0x80643A88]
+62
View File
@@ -0,0 +1,62 @@
#ifndef AC_AIRPLANE_H
#define AC_AIRPLANE_H
#include "types.h"
#include "m_actor.h"
#ifdef __cplusplus
extern "C" {
#endif
enum {
aAp_STATUS_FREE_FLY_MOVE,
aAp_STATUS_FALL_FLY_MOVE,
aAp_STATUS_FALL_FLY_MOVE2,
aAp_STATUS_SOMER_FLY_MOVE,
aAp_STATUS_START_FLY_MOVE,
aAp_STATUS_STOP_FLY_MOVE,
aAp_STATUS_PLAYER_CATCH,
aAp_STATUS_NUM
};
enum {
aAp_TILT_DOWN,
aAp_TILT_UP,
aAp_TILT_NUM
};
typedef struct airplane_s {
ACTOR actor_class;
s16 status;
s16 tilt_status;
f32 speed;
f32 y_speed;
f32 rotY_goal;
f32 rotY_min;
f32 rotY;
f32 rotX;
f32 rotZ;
int joystick_y;
int joystick_x;
s16 ground_timer;
int wind_frame;
int wind_change_frame;
xyz_t* wind;
u8 _1AC[28]; // unused
} AIRPLANE_ACTOR;
extern ACTOR_PROFILE Airplane_Profile;
#ifdef __cplusplus
}
#endif
#endif
+41
View File
@@ -0,0 +1,41 @@
#ifndef EF_EFFECT_CONTROL_H
#define EF_EFFECT_CONTROL_H
#include "types.h"
#include "m_lib.h"
#include "m_actor.h"
#ifdef __cplusplus
extern "C" {
#endif
enum effect_type {
eEC_EFFECT_SHOCK,
eEC_EFFECT_DUST,
eEC_EFFECT_MUKA,
eEC_EFFECT_WARAU,
/* TODO: finish */
eEC_EFFECT_NUM = 126
};
typedef void (*eEC_NAME2EFFECTMAKE_PROC)(int, xyz_t, int, short, GAME*, u16, s16, s16);
typedef struct effect_control_clip_s {
eEC_NAME2EFFECTMAKE_PROC effect_make_proc;
/* TODO: finish */
} eEC_EffectControl_Clip_c;
typedef struct effect_control_s EFFECT_CONTROL_ACTOR;
struct effect_control_s {
ACTOR actor_class;
eEC_EffectControl_Clip_c clip;
};
#ifdef __cplusplus
}
#endif
#endif
+10 -3
View File
@@ -5,6 +5,8 @@
#include "m_actor_type.h"
#include "game.h"
#include "m_lib.h"
#include "m_lights.h"
#include "m_collision_bg.h"
#ifdef __cplusplus
extern "C" {
@@ -18,6 +20,7 @@ typedef void (*mActor_proc)(ACTOR*, GAME*);
#define ACTOR_OBJ_BANK_NONE 0
#define ACTOR_OBJ_BANK_3 3 /* TODO: rename, also likely an enum */
#define ACTOR_OBJ_BANK_7 7
#define ACTOR_OBJ_BANK_12 12
enum actor_part {
@@ -48,7 +51,7 @@ typedef struct actor_profile_s {
/* 0x20 */ mActor_proc sv_proc; /* save */
} ACTOR_PROFILE;
typedef void (*mActor_shadow_proc)(ACTOR*, void*, GAME_PLAY*); /* TODO: void* is actually LightsN*, see m_lights */
typedef void (*mActor_shadow_proc)(ACTOR*, LightsN*, GAME_PLAY*);
/* sizeof(Shape_Info) == 0x48 */
typedef struct actor_shape_info_s {
@@ -95,8 +98,7 @@ struct actor_s {
/* 0x078 */ f32 gravity; /* gravity acting on actor */
/* 0x07C */ f32 max_velocity_y; /* maximum y velocity possible due to gravity, usually -20.0f */
/* 0x080 */ f32 ground_y; /* vertical position of ground underneath actor */
/* 0x084 */ u8 bg_collision_data[0xB2-0x84]; /* actor collision data, TODO: implement, mCoBG */
/* 0x0B2 */ u8 unused_b2[2];
/* 0x084 */ mCoBG_Check_c bg_collision_check; /* background object collision info with actor */
/* 0x0B4 */ u8 unknown_b4; /* some sort of flag */
/* 0x0B5 */ u8 drawn; /* was drawn flag, TRUE = actor was drawn, FALSE = actor was not drawn */
/* 0x0B6 */ s16 player_angle_y; /* Y angle (yaw) between actor and player actor */
@@ -141,6 +143,11 @@ typedef struct actor_info_s {
extern void Actor_delete(ACTOR* actor);
extern ACTOR* Actor_info_fgName_search(Actor_info* actor_info, mActor_name_t fg_name, int part);
extern void Actor_world_to_eye(ACTOR* actor, f32 eye_height);
extern void Shape_Info_init(ACTOR* actor, f32 y_ofs, mActor_shadow_proc shadow_proc, f32 shadow_sizeX, f32 shadow_sizeZ);
extern void Actor_position_moveF(ACTOR* actor);
extern void mAc_ActorShadowCircle(ACTOR* actor, LightsN* lightsN, GAME_PLAY* play);
extern void mAc_ActorShadowEllipse(ACTOR* actor, LightsN* lightsN, GAME_PLAY* play);
#ifdef __cplusplus
}
+3 -1
View File
@@ -6,6 +6,7 @@
#include "ac_insect_h.h"
#include "ac_structure.h"
#include "ac_animal_logo.h"
#include "ef_effect_control.h"
#ifdef __cplusplus
extern "C" {
@@ -17,7 +18,8 @@ typedef struct clip_s {
/* 0x07C */ aINS_Clip_c* insect_clip;
/* 0x080 */ void* _080[(0x08C - 0x080) / sizeof(void*)];
/* 0x08C */ aSTR_Clip_c* structure_clip;
/* 0x090 */ void* _090[(0x0AC - 0x090) / sizeof(void*)];
/* 0x090 */ eEC_EffectControl_Clip_c* effect_clip;
/* 0x094 */ void* _094[(0x0AC - 0x094) / sizeof(void*)];
/* 0x0AC */ aGYO_Clip_c* gyo_clip;
/* 0x0B0 */ void* _0B0[(0x0DC - 0x0B0) / sizeof(void*)];
/* 0x0DC */ aAL_Clip_c* animal_logo_clip;
+34 -1
View File
@@ -51,14 +51,47 @@ typedef union collision_bg_u {
mCoBG_CollisionData_c data;
} mCoBG_Collision_u;
typedef struct collision_bg_check_result_s {
u32 on_ground:1;
u32 hit_attribute_wall:5;
u32 hit_wall:5;
u32 hit_wall_count:3;
u32 unk_flag0:1;
u32 unit_attribute:6;
u32 is_on_move_bg_obj:1;
u32 is_in_water:1;
u32 unk_flag1:1;
u32 unk_flag2:1;
u32 unk_flag3:1;
u32 unk_flag4:1;
u32 unk_flag5:1;
u32 unk_flag6:4;
} mCoBG_CheckResult_c;
typedef struct wall_info_s {
s16 angleY;
s16 type;
} mCoBG_WallInfo_c;
typedef struct collision_bg_check_s {
mCoBG_Collision_u collision_units[5];
mCoBG_CheckResult_c result;
f32 wall_top_y;
f32 wall_bottom_y;
f32 ground_y;
mCoBG_WallInfo_c wall_info[2];
s16 in_front_wall_angle_y;
} mCoBG_Check_c;
extern u32 mCoBG_Wpos2BgAttribute_Original(xyz_t wpos);
extern u32 mCoBG_Wpos2Attribute(xyz_t wpos, char* is_diggable);
extern int mCoBG_CheckWaterAttribute(u32 attribute);
extern f32 mCoBG_GetBgY_AngleS_FromWpos(s_xyz* angle_to_ground, xyz_t wpos, f32 offset);
extern f32 mCoBG_GetBgY_AngleS_FromWpos(s_xyz* angle_to_ground, xyz_t wpos, f32 offset_y);
extern int mCoBG_CheckWaterAttribute_OutOfSea(u32 attribute);
extern int mCoBG_CheckHole_OrgAttr(u32 attribute);
extern f32 mCoBG_GetBgY_OnlyCenter_FromWpos2(xyz_t wpos, f32 foot_dist);
extern int mCoBG_Attribute2CheckPlant(u32 attribute, const xyz_t* wpos);
extern void mCoBG_BgCheckControll(xyz_t* reverse_pos, ACTOR* actor, f32 check_range, f32 offset_y, s16 wall_attr_check, s16 no_reverse, s16 check_type);
extern f32 mCoBG_GetWaterHeight_File(xyz_t wpos, char* file, int line);
#define mCoBG_GetWaterHeight(wpos) mCoBG_GetWaterHeight_File(wpos, __FILE__, __LINE__)
+8
View File
@@ -24,9 +24,11 @@ extern "C" {
/* radians -> short angle */
#define RAD2SHORT_ANGLE(rad) ((s16)(int)((rad) * (65536.0f / (2.0f * F_PI))))
#define RAD2SHORTANGLE(rad) ((s16)((32768.0f / F_PI) * ((f32)(rad))))
/* short angle -> radians */
#define SHORT2RAD_ANGLE(s) ((((f32)(s)) / (65536.0f / (2.0f * F_PI))))
#define SHORTANGLE2RAD(sangle) ((F_PI / 32768.0f) * ((f32)(sangle)))
/* degrees -> short angle */
#define DEG2SHORT_ANGLE(deg) ((s16)((deg) * (65536.0f / 360.0f)))
@@ -34,6 +36,12 @@ extern "C" {
/* short angle -> degrees */
#define SHORT2DEG_ANGLE(s) ((((f32)(s)) / (65536.0f / 360.0f)))
/* radians -> degrees */
#define RAD2DEG(rad) ((180.0f / F_PI) * (rad))
/* degrees -> radians */
#define DEG2RAD(deg) ((F_PI / 180.0f) * (deg))
typedef struct rgba_t { //can be put in other place
u8 r, g, b, a;
} rgba_t;
+20
View File
@@ -0,0 +1,20 @@
#ifndef M_LIGHTS_H
#define M_LIGHTS_H
#include "types.h"
#include "PR/mbi.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct lightsn_s {
u8 diffuse_count;
Lights7 lights;
} LightsN;
#ifdef __cplusplus
}
#endif
#endif
+3
View File
@@ -472,6 +472,9 @@ extern int mNT_check_unknown(mActor_name_t item_no);
#define TRAIN0 0x580A
#define TRAIN1 0x580B
#define ETC_START 0x8000
#define ETC_AIRPLANE ETC_START
#define MISC_ACTOR_START 0x9000
#define MISC_ACTOR_SAMPLE MISC_ACTOR_START
+2
View File
@@ -14,6 +14,8 @@ extern void mPlib_SetData2_controller_data_for_title_demo(mActor_name_t tool);
extern void mPlib_request_main_invade_type1(GAME_PLAY* play);
extern mActor_name_t mPlib_Get_itemNo_forWindow();
extern int mPlib_check_able_change_camera_normal_index();
extern void mPlib_request_main_refuse_type1(GAME_PLAY* play);
extern void mPlib_request_main_wait_type3(GAME_PLAY* play);
#ifdef __cplusplus
}
+3
View File
@@ -16,6 +16,9 @@ typedef struct math_3d_pipe_s {
} Math3D_pipe_c;
extern f32 Math3DVecLength(xyz_t* vec);
extern void sMath_RotateX(xyz_t* pos, f32 rad);
extern void sMath_RotateY(xyz_t* pos, f32 rad);
extern void sMath_RotateZ(xyz_t* pos, f32 rad);
extern xyz_t ZeroVec;
+387
View File
@@ -0,0 +1,387 @@
#include "ac_airplane.h"
#include "m_collision_bg.h"
#include "m_player.h"
#include "m_player_lib.h"
#include "sys_matrix.h"
#include "sys_math3d.h"
#include "sys_math.h"
#include "libc64/qrand.h"
#include "m_controller.h"
#include "m_name_table.h"
#include "m_common_data.h"
static void Airplane_Actor_ct(ACTOR* actor, GAME* game);
static void Airplane_Actor_dt(ACTOR* actor, GAME* game);
static void Airplane_Actor_move(ACTOR* actor, GAME* game);
static void Airplane_Actor_draw(ACTOR* actor, GAME* game);
/* TODO: ct, dt, & draw go in this TU, while all others go in a separate TU. Probably something like ac_airplane_move.c_inc */
ACTOR_PROFILE Airplane_Profile = {
0x05, // TODO: enum
ACTOR_PART_BG,
ACTOR_STATE_NO_MOVE_WHILE_CULLED | ACTOR_STATE_NO_DRAW_WHILE_CULLED,
ETC_AIRPLANE,
ACTOR_OBJ_BANK_7,
sizeof(AIRPLANE_ACTOR),
&Airplane_Actor_ct,
&Airplane_Actor_dt,
&Airplane_Actor_move,
&Airplane_Actor_draw,
NULL
};
static void Airplane_Actor_ct(ACTOR* actor, GAME* game) {
AIRPLANE_ACTOR* airplane = (AIRPLANE_ACTOR*)actor;
Shape_Info_init(actor, 0.0f, &mAc_ActorShadowEllipse, 6.5f, 6.5f);
airplane->status = 5;
airplane->speed = 6.2f;
airplane->y_speed = 0.0f;
airplane->actor_class.speed = airplane->speed;
airplane->rotY = RAD2DEG(SHORTANGLE2RAD((f32)actor->world_rotation.y));
airplane->rotY_goal = airplane->rotY;
airplane->rotY_min = airplane->rotY;
airplane->rotZ = 0.0f;
airplane->rotX = 0.0f;
airplane->ground_timer = 0;
airplane->wind_frame = 0;
airplane->wind_change_frame = 0;
airplane->wind = NULL;
actor->world_position.y = mCoBG_GetBgY_AngleS_FromWpos(NULL, actor->world_position, -5.5f);
}
static void Airplane_Actor_dt(ACTOR* actor, GAME* game) { }
extern Gfx glider_model[];
static void Airplane_Actor_draw(ACTOR* actor, GAME* game) {
AIRPLANE_ACTOR* airplane = (AIRPLANE_ACTOR*)actor;
if (airplane->status != aAp_STATUS_PLAYER_CATCH && airplane->status != aAp_STATUS_START_FLY_MOVE) {
GRAPH* g = game->graph;
_texture_z_light_fog_prim(g);
Matrix_RotateX(RAD2SHORTANGLE(DEG2RAD(airplane->rotX)), 1);
Matrix_RotateZ(RAD2SHORTANGLE(DEG2RAD(airplane->rotZ)), 1);
Matrix_scale(50.0f, 50.0f, 50.0f, 1);
OPEN_DISP(g);
gSPMatrix(NOW_POLY_OPA_DISP++, _Matrix_to_Mtx_new(game->graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(NOW_POLY_OPA_DISP++, glider_model);
CLOSE_DISP(g);
}
}
static void aAp_RubberMove(f32* now, f32 target, f32 step) {
*now += step * (target - *now);
}
static void aAp_FallByWall(ACTOR* actor) {
AIRPLANE_ACTOR* airplane = (AIRPLANE_ACTOR*)actor;
if (actor->bg_collision_check.result.hit_wall == 0) {
return;
}
airplane->status = aAp_STATUS_FALL_FLY_MOVE;
}
static void aAp_GroundFriction(ACTOR* actor, GAME* game) {
AIRPLANE_ACTOR* airplane = (AIRPLANE_ACTOR*)actor;
if (actor->bg_collision_check.result.on_ground) {
/* slow down speed since we're on the ground */
aAp_RubberMove(&airplane->speed, 0.0f, 0.6f);
if (airplane->speed < 1.0f) {
airplane->speed = 0.0f;
airplane->status = aAp_STATUS_STOP_FLY_MOVE;
if (airplane->ground_timer >= 5) {
airplane->ground_timer = 0;
(*Common_Get(clip.effect_clip)->effect_make_proc)(eEC_EFFECT_DUST, actor->world_position, 1, actor->world_rotation.y, game, actor->npc_id, 0, 8);
}
airplane->ground_timer++;
}
}
}
static void aAp_FreeFlyMove(ACTOR* actor, GAME* game) {
AIRPLANE_ACTOR* airplane = (AIRPLANE_ACTOR*)actor;
aAp_RubberMove(&airplane->speed, 3.0f, 0.01f);
aAp_RubberMove(&airplane->rotX, 19.0f, 0.045f);
aAp_RubberMove(&airplane->rotZ, 0.0f, 0.05f);
aAp_GroundFriction(actor, game);
aAp_FallByWall(actor);
}
static void aAp_SomerFlyMove(ACTOR* actor, GAME* game) {
AIRPLANE_ACTOR* airplane = (AIRPLANE_ACTOR*)actor;
switch (airplane->tilt_status) {
case aAp_TILT_DOWN:
{
aAp_RubberMove(&airplane->rotX, -89.0f, 0.2f);
aAp_RubberMove(&airplane->speed, 9.0f, 0.1f);
if (airplane->rotX < -87.0f) {
airplane->tilt_status = aAp_TILT_UP;
airplane->rotX = 60.0f;
}
break;
}
case aAp_TILT_UP:
{
aAp_RubberMove(&airplane->rotX, 0.0f, 0.04f);
aAp_RubberMove(&airplane->speed, 10.0f, 0.1f);
if (ABS(airplane->rotX) < 3.0f) {
airplane->status = aAp_STATUS_FREE_FLY_MOVE;
airplane->tilt_status = aAp_TILT_DOWN;
}
aAp_GroundFriction(actor, game);
break;
}
}
aAp_FallByWall(actor);
}
static int aAp_SelectFly(AIRPLANE_ACTOR* actor, int stick_y) {
int mode = (int)(fqrand() * 7.0f) & 1;
if (stick_y > 67) {
if (mode != 0) {
actor->status = aAp_STATUS_FALL_FLY_MOVE2;
}
else {
actor->status = aAp_STATUS_SOMER_FLY_MOVE;
actor->tilt_status = aAp_TILT_DOWN;
}
}
else {
actor->status = aAp_STATUS_FREE_FLY_MOVE;
}
return TRUE;
}
static void aAp_StartFlyMove(ACTOR* actor, GAME* game) {
static s16 goal_angle_random[8] = { 2366, 2002, -1092, -2366, 0, 4368, -4186, 4186 };
static s16 goal_angle_random2[8] = { 12740, 8190, -9100, -8190, -10920, 10920, 9100, 0 };
AIRPLANE_ACTOR* airplane = (AIRPLANE_ACTOR*)actor;
int now_stick_y = getJoystick_Y();
PLAYER_ACTOR* player = get_player_actor_withoutCheck((GAME_PLAY*)game);
int goal = fqrand() * 8.0f;
GAME_PLAY* play = (GAME_PLAY*)game;
int last_stick_y = airplane->joystick_y;
s16* goal_angle_random_tbl;
if (now_stick_y - last_stick_y > 30) {
f32 stick_y = ABS((f32)last_stick_y);
int adjusted_y = ABS(last_stick_y);
airplane->speed = ABS((f32)last_stick_y) * 0.0875f + 3.0f;
aAp_SelectFly(airplane, adjusted_y);
goal_angle_random_tbl = adjusted_y > 50 ? goal_angle_random2 : goal_angle_random;
actor->world_position.y = player->actor_class.world_position.y + 25.0f;
actor->world_position.x = player->actor_class.world_position.x;
actor->world_position.z = player->actor_class.world_position.z;
airplane->rotY = RAD2DEG(SHORTANGLE2RAD(player->actor_class.shape_info.rotation.y));
airplane->rotY_goal = airplane->rotY + (RAD2DEG(SHORTANGLE2RAD(goal_angle_random_tbl[goal])));
airplane->rotX = airplane->speed * RAD2DEG(-0.14959965f) + 30.0f;
airplane->rotZ = 0.0f;
airplane->y_speed = 0.0f;
mPlib_request_main_wait_type3(play);
}
}
static void aAp_PlayerCatch(ACTOR* actor, GAME* game) { }
static void aAp_StopFlyMove(ACTOR* actor, GAME* game) {
AIRPLANE_ACTOR* airplane = (AIRPLANE_ACTOR*)actor;
airplane->speed = 0.0f;
if (actor->player_distance_xz <= 30.0f && chkTrigger(BUTTON_A)) {
airplane->status = aAp_STATUS_PLAYER_CATCH; // player is now "holding" the airplane
}
}
static void aAp_FallFlyMove(ACTOR* actor, GAME* game) {
AIRPLANE_ACTOR* airplane = (AIRPLANE_ACTOR*)actor;
aAp_RubberMove(&airplane->rotX, 60.0f, 0.04f);
aAp_RubberMove(&airplane->speed, 5.0f, 0.02f);
actor->world_position.y -= 0.15f;
if (actor->bg_collision_check.result.on_ground) {
Common_Get(clip.effect_clip)->effect_make_proc(eEC_EFFECT_DUST, actor->world_position, 1, actor->world_rotation.y, game, actor->npc_id, 0, 8);
airplane->status = aAp_STATUS_STOP_FLY_MOVE;
}
}
static void aAp_FallFlyMove2(ACTOR* actor, GAME* game) {
AIRPLANE_ACTOR* airplane = (AIRPLANE_ACTOR*)actor;
aAp_RubberMove(&airplane->rotX, 70.0f, 0.15f);
aAp_RubberMove(&airplane->speed, 10.0f, 0.02f);
actor->world_position.y -= 0.15f;
if (actor->bg_collision_check.result.on_ground) {
Common_Get(clip.effect_clip)->effect_make_proc(eEC_EFFECT_DUST, actor->world_position, 1, actor->world_rotation.y, game, actor->npc_id, 0, 8);
airplane->status = aAp_STATUS_STOP_FLY_MOVE;
}
}
static void aAp_LeanAirplane(AIRPLANE_ACTOR* airplane) {
if (airplane->status == aAp_STATUS_FREE_FLY_MOVE) {
aAp_RubberMove(&airplane->rotZ, 0.0f, 0.05f);
}
else if (airplane->rotY_min - airplane->rotY > 0.0f) {
aAp_RubberMove(&airplane->rotZ, 50.0f, 0.05f);
}
else {
aAp_RubberMove(&airplane->rotZ, -50.0f, 0.05f);
}
}
static xyz_t wind1 = { 2.0f, 1.0f, 4.0f };
static xyz_t wind2 = { -3.0f, -4.0f, -7.0f };
static xyz_t wind3 = { 4.0f, -3.0f, 1.0f };
static xyz_t wind4 = { -1.0f, 3.0f, -4.0f };
static xyz_t* wind_table[4] = { &wind1, &wind2, &wind3, &wind4 };
static int wind_change_frame_table[10] = {
300, 20, 500, 1000, 100,
700, 20, 200, 80, 70
};
static void aAp_WindSystem(ACTOR* actor, GAME* game) {
AIRPLANE_ACTOR* airplane = (AIRPLANE_ACTOR*)actor;
xyz_t dir = { 0.0f, 1.0f, 0.0f };
airplane->wind_frame++;
if (airplane->wind_frame > airplane->wind_change_frame) {
int table_rng = fqrand() * 4.0f;
int change_frame_rng = fqrand() * 10.0f;
airplane->wind_frame = 0;
airplane->wind_change_frame = wind_change_frame_table[change_frame_rng];
airplane->wind = wind_table[table_rng];
}
if (airplane->status != aAp_STATUS_STOP_FLY_MOVE &&
airplane->status != aAp_STATUS_START_FLY_MOVE &&
airplane->status != aAp_STATUS_PLAYER_CATCH &&
airplane->wind != NULL
) {
sMath_RotateX(&dir, DEG2RAD(airplane->rotX));
sMath_RotateZ(&dir, DEG2RAD(airplane->rotZ));
sMath_RotateY(&dir, DEG2RAD(airplane->rotY));
}
}
static void aAp_CommonHandle(ACTOR* actor, AIRPLANE_ACTOR* airplane, GAME* game) {
aAp_LeanAirplane(airplane);
actor->speed = airplane->speed * cosf_table(DEG2RAD(airplane->rotX));
airplane->y_speed = airplane->speed * sinf_table(DEG2RAD(airplane->rotX));
actor->world_position.y -= airplane->y_speed;
actor->world_rotation.y = RAD2SHORTANGLE(DEG2RAD(airplane->rotY));
actor->shape_info.rotation.y = RAD2SHORTANGLE(DEG2RAD(airplane->rotY));
Actor_position_moveF(actor);
airplane->joystick_x = getJoystick_X();
airplane->joystick_y = getJoystick_Y();
switch (airplane->status) {
case aAp_STATUS_START_FLY_MOVE:
case aAp_STATUS_PLAYER_CATCH:
{
actor->shape_info.draw_shadow = FALSE;
break;
}
case aAp_STATUS_FREE_FLY_MOVE:
case aAp_STATUS_FALL_FLY_MOVE:
case aAp_STATUS_FALL_FLY_MOVE2:
case aAp_STATUS_SOMER_FLY_MOVE:
{
aAp_RubberMove(&airplane->rotY, airplane->rotY_goal, 0.07f);
actor->shape_info.draw_shadow = TRUE;
break;
}
default:
{
actor->shape_info.draw_shadow = TRUE;
break;
}
}
aAp_WindSystem(actor, game);
}
static void aAp_ZbuttonChangeStatus(AIRPLANE_ACTOR* actor, GAME* game) {
GAME_PLAY* play = (GAME_PLAY*)game;
if (chkButton(BUTTON_Z)) {
if (actor->status == aAp_STATUS_PLAYER_CATCH) {
mPlib_request_main_refuse_type1(play);
actor->status = aAp_STATUS_START_FLY_MOVE;
}
}
else if (actor->status == aAp_STATUS_START_FLY_MOVE) {
mPlib_request_main_wait_type3(play);
actor->status = aAp_STATUS_PLAYER_CATCH;
}
}
static f32 aAp_GetBgCheckOffsetY(s16 status) {
if (status == aAp_STATUS_FALL_FLY_MOVE || status == aAp_STATUS_STOP_FLY_MOVE) {
return -5.5f;
}
return 0.0f;
}
typedef void (*AIRPLANE_ACTOR_MOVE_PROC)(ACTOR*, GAME*);
static void Airplane_Actor_move(ACTOR* actor, GAME* game) {
static AIRPLANE_ACTOR_MOVE_PROC AirplaneMove[aAp_STATUS_NUM] = {
&aAp_FreeFlyMove,
&aAp_FallFlyMove,
&aAp_FallFlyMove2,
&aAp_SomerFlyMove,
&aAp_StartFlyMove,
&aAp_StopFlyMove,
&aAp_PlayerCatch
};
AIRPLANE_ACTOR* airplane = (AIRPLANE_ACTOR*)actor;
f32 offset_y;
airplane->rotY_min = airplane->rotY;
(*AirplaneMove[airplane->status])(actor, game);
aAp_ZbuttonChangeStatus(airplane, game);
aAp_CommonHandle(actor, airplane, game);
offset_y = aAp_GetBgCheckOffsetY(airplane->status);
mCoBG_BgCheckControll(NULL, actor, 15.0f, offset_y, FALSE, FALSE, 0);
}