Implement & link ac_fuusen

This commit is contained in:
Cuyler36
2023-12-11 02:41:03 -05:00
parent 6373168c48
commit eb91519829
8 changed files with 649 additions and 4 deletions
+4
View File
@@ -516,6 +516,10 @@ m_random_field_ovl.c:
.rodata: [0x80648ED0, 0x80648ED8]
.data: [0x8069E918, 0x8069F070]
.bss: [0x813010D0, 0x813013E0]
ac_fuusen.c:
.text: [0x8050DAC4, 0x8050F06C]
.rodata: [0x80648FE8, 0x80649098]
.data: [0x8069F190, 0x8069F320]
m_mail_check_ovl.c:
.text: [0x8050F06C, 0x8050F838]
.data: [0x8069F320, 0x8069FA40]
+36
View File
@@ -3,11 +3,47 @@
#include "types.h"
#include "m_actor.h"
#include "c_keyframe.h"
#ifdef __cplusplus
extern "C" {
#endif
#define aFSN_ESCAPE_TIMER 1554
enum {
aFSN_ACTION_BIRTH,
aFSN_ACTION_MOVING,
aFSN_ACTION_WOOD_STOP,
aFSN_ACTION_ESCAPE,
aFSN_ACTION_NUM
};
typedef struct fuusen_actor_s FUUSEN_ACTOR;
struct fuusen_actor_s {
ACTOR actor_class;
int action;
mActor_proc action_proc;
char* segment_p;
int type_idx;
int escape_timer;
int timer;
int count;
int look_up_flag;
int wind_idx;
s16 fuwafuwa_cycle;
f32 wind_power;
f32 y_offset;
u8 wind_change_flag;
cKF_SkeletonInfo_R_c keyframe;
s_xyz work[5];
s_xyz morph[5];
int _254;
Mtx mtx[2][3];
};
extern ACTOR_PROFILE Fuusen_Profile;
#ifdef __cplusplus
+9 -1
View File
@@ -19,10 +19,18 @@ typedef struct background_item_shadow_s {
typedef void (*bIT_SHADOW_DRAW_PROC)(GAME*, bIT_ShadowData_c*, int);
typedef int (*bIT_FRUIT_SET_PROC)(mActor_name_t item, int ut_x, int ut_z, s16 p0, s16 p1);
typedef void (*bIT_ITEM_TREE_FRUIT_DROP_PROC)(mActor_name_t item, int ut_x, int ut_z, xyz_t* pos);
typedef struct background_item_clip_s {
void* _00;
bIT_SHADOW_DRAW_PROC draw_shadow_proc;
void* _08[(0x54 - 0x08) / sizeof(void*)];
void* _08[(0x30 - 0x08) / sizeof(void*)];
bIT_FRUIT_SET_PROC fruit_set_proc;
void* _34;
bIT_ITEM_TREE_FRUIT_DROP_PROC item_tree_fruit_drop_proc;
void* _3C[(0x54 - 0x3C) / sizeof(void*)];
} bIT_Clip_c;
#ifdef __cplusplus
+1 -1
View File
@@ -439,7 +439,7 @@ typedef enum bank_id {
ACTOR_OBJ_BANK_397,
ACTOR_OBJ_BANK_398,
ACTOR_OBJ_BANK_399,
ACTOR_OBJ_BANK_400,
ACTOR_OBJ_BANK_FUUSEN,
ACTOR_OBJ_BANK_401,
ACTOR_OBJ_BANK_402,
ACTOR_OBJ_BANK_403,
+1
View File
@@ -259,6 +259,7 @@ extern int mCoBG_Attr2CheckPlaceNpc(u32 attribute);
extern int mCoBG_ExistHeightGap_KeepAndNow(xyz_t wpos);
extern void mCoBG_GetNorm_By3Point(xyz_t* norm, xyz_t* p0, xyz_t* p1, xyz_t* p2);
extern int mCoBG_SearchWaterLimitDistN(xyz_t* water_pos, xyz_t wpos, s16 angle, float max_dist, int divisor);
extern f32 mCoBG_GetBalloonGroundY(const xyz_t* pos);
extern void mCoBG_InitMoveBgData();
extern void mCoBG_InitBlockBgCheckMode();
+1 -2
View File
@@ -15,8 +15,7 @@ struct debug_display_s{
Debug_display* next;
};
extern void Debug_Display_init();
extern Debug_display* Debug_Display_new(f32 posX, f32 posY, f32 posZ, f32 scaleX, f32 scaleY, f32 scaleZ,
s16 rotX, s16 rotY, s16 rotZ, s8 r, s8 g, s8 b, s8 alpha, s16 type, GRAPH* graph);
extern Debug_display* Debug_Display_new(f32 posX, f32 posY, f32 posZ, f32 scaleX, f32 scaleY, f32 scaleZ, s16 rotX, s16 rotY, s16 rotZ, u8 r, u8 g, u8 b, u8 alpha, s16 type, GRAPH* graph);
extern void Debug_Display_output(GAME_PLAY* play);
+2
View File
@@ -46,6 +46,8 @@ extern int mPlib_able_submenu_type1(GAME* game);
extern void mPlib_request_main_demo_wait_from_submenu(ACTOR* force_speak_label);
extern void mPlib_Load_PlayerTexAndPallet(void* tex_p, void* pal_p, int idx);
extern void mPlib_request_main_give_from_submenu(mActor_name_t disp_item, int submenu_ovl, int present_flag, int counter_flag);
extern int mPlib_Check_tree_shaken_big(const xyz_t* pos);
extern int mPlib_Check_tree_shaken_little(const xyz_t* pos);
extern mPlayer_change_data_from_submenu_c* mPlib_Get_change_data_from_submenu_p();
+595
View File
@@ -0,0 +1,595 @@
#include "ac_fuusen.h"
#include "m_actor_shadow.h"
#include "m_common_data.h"
#include "m_debug_display.h"
#include "m_fuusen.h"
#include "m_play.h"
#include "m_player_lib.h"
#include "m_rcp.h"
#include "sys_matrix.h"
#include "zurumode.h"
static void aFSN_actor_ct(ACTOR* actorx, GAME* game);
static void aFSN_actor_dt(ACTOR* actorx, GAME* game);
static void aFSN_actor_move(ACTOR* actorx, GAME* game);
static void aFSN_actor_draw(ACTOR* actorx, GAME* game);
ACTOR_PROFILE Fuusen_Profile = {
mAc_PROFILE_FUUSEN,
ACTOR_PART_CONTROL,
ACTOR_STATE_NO_MOVE_WHILE_CULLED,
EMPTY_NO,
ACTOR_OBJ_BANK_FUUSEN,
sizeof(FUUSEN_ACTOR),
&aFSN_actor_ct,
&aFSN_actor_dt,
&aFSN_actor_move,
&aFSN_actor_draw,
NULL
};
static void aFSN_setupAction(FUUSEN_ACTOR* fuusen_actor, GAME* game, int action);
extern cKF_Skeleton_R_c cKF_bs_r_act_balloon;
extern cKF_Animation_R_c cKF_ba_r_act_balloon;
static void aFSN_actor_ct(ACTOR* actorx, GAME* game) {
FUUSEN_ACTOR* fuusen = (FUUSEN_ACTOR*)actorx;
cKF_SkeletonInfo_R_c* keyframe_p = &fuusen->keyframe;
static xyz_t Init_Size = { 0.01f, 0.01f, 0.01f };
f32 balloon_ground_y = mCoBG_GetBalloonGroundY(&actorx->world.position);
fuusen->escape_timer = 2000;
cKF_SkeletonInfo_R_ct(keyframe_p, &cKF_bs_r_act_balloon, &cKF_ba_r_act_balloon, fuusen->work, fuusen->morph);
cKF_SkeletonInfo_R_init_standard_repeat(keyframe_p, &cKF_ba_r_act_balloon, NULL);
Shape_Info_init(actorx, 0.0f, &mAc_ActorShadowCircle, 10.0f, 10.0f);
actorx->shape_info.draw_shadow = FALSE;
cKF_SkeletonInfo_R_play(keyframe_p);
keyframe_p->frame_control.speed = 1.0f;
xyz_t_move(&actorx->scale, &Init_Size);
actorx->world.position.y = balloon_ground_y + 200.0f;
fuusen->y_offset = 110.0f;
fuusen->segment_p = ((GAME_PLAY*)game)->object_exchange.banks[actorx->data_bank_id].ram_start;
aFSN_setupAction(fuusen, game, aFSN_ACTION_BIRTH);
}
static void aFSN_actor_dt(ACTOR* actorx, GAME* game) {
FUUSEN_ACTOR* fuusen = (FUUSEN_ACTOR*)actorx;
if (fuusen->look_up_flag == TRUE) {
Balloon_look_up();
}
else {
Balloon_kill();
}
}
static void aFSN_birth(ACTOR* actorx, GAME* game) {
FUUSEN_ACTOR* fuusen = (FUUSEN_ACTOR*)actorx;
aFSN_setupAction(fuusen, game, aFSN_ACTION_MOVING);
}
static void aFSN_moving(ACTOR* actorx, GAME* game) {
FUUSEN_ACTOR* fuusen = (FUUSEN_ACTOR*)actorx;
GAME_PLAY* play = (GAME_PLAY*)game;
f32 balloon_y = mCoBG_GetBalloonGroundY(&actorx->world.position) + fuusen->y_offset;
xyz_t screen_pos;
mActor_name_t* fg_item_p;
if (fuusen->escape_timer > 0) {
fuusen->escape_timer--;
}
else {
/* Escape if flown to the edge of the map */
if (
(actorx->world.position.x <= 660.0f || actorx->world.position.x >= 3820.0f) ||
(actorx->world.position.z <= 660.0f || actorx->world.position.z >= 4460.0f)
) {
fuusen->escape_timer = aFSN_ESCAPE_TIMER;
aFSN_setupAction(fuusen, game, aFSN_ACTION_ESCAPE);
return;
}
/* Escape if flown into the train station acre? */
if (
(actorx->world.position.x <= 2440.0f && actorx->world.position.x >= 2040.0f) &&
(actorx->world.position.z <= 960.0f && actorx->world.position.z >= 800.0f)
) {
fuusen->escape_timer = aFSN_ESCAPE_TIMER;
aFSN_setupAction(fuusen, game, aFSN_ACTION_ESCAPE);
return;
}
}
fuusen->wind_power = mEnv_GetWindPowerF();
actorx->speed = fuusen->wind_power * 0.5f + 1.0f;
fuusen->fuwafuwa_cycle += 250;
add_calc(
&actorx->world.position.y,
balloon_y + sin_s(fuusen->fuwafuwa_cycle) * 10.0f,
1.0f - sqrtf(0.7f),
0.5f, 0.0f
);
Game_play_Projection_Trans(play, &actorx->world.position, &screen_pos);
if (-40.0f > screen_pos.x || screen_pos.x > 360.0f || -40.0f > screen_pos.y || screen_pos.y > 280.0f) {
return;
}
mCoBG_BgCheckControll(NULL, actorx, 12.0f, 0.0f, 0, 0, 0);
if (
(actorx->bg_collision_check.result.hit_wall & mCoBG_HIT_WALL) ||
(actorx->bg_collision_check.result.hit_attribute_wall & mCoBG_HIT_WALL)
) {
fuusen->y_offset += 0.05f; // raise quickly over walls
if (fuusen->y_offset >= 300.0f) {
fuusen->y_offset = 300.0f;
}
}
else if (fuusen->y_offset > 110.0f) {
fuusen->y_offset -= 0.005f; // slowly fall
}
fg_item_p = mFI_GetUnitFG(actorx->world.position);
if (
fg_item_p != NULL &&
(
*fg_item_p == TREE ||
*fg_item_p == TREE_APPLE_NOFRUIT_0 ||
*fg_item_p == TREE_APPLE_NOFRUIT_1 ||
*fg_item_p == TREE_APPLE_NOFRUIT_2 ||
*fg_item_p == TREE_ORANGE_NOFRUIT_0 ||
*fg_item_p == TREE_ORANGE_NOFRUIT_1 ||
*fg_item_p == TREE_ORANGE_NOFRUIT_2 ||
*fg_item_p == TREE_PEACH_NOFRUIT_0 ||
*fg_item_p == TREE_PEACH_NOFRUIT_1 ||
*fg_item_p == TREE_PEACH_NOFRUIT_2 ||
*fg_item_p == TREE_PEAR_NOFRUIT_0 ||
*fg_item_p == TREE_PEAR_NOFRUIT_1 ||
*fg_item_p == TREE_PEAR_NOFRUIT_2 ||
*fg_item_p == TREE_CHERRY_NOFRUIT_0 ||
*fg_item_p == TREE_CHERRY_NOFRUIT_1 ||
*fg_item_p == TREE_CHERRY_NOFRUIT_2 ||
*fg_item_p == TREE_PALM_NOFRUIT_0 ||
*fg_item_p == TREE_PALM_NOFRUIT_1 ||
*fg_item_p == TREE_PALM_NOFRUIT_2 ||
*fg_item_p == CEDAR_TREE ||
*fg_item_p == GOLD_TREE
)
) {
f32 dx;
f32 dy;
f32 dz;
mFI_Wpos2UtCenterWpos(&screen_pos, actorx->world.position);
if (*fg_item_p == CEDAR_TREE) {
screen_pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(actorx->world.position, 0.0f) + 100.0f;
screen_pos.z += 20.0f;
}
else {
screen_pos.x -= 2.5f;
screen_pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(actorx->world.position, 0.0f) + 97.5f;
screen_pos.z += 7.5f;
}
dx = screen_pos.x - actorx->world.position.x;
dy = screen_pos.y - actorx->world.position.y;
dz = screen_pos.z - actorx->world.position.z;
if (*fg_item_p == CEDAR_TREE) {
if (dx * dx + dz * dz < 484.0f && dy * dy < 225.0f) {
aFSN_setupAction(fuusen, game, aFSN_ACTION_WOOD_STOP);
}
}
else if (dx * dx + dz * dz < 225.0f && dy * dy < 225.0f) {
aFSN_setupAction(fuusen, game, aFSN_ACTION_WOOD_STOP);
}
}
else {
if (fuusen->wind_change_flag == FALSE) {
static int senkou_check_data[] = { -2500, 0, 2500 };
s16 new_angle;
int i;
for (i = 0; i < ARRAY_COUNT(senkou_check_data); i++) {
xyz_t_move(&screen_pos, &actorx->world.position);
new_angle = (int)actorx->world.angle.y + (s16)senkou_check_data[i];
screen_pos.x += 80.0f * sin_s(new_angle);
screen_pos.z += 80.0f * cos_s(new_angle);
fg_item_p = mFI_GetUnitFG(screen_pos);
if (
fg_item_p != NULL &&
(
*fg_item_p == TREE ||
*fg_item_p == TREE_APPLE_NOFRUIT_0 ||
*fg_item_p == TREE_APPLE_NOFRUIT_1 ||
*fg_item_p == TREE_APPLE_NOFRUIT_2 ||
*fg_item_p == TREE_ORANGE_NOFRUIT_0 ||
*fg_item_p == TREE_ORANGE_NOFRUIT_1 ||
*fg_item_p == TREE_ORANGE_NOFRUIT_2 ||
*fg_item_p == TREE_PEACH_NOFRUIT_0 ||
*fg_item_p == TREE_PEACH_NOFRUIT_1 ||
*fg_item_p == TREE_PEACH_NOFRUIT_2 ||
*fg_item_p == TREE_PEAR_NOFRUIT_0 ||
*fg_item_p == TREE_PEAR_NOFRUIT_1 ||
*fg_item_p == TREE_PEAR_NOFRUIT_2 ||
*fg_item_p == TREE_CHERRY_NOFRUIT_0 ||
*fg_item_p == TREE_CHERRY_NOFRUIT_1 ||
*fg_item_p == TREE_CHERRY_NOFRUIT_2 ||
*fg_item_p == TREE_PALM_NOFRUIT_0 ||
*fg_item_p == TREE_PALM_NOFRUIT_1 ||
*fg_item_p == TREE_PALM_NOFRUIT_2 ||
*fg_item_p == CEDAR_TREE ||
*fg_item_p == GOLD_TREE
)
) {
actorx->world.angle.y = new_angle;
fuusen->wind_change_flag = TRUE;
break;
}
}
}
if (fuusen->wind_change_flag == FALSE) {
actorx->world.angle.y = mEnv_GetWindAngleS();
}
}
}
static void aFSN_wood_stop(ACTOR* actorx, GAME* game) {
FUUSEN_ACTOR* fuusen = (FUUSEN_ACTOR*)actorx;
fuusen->escape_timer--;
if (fuusen->escape_timer <= aFSN_ESCAPE_TIMER) {
fuusen->escape_timer = aFSN_ESCAPE_TIMER;
aFSN_setupAction(fuusen, game, aFSN_ACTION_ESCAPE);
}
else {
xyz_t pos;
xyz_t pos2;
mActor_name_t* fg_item_p;
f32 dx;
f32 dz;
mFI_Wpos2UtCenterWpos(&pos, actorx->world.position);
xyz_t_move(&pos2, &pos);
fg_item_p = mFI_GetUnitFG(actorx->world.position);
if (fg_item_p != NULL && *fg_item_p == CEDAR_TREE) {
pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(actorx->world.position, 0.0f) + 100.0f;
pos.z += 20.0f;
}
else {
pos.x -= 2.5f;
pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(actorx->world.position, 0.0f) + 97.5f;
pos.z += 7.5f;
}
dx = actorx->world.position.x - pos.x;
dz = actorx->world.position.z - pos.z;
if (sqrtf(dx * dx + dz * dz) > 2.0f) {
add_calc(&actorx->world.position.x, pos.x, 1.0f - sqrtf(0.7f), 0.5f, 0.0f);
add_calc(&actorx->world.position.y, pos.y, 1.0f - sqrtf(0.7f), 0.5f, 0.0f);
add_calc(&actorx->world.position.z, pos.z, 1.0f - sqrtf(0.7f), 0.5f, 0.0f);
}
else if (mPlib_Check_tree_shaken_big(&pos2)) {
actorx->shape_info.rotation.z = 0;
aFSN_setupAction(fuusen, game, aFSN_ACTION_ESCAPE);
}
else if (mPlib_Check_tree_shaken_little(&pos2)) {
if ((fuusen->count & 4) == 0) {
actorx->shape_info.rotation.z = 500;
}
else {
actorx->shape_info.rotation.z = -500;
actorx->shape_info.rotation.z = 0; // set again???
}
fuusen->count++;
}
else {
actorx->shape_info.rotation.z = 0;
fuusen->count = 0;
}
}
}
static void aFSN_escape(ACTOR* actorx, GAME* game) {
FUUSEN_ACTOR* fuusen = (FUUSEN_ACTOR*)actorx;
f32 balloon_y = mCoBG_GetBalloonGroundY(&actorx->world.position);
if (fuusen->count == 0) {
xyz_t pos;
mFI_Wpos2UtCenterWpos(&pos, actorx->world.position);
if (Common_Get(clip).bg_item_clip != NULL && Common_Get(clip).bg_item_clip->item_tree_fruit_drop_proc != NULL) {
int ut_x;
int ut_z;
if (mFI_Wpos2UtNum(&ut_x, &ut_z, pos)) {
(*Common_Get(clip).bg_item_clip->fruit_set_proc)(ITM_PRESENT, ut_x, ut_z, 1, 1);
fuusen->count = 1;
}
}
}
if (fuusen->count == 1 && actorx->world.position.y > balloon_y + 500.0f) {
Actor_delete(actorx);
}
}
static void aFSN_birth_init(FUUSEN_ACTOR* fuusen, GAME* game) {
static int data_index_data[16] = {
0, 1, 1, 2,
2, 3, 3, 4,
4, 5, 5, 6,
6, 7, 7, 0
};
static xyz_t birth_pos_data[8] = {
{ 1600.0f, 100.0f, 500.0f }, /* X:2.5, Z:0.8 - Acre Q-2 (above A-2) */
{ 500.0f, 100.0f, 500.0f }, /* X:0.8, Z:0.8 - Acre Q-0 (top-left corner acre) */
{ 500.0f, 100.0f, 1600.0f }, /* X:0.8, Z:2.5 - Acre B-0 (left of B-1) */
{ 500.0f, 100.0f, 4620.0f }, /* X:0.8, Z:7.2 - Acre G-0 (bottom-left corner acre)*/
{ 1600.0f, 100.0f, 4620.0f }, /* X:2.5, Z:7.2 - Acre G-2 (below F-2)*/
{ 3980.0f, 100.0f, 4620.0f }, /* X:6.2, Z:7.2 - Acre F-6 (bottom-right corner) */
{ 3980.0f, 100.0f, 1600.0f }, /* X:6.2, Z:2.5 - Acre B-6 (right of B-5) */
{ 3980.0f, 100.0f, 500.0f } /* X:6.2, Z:0.8 - Acre Q-6 (top-right corner)*/
};
static xyz_t birth_pos_random_data[8] = {
{ 1280.0f, 100.0f, 0.0f },
{ 960.0f, 100.0f, 960.0f },
{ 0.0f, 100.0f, 1920.0f },
{ 960.0f, 100.0f, -960.0f },
{ 1280.0f, 100.0f, 0.0f },
{ -960.0f, 100.0f, -960.0f },
{ 0.0f, 100.0f, 1920.0f },
{ -960.0f, 100.0f, 960.0f }
};
GAME_PLAY* play = (GAME_PLAY*)game;
f32 balloon_y = mCoBG_GetBalloonGroundY(&fuusen->actor_class.world.position);
int randomize_z;
fuusen->actor_class.world.angle.y = mEnv_GetWindAngleS();
fuusen->wind_idx = ((s16)(fuusen->actor_class.world.angle.y & 0xF000)) >> 12;
fuusen->wind_idx &= 0xF;
fuusen->wind_idx = data_index_data[fuusen->wind_idx];
xyz_t_move(&fuusen->actor_class.world.position, &birth_pos_data[fuusen->wind_idx]);
randomize_z = FALSE;
fuusen->actor_class.world.position.y = balloon_y + 200.0f;
fuusen->type_idx = play->game_frame % 5;
fuusen->timer = 10;
if (birth_pos_random_data[fuusen->wind_idx].x != 0.0f && birth_pos_random_data[fuusen->wind_idx].z != 0.0f) {
randomize_z = play->game_frame & 1; // randomly choose between X & Z
}
else if (birth_pos_random_data[fuusen->wind_idx].z != 0.0f) {
randomize_z = TRUE; // only Z can be randomized
}
if (randomize_z == FALSE) {
/* Adjust X position */
if (birth_pos_random_data[fuusen->wind_idx].x != 0.0f) {
f32 rng = fqrand() * fabsf(birth_pos_random_data[fuusen->wind_idx].x);
if (birth_pos_random_data[fuusen->wind_idx].x > 0.0f) {
fuusen->actor_class.world.position.x += rng;
}
else {
fuusen->actor_class.world.position.x -= rng;
}
}
}
else {
/* Adjust Z position */
if (birth_pos_random_data[fuusen->wind_idx].z != 0.0f) {
f32 rng = fqrand() * fabsf(birth_pos_random_data[fuusen->wind_idx].z);
if (birth_pos_random_data[fuusen->wind_idx].z > 0.0f) {
fuusen->actor_class.world.position.z += rng;
}
else {
fuusen->actor_class.world.position.z -= rng;
}
}
}
}
static void aFSN_moving_init(FUUSEN_ACTOR* fuusen, GAME* game) {
fuusen->wind_change_flag = FALSE;
}
static void aFSN_wood_stop_init(FUUSEN_ACTOR* fuusen, GAME* game) {
fuusen->actor_class.speed = 0.0f;
fuusen->escape_timer = 18000 + aFSN_ESCAPE_TIMER;
sAdo_OngenTrgStart(0x402, &fuusen->actor_class.world.position);
}
static void aFSN_escape_init(FUUSEN_ACTOR* fuusen, GAME* game) {
PLAYER_ACTOR* player = GET_PLAYER_ACTOR((GAME_PLAY*)game);
ACTOR* actorx = (ACTOR*)fuusen;
f32 dx = player->actor_class.world.position.x - actorx->world.position.x;
f32 dz = player->actor_class.world.position.z - actorx->world.position.z;
fuusen->count = 0;
actorx->max_velocity_y = 5.0f;
actorx->gravity = 0.5f;
fuusen->look_up_flag = FALSE;
if (fuusen->escape_timer == aFSN_ESCAPE_TIMER) {
fuusen->count = 1;
/* If the balloon is within 1 acre of distance to the player when it flies away, the 'look up flag' is set */
if (sqrtf(dx * dx + dz * dz) < (mFI_UNIT_BASE_SIZE_F * UT_BASE_NUM)) {
fuusen->look_up_flag = TRUE;
}
}
}
typedef void (*aFSN_INIT_PROC)(FUUSEN_ACTOR*, GAME*);
static void aFSN_setupAction(FUUSEN_ACTOR* fuusen, GAME* game, int action) {
static aFSN_INIT_PROC init_proc[aFSN_ACTION_NUM] = {
&aFSN_birth_init,
&aFSN_moving_init,
&aFSN_wood_stop_init,
&aFSN_escape_init
};
static mActor_proc act_proc[aFSN_ACTION_NUM] = {
&aFSN_birth,
&aFSN_moving,
&aFSN_wood_stop,
&aFSN_escape
};
fuusen->action = action;
fuusen->action_proc = act_proc[action];
(*init_proc[action])(fuusen, game);
}
static void aFSN_actor_move(ACTOR* actorx, GAME* game) {
FUUSEN_ACTOR* fuusen = (FUUSEN_ACTOR*)actorx;
cKF_SkeletonInfo_R_c* keyframe_p = &fuusen->keyframe;
if (fuusen->timer == 0) {
Actor_position_moveF(actorx);
}
else if (fuusen->timer > 0) {
fuusen->timer--;
}
if (fuusen_DEBUG_mode_flag != FALSE && zurumode_flag != 0) {
PLAYER_ACTOR* player = GET_PLAYER_ACTOR((GAME_PLAY*)game);
int rot_y = (int)actorx->player_angle_y - (s16)-0x8000;
Debug_Display_new(
player->actor_class.world.position.x + sin_s(actorx->player_angle_y - (s16)-0x8000) * 30.0f,
player->actor_class.world.position.y + 60.0f,
player->actor_class.world.position.z + cos_s(actorx->player_angle_y - (s16)-0x8000) * 30.0f,
1.0f, 1.0f, 1.0f,
0, rot_y, 0,
250, 100, 120, 128,
4,
game->graph
);
}
cKF_SkeletonInfo_R_play(keyframe_p);
(*fuusen->action_proc)(actorx, game);
}
static int aFSN_actor_draw_before(GAME* game, cKF_SkeletonInfo_R_c* keyframe, int joint_num, Gfx** gfx_pp, u8* data_p, void* arg, s_xyz* joint_p, xyz_t* pos_p) {
static rgba_t balloon_prim_data[] = {
{ 255, 210, 200, 255 },
{ 200, 230, 200, 255 },
{ 255, 250, 200, 255 },
{ 220, 255, 200, 255 },
{ 240, 210, 255, 255 }
};
static rgba_t balloon_env_data[] = {
{ 255, 40, 0, 255 },
{ 0, 180, 255, 255 },
{ 255, 200, 0, 255 },
{ 100, 255, 0, 255 },
{ 200, 30, 255, 255 }
};
FUUSEN_ACTOR* fuusen = (FUUSEN_ACTOR*)arg;
GRAPH* graph = game->graph;
Gfx* gfx;
if (joint_num == 3) {
OPEN_DISP(graph);
gfx = NOW_POLY_OPA_DISP;
gDPSetPrimColor(gfx++, 0, 255, balloon_prim_data[fuusen->type_idx].r, balloon_prim_data[fuusen->type_idx].g, balloon_prim_data[fuusen->type_idx].b, balloon_prim_data[fuusen->type_idx].a);
gDPSetEnvColor(gfx++, balloon_env_data[fuusen->type_idx].r, balloon_env_data[fuusen->type_idx].g, balloon_env_data[fuusen->type_idx].b, balloon_env_data[fuusen->type_idx].a);
SET_POLY_OPA_DISP(gfx);
CLOSE_DISP(graph);
}
OPEN_DISP(graph);
gfx = NOW_POLY_OPA_DISP;
if (joint_num != 3) {
gDPSetTexEdgeAlpha(gfx++, 80);
}
else {
gDPSetTexEdgeAlpha(gfx++, 144);
}
SET_POLY_OPA_DISP(gfx);
CLOSE_DISP(graph);
return TRUE;
}
extern Gfx present_DL_mode[];
extern Gfx present_DL_vtx[];
static void aFSN_actor_draw(ACTOR* actorx, GAME* game) {
static xyz_t offset0 = { 0.0f, 0.0f, 0.0f };
FUUSEN_ACTOR* fuusen = (FUUSEN_ACTOR*)actorx;
Mtx* mtx = fuusen->mtx[game->frame_counter & 1];
GAME_PLAY* play = (GAME_PLAY*)game;
GRAPH* graph = game->graph;
Gfx* gfx;
if (
Camera2_CheckCullingMode() == FALSE ||
Camera2_CheckEnterCullingArea(actorx->world.position.x, actorx->world.position.z, 60.0f) == FALSE
) {
Matrix_push();
if (fuusen->action != aFSN_ACTION_ESCAPE || fuusen->escape_timer == aFSN_ESCAPE_TIMER || (fuusen->action == aFSN_ACTION_ESCAPE && fuusen->count == 0)) {
/* Draw present */
Matrix_translate(actorx->world.position.x, actorx->world.position.y, actorx->world.position.z, 0);
Matrix_scale(0.01f, 0.01f, 0.01f, 1);
Matrix_RotateX(actorx->shape_info.rotation.x, 1);
Matrix_RotateZ(actorx->shape_info.rotation.z, 1);
Matrix_RotateY(actorx->shape_info.rotation.y, 1);
_texture_z_light_fog_prim(graph);
OPEN_DISP(graph);
gfx = NOW_POLY_OPA_DISP;
gSPMatrix(gfx++, _Matrix_to_Mtx_new(graph), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(gfx++, present_DL_mode);
gSPDisplayList(gfx++, present_DL_vtx);
SET_POLY_OPA_DISP(gfx);
CLOSE_DISP(graph);
}
Setpos_HiliteReflect_init(&actorx->world.position, (GAME_PLAY*)game);
cKF_Si3_draw_R_SV(game, &fuusen->keyframe, mtx, &aFSN_actor_draw_before, NULL, actorx);
OPEN_DISP(graph);
gfx = NOW_POLY_OPA_DISP;
gDPSetTexEdgeAlpha(gfx++, 144);
SET_POLY_OPA_DISP(gfx);
CLOSE_DISP(graph);
mAc_ActorShadowDraw_ShadowDrawFlagOn(actorx, play, 0, offset0, 170.0f);
Matrix_pull();
}
}