summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorinspectredc <78732756+inspectredc@users.noreply.github.com>2024-04-16 20:31:29 +0100
committerGitHub <noreply@github.com>2024-04-16 12:31:29 -0700
commite6ea51bc3dcf69310c5dcdae5b812dc74e628aaf (patch)
tree406fc1756035e49f5c5252058b949ba5809e9833 /src
parent7f426967efd07046bfbe791ed4e64808ae5a26e2 (diff)
ac_Fuusen OK and documented (#174)
* ac_Fuusen OK and documented * add struct offsets * use null post merge * fix sym stuff * suggestions * act_balloon extracted * remove fake symbol * name object enum * include assets * fgname enum/macro
Diffstat (limited to 'src')
-rw-r--r--src/code/m_field_info.c4
-rw-r--r--src/objects/act_balloon/act_balloon.c19
-rw-r--r--src/objects/act_balloon/act_balloon.h21
-rw-r--r--src/overlays/actors/ovl_Fuusen/ac_fuusen.c452
-rw-r--r--src/overlays/actors/ovl_Fuusen/ac_fuusen.h34
-rw-r--r--src/overlays/gamestates/ovl_play/m_play.h2
6 files changed, 509 insertions, 23 deletions
diff --git a/src/code/m_field_info.c b/src/code/m_field_info.c
index e48824d..c54b60a 100644
--- a/src/code/m_field_info.c
+++ b/src/code/m_field_info.c
@@ -41,11 +41,11 @@
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_80088320_jp.s")
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_80088344_jp.s")
+#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/mFI_Wpos2UtNum.s")
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_80088458_jp.s")
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_800884E0_jp.s")
+#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/mFI_Wpos2UtCenterWpos.s")
#pragma GLOBAL_ASM("asm/jp/nonmatchings/code/m_field_info/func_800885A8_jp.s")
diff --git a/src/objects/act_balloon/act_balloon.c b/src/objects/act_balloon/act_balloon.c
new file mode 100644
index 0000000..3a7e46d
--- /dev/null
+++ b/src/objects/act_balloon/act_balloon.c
@@ -0,0 +1,19 @@
+#include "act_balloon.h"
+
+#include "assets/jp/objects/act_balloon/act_balloon_v.vtx.inc.c"
+#include "assets/jp/objects/act_balloon/act_balloon_head_model.gfx.inc.c"
+#include "assets/jp/objects/act_balloon/act_balloon_wireB_model.gfx.inc.c"
+#include "assets/jp/objects/act_balloon/act_balloon_wireA_model.gfx.inc.c"
+u8 act_balloon_wire_tex_txt[] = {
+#include "assets/jp/objects/act_balloon/act_balloon_wire_tex_txt.i4.inc.c"
+};
+u16 act_balloon_head_tex_rgb_ia16[] = {
+#include "assets/jp/objects/act_balloon/act_balloon_head_tex_rgb_ia16.ia16.inc.c"
+};
+#include "assets/jp/objects/act_balloon/cKF_ckcb_r_act_balloon_tbl.inc.c"
+#include "assets/jp/objects/act_balloon/cKF_kn_act_balloon_tbl.inc.c"
+#include "assets/jp/objects/act_balloon/cKF_c_act_balloon_tbl.inc.c"
+#include "assets/jp/objects/act_balloon/cKF_ds_act_balloon_tbl.inc.c"
+#include "assets/jp/objects/act_balloon/cKF_ba_r_act_balloon.inc.c"
+#include "assets/jp/objects/act_balloon/cKF_je_r_act_balloon_tbl.inc.c"
+#include "assets/jp/objects/act_balloon/cKF_bs_r_act_balloon.inc.c"
diff --git a/src/objects/act_balloon/act_balloon.h b/src/objects/act_balloon/act_balloon.h
new file mode 100644
index 0000000..a3ff00b
--- /dev/null
+++ b/src/objects/act_balloon/act_balloon.h
@@ -0,0 +1,21 @@
+#ifndef OBJECT_ACT_BALLOON_H
+#define OBJECT_ACT_BALLOON_H
+
+#include "gbi.h"
+#include "c_keyframe.h"
+
+extern Vtx act_balloon_v[];
+extern Gfx act_balloon_head_model[];
+extern Gfx act_balloon_wireB_model[];
+extern Gfx act_balloon_wireA_model[];
+extern u8 act_balloon_wire_tex_txt[];
+extern u16 act_balloon_head_tex_rgb_ia16[];
+extern u8 cKF_ckcb_r_act_balloon_tbl[];
+extern s16 cKF_kn_act_balloon_tbl[];
+extern s16 cKF_c_act_balloon_tbl[];
+extern Keyframe cKF_ds_act_balloon_tbl[];
+extern BaseAnimationR cKF_ba_r_act_balloon;
+extern JointElemR cKF_je_r_act_balloon_tbl[];
+extern BaseSkeletonR cKF_bs_r_act_balloon;
+
+#endif
diff --git a/src/overlays/actors/ovl_Fuusen/ac_fuusen.c b/src/overlays/actors/ovl_Fuusen/ac_fuusen.c
index ff4c632..16c8424 100644
--- a/src/overlays/actors/ovl_Fuusen/ac_fuusen.c
+++ b/src/overlays/actors/ovl_Fuusen/ac_fuusen.c
@@ -1,20 +1,37 @@
#include "ac_fuusen.h"
#include "m_actor_dlftbls.h"
+#include "m_actor_shadow.h"
#include "m_object.h"
#include "overlays/gamestates/ovl_play/m_play.h"
+#include "overlays/actors/player_actor/m_player.h"
+#include "libc/math.h"
+#include "macros.h"
+#include "m_handbill.h"
+#include "m_field_info.h"
+#include "m_debug_display.h"
+#include "m_player_lib.h"
+#include "m_rcp.h"
+#include "683030.h"
+#include "audio.h"
+#include "code_variables.h"
+#include "m_name_table.h"
+
+#include "objects/act_balloon/act_balloon.h"
+
+#define THIS ((Fuusen*)thisx)
void aFSN_actor_ct(Actor* thisx, Game_Play* game_play);
void aFSN_actor_dt(Actor* thisx, Game_Play* game_play);
void aFSN_actor_move(Actor* thisx, Game_Play* game_play);
void aFSN_actor_draw(Actor* thisx, Game_Play* game_play);
+void aFSN_setupAction(Fuusen*, s32, Game_Play*);
-#if 0
ActorProfile Fuusen_Profile = {
/* */ ACTOR_FUUSEN,
/* */ ACTOR_PART_7,
/* */ ACTOR_FLAG_10,
/* */ 0x0000,
- /* */ OBJECT_400,
+ /* */ OBJECT_ACT_BALLOON,
/* */ sizeof(Fuusen),
/* */ aFSN_actor_ct,
/* */ aFSN_actor_dt,
@@ -22,34 +39,433 @@ ActorProfile Fuusen_Profile = {
/* */ aFSN_actor_draw,
/* */ NULL,
};
-#endif
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/aFSN_actor_ct.s")
+void aFSN_actor_ct(Actor* thisx, Game_Play* game_play) {
+ static xyz_t Init_Size = { 0.01f, 0.01f, 0.01f };
+ Fuusen* this = THIS;
+ SkeletonInfoR* skeletonInfo = &this->skeletonInfo;
+ xyz_t size = Init_Size;
+ f32 balloonGroundY = mCoBG_GetBalloonGroundY(&this->actor.world.pos);
+
+ this->escapeTimer = 1000;
+ cKF_SkeletonInfo_R_ct(skeletonInfo, &cKF_bs_r_act_balloon, &cKF_ba_r_act_balloon, this->jointTable,
+ this->morphTable);
+ cKF_SkeletonInfo_R_init_standard_repeat(skeletonInfo, Lib_SegmentedToVirtual(&cKF_ba_r_act_balloon), NULL);
+ Shape_Info_init(&this->actor, 0.0f, mAc_ActorShadowCircle, 10.0f, 10.0f);
+ this->actor.shape.drawShadow = 0;
+ cKF_SkeletonInfo_R_play(skeletonInfo);
+ skeletonInfo->frameControl.speed = 1.0f;
+ xyz_t_move(&this->actor.scale, &size);
+ this->actor.world.pos.y = balloonGroundY + 200.0f;
+ this->heightOffset = 110.0f;
+ this->segment = game_play->objectExchangeBank.status[this->actor.unk_026].segment;
+ this->actor.update = aFSN_actor_move;
+ aFSN_setupAction(this, FSN_PROCESS_BIRTH, game_play);
+}
+
+void aFSN_actor_dt(Actor* thisx, UNUSED Game_Play* game_play) {
+ Fuusen* this = THIS;
+
+ if (this->shouldLookUp) {
+ Balloon_look_up();
+ } else {
+ Balloon_kill();
+ }
+}
+
+void aFSN_birth_init(Fuusen* this, Game_Play* game_play) {
+ static s32 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 }, { 500.0f, 100.0f, 500.0f }, { 500.0f, 100.0f, 1600.0f },
+ { 500.0f, 100.0f, 4620.0f }, { 1600.0f, 100.0f, 4620.0f }, { 3980.0f, 100.0f, 4620.0f },
+ { 3980.0f, 100.0f, 1600.0f }, { 3980.0f, 100.0f, 500.0f },
+ };
+ 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 },
+ };
+ s16 rotVar;
+ f32 rand;
+ s32 randXOrZ;
+ f32 balloonGroundY = mCoBG_GetBalloonGroundY(&this->actor.world.pos);
+ f32 xPos;
+ f32 zPos;
+
+ this->actor.world.rot.y = mEnv_GetWindAngleS();
+ rotVar = this->actor.world.rot.y & 0xF000;
+ this->dataIndex = (rotVar >> 0xC) & 0xF;
+ this->dataIndex = data_index_data[this->dataIndex];
+ xyz_t_move(&this->actor.world.pos, &birth_pos_data[this->dataIndex]);
+ this->actor.world.pos.y = (f32)(balloonGroundY + 200.0f);
+ this->colorIndex = game_play->unk_1EA0 % 5;
+ this->birthTimer = 10;
+ randXOrZ = FSN_RAND_X;
+ if ((birth_pos_random_data[this->dataIndex].x != 0.0f) && (birth_pos_random_data[this->dataIndex].z != 0.0f)) {
+ randXOrZ = game_play->unk_1EA0 & 1;
+ } else if (birth_pos_random_data[this->dataIndex].z != 0.0f) {
+ randXOrZ = FSN_RAND_Z;
+ }
+ if (randXOrZ == FSN_RAND_X) {
+ if (birth_pos_random_data[this->dataIndex].x != 0.0f) {
+ rand = fqrand();
+ xPos = fabsf(birth_pos_random_data[this->dataIndex].x);
+ if (birth_pos_random_data[this->dataIndex].x > 0.0f) {
+ this->actor.world.pos.x += xPos * rand;
+ } else {
+ this->actor.world.pos.x -= xPos * rand;
+ }
+ }
+ } else {
+ if (birth_pos_random_data[this->dataIndex].z != 0.0f) {
+ rand = fqrand();
+ zPos = fabsf(birth_pos_random_data[this->dataIndex].z);
+ if (birth_pos_random_data[this->dataIndex].z > 0.0f) {
+ this->actor.world.pos.z += zPos * rand;
+ } else {
+ this->actor.world.pos.z -= zPos * rand;
+ }
+ }
+ }
+}
+
+void aFSN_moving_init(Fuusen* this, UNUSED Game_Play* game_play) {
+ this->unk_1A4 = false;
+}
+
+void aFSN_wood_stop_init(Fuusen* this, UNUSED Game_Play* game_play) {
+ this->escapeTimer = 9000 + 777;
+ this->actor.speed = 0.0f;
+ sAdo_OngenTrgStart(0x402, &this->actor.world.pos);
+}
+
+void aFSN_escape_init(Fuusen* this, Game_Play* game_play) {
+ Player* player = get_player_actor_withoutCheck(game_play);
+ f32 xDist = player->actor.world.pos.x - this->actor.world.pos.x;
+ f32 zDist = player->actor.world.pos.z - this->actor.world.pos.z;
+
+ this->unk_18C = 0;
+ this->actor.terminalVelocity = 5.0f;
+ this->actor.gravity = 0.5f;
+ this->shouldLookUp = false;
+ if (this->escapeTimer == 777) {
+ this->unk_18C = 1;
+ if (sqrtf(SQ(xDist) + SQ(zDist)) < 640.0f) {
+ this->shouldLookUp = true;
+ }
+ }
+}
+
+Color_RGBA8 balloon_prim_data[5] = {
+ { 255, 210, 200, 255 }, { 200, 230, 200, 255 }, { 255, 250, 200, 255 },
+ { 220, 255, 200, 255 }, { 240, 210, 255, 255 },
+};
+
+Color_RGBA8 balloon_env_data[5] = {
+ { 255, 40, 0, 255 }, { 0, 180, 255, 255 }, { 255, 200, 0, 255 }, { 100, 255, 0, 255 }, { 200, 30, 255, 255 },
+};
+
+void aFSN_birth(Actor* thisx, Game_Play* game_play) {
+ Fuusen* this = THIS;
+ aFSN_setupAction(this, FSN_PROCESS_MOVING, game_play);
+}
+
+void aFSN_moving(Actor* thisx, Game_Play* game_play) {
+ static Vec2s senkou_check_data[3] = {
+ { -1, -2500 },
+ { 0, 0 },
+ { 0, 2500 },
+ };
+ Fuusen* this = THIS;
+ f32 balloonGroundY = mCoBG_GetBalloonGroundY(&this->actor.world.pos) + this->heightOffset;
+ UNUSED UNK_TYPE1 pad[0x4];
+ u16* unitFG;
+ xyz_t screenPos;
+ f32 distX;
+ f32 distY;
+ f32 distZ;
+ s32 i;
+ s16 yRot;
+
+ if (this->escapeTimer > 0) {
+ this->escapeTimer--;
+ } else {
+ if ((this->actor.world.pos.x <= 660.0f) || (this->actor.world.pos.x >= 3820.0f) ||
+ (this->actor.world.pos.z <= 660.0f) || (this->actor.world.pos.z >= 4460.0f)) {
+ this->escapeTimer = 777;
+ aFSN_setupAction(this, FSN_PROCESS_ESCAPE, game_play);
+ return;
+ } else if ((this->actor.world.pos.x <= 2440.0f) && (this->actor.world.pos.x >= 2040.0f) &&
+ (this->actor.world.pos.z <= 960.0f) && (this->actor.world.pos.z >= 800.0f)) {
+ this->escapeTimer = 777;
+ aFSN_setupAction(this, FSN_PROCESS_ESCAPE, game_play);
+ return;
+ }
+ }
+ this->windPower = mEnv_GetWindPowerF();
+ this->heightAmplitudeCounter += 500;
+ this->actor.speed = this->windPower * 0.5f + 1.0f;
+ add_calc(&this->actor.world.pos.y, (sin_s(this->heightAmplitudeCounter) * 10.0f) + balloonGroundY, 0.3f, 1.0f,
+ 0.0f);
+ Game_play_Projection_Trans(game_play, &this->actor.world.pos, &screenPos);
+ if (!(screenPos.x < -40.0f) && !(screenPos.x > 360.0f) && !(screenPos.y < -40.0f) && !(screenPos.y > 280.0f)) {
+ mCoBG_BgCheckControll(NULL, &this->actor, 12.0f, 0, 0, 0, 0);
+ if (this->actor.colResult.hitWall & 1 || this->actor.colResult.unk1 & 1) {
+ this->heightOffset += 0.01f;
+ if (this->heightOffset >= 300.0f) {
+ this->heightOffset = 300.0f;
+ }
+ } else {
+ if (this->heightOffset > 110.0f) {
+ this->heightOffset -= 0.01f;
+ }
+ }
+ unitFG = mFI_GetUnitFG(this->actor.world.pos);
+ if ((unitFG != NULL) && ((*unitFG == TREE) || (*unitFG == TREE_APPLE_NOFRUIT_0) ||
+ (*unitFG == TREE_ORANGE_NOFRUIT_0) || (*unitFG == TREE_PEACH_NOFRUIT_0) ||
+ (*unitFG == TREE_PEAR_NOFRUIT_0) || (*unitFG == TREE_CHERRY_NOFRUIT_0) ||
+ (*unitFG == TREE_APPLE_NOFRUIT_1) || (*unitFG == TREE_ORANGE_NOFRUIT_1) ||
+ (*unitFG == TREE_PEACH_NOFRUIT_1) || (*unitFG == TREE_PEAR_NOFRUIT_1) ||
+ (*unitFG == TREE_CHERRY_NOFRUIT_1) || (*unitFG == TREE_APPLE_NOFRUIT_2) ||
+ (*unitFG == TREE_ORANGE_NOFRUIT_2) || (*unitFG == TREE_PEACH_NOFRUIT_2) ||
+ (*unitFG == TREE_PEAR_NOFRUIT_2) || (*unitFG == TREE_CHERRY_NOFRUIT_2))) {
+ mFI_Wpos2UtCenterWpos(&screenPos, this->actor.world.pos);
+ screenPos.x -= 2.5f;
+ screenPos.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(this->actor.world.pos, 0.0f) + 97.5f;
+ screenPos.z += 7.5f;
+ distX = screenPos.x - this->actor.world.pos.x;
+ distY = screenPos.y - this->actor.world.pos.y;
+ distZ = screenPos.z - this->actor.world.pos.z;
+ if ((sqrtf(SQ(distX) + SQ(distZ)) < 15.0f) && (sqrtf(SQ(distY)) < 15.0f)) {
+ aFSN_setupAction(this, FSN_PROCESS_WOOD_STOP, game_play);
+ }
+ } else {
+ if (!this->unk_1A4) {
+ // FAKE
+ dummy_label:
+ for (i = 0; i < ARRAY_COUNT(senkou_check_data); i++) {
+ xyz_t_move(&screenPos, &this->actor.world.pos);
+ yRot = senkou_check_data[i].z + this->actor.world.rot.y;
+ screenPos.x += sin_s(yRot) * 80.0f;
+ screenPos.z += cos_s(yRot) * 80.0f;
+ unitFG = mFI_GetUnitFG(screenPos);
+ if ((unitFG != NULL) && ((*unitFG == TREE) || (*unitFG == TREE_APPLE_NOFRUIT_0) ||
+ (*unitFG == TREE_ORANGE_NOFRUIT_0) || (*unitFG == TREE_PEACH_NOFRUIT_0) ||
+ (*unitFG == TREE_PEAR_NOFRUIT_0) || (*unitFG == TREE_CHERRY_NOFRUIT_0) ||
+ (*unitFG == TREE_APPLE_NOFRUIT_1) || (*unitFG == TREE_ORANGE_NOFRUIT_1) ||
+ (*unitFG == TREE_PEACH_NOFRUIT_1) || (*unitFG == TREE_PEAR_NOFRUIT_1) ||
+ (*unitFG == TREE_CHERRY_NOFRUIT_1) || (*unitFG == TREE_APPLE_NOFRUIT_2) ||
+ (*unitFG == TREE_ORANGE_NOFRUIT_2) || (*unitFG == TREE_PEACH_NOFRUIT_2) ||
+ (*unitFG == TREE_PEAR_NOFRUIT_2) || (*unitFG == TREE_CHERRY_NOFRUIT_2))) {
+ this->actor.world.rot.y = yRot;
+ this->unk_1A4 = true;
+ break;
+ }
+ }
+ }
+ if (!this->unk_1A4) {
+ this->actor.world.rot.y = mEnv_GetWindAngleS();
+ }
+ }
+ }
+}
+
+void aFSN_wood_stop(Actor* thisx, Game_Play* game_play) {
+ Fuusen* this = THIS;
+ xyz_t pos;
+ xyz_t posCopy;
+ f32 distX;
+ f32 distZ;
+
+ this->escapeTimer--;
+ if (this->escapeTimer <= 777) {
+ this->escapeTimer = 777;
+ aFSN_setupAction(this, FSN_PROCESS_ESCAPE, game_play);
+ } else {
+ mFI_Wpos2UtCenterWpos(&pos, this->actor.world.pos);
+ xyz_t_move(&posCopy, &pos);
+ pos.x -= 2.5f;
+ pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(this->actor.world.pos, 0.0f) + 97.5f;
+ pos.z += 7.5f;
+ distX = this->actor.world.pos.x - pos.x;
+ distZ = this->actor.world.pos.z - pos.z;
+ if (sqrtf(SQ(distX) + SQ(distZ)) > 2.0f) {
+ add_calc(&this->actor.world.pos.x, pos.x, 0.3f, 1.0f, 0.0f);
+ add_calc(&this->actor.world.pos.y, pos.y, 0.3f, 1.0f, 0.0f);
+ add_calc(&this->actor.world.pos.z, pos.z, 0.3f, 1.0f, 0.0f);
+ } else if (mPlib_Check_tree_shaken_big(&posCopy)) {
+ this->actor.shape.rot.z = 0;
+ aFSN_setupAction(this, FSN_PROCESS_ESCAPE, game_play);
+ } else if (mPlib_Check_tree_shaken_little(&posCopy)) {
+ if (!(this->unk_18C & 2)) {
+ this->actor.shape.rot.z = 500;
+ } else {
+ this->actor.shape.rot.z = 0;
+ }
+ this->unk_18C++;
+ } else {
+ this->actor.shape.rot.z = 0;
+ this->unk_18C = 0;
+ }
+ }
+}
+
+void aFSN_escape(Actor* thisx, UNUSED Game_Play* game_play) {
+ Fuusen* this = THIS;
+ f32 balloonGroundY = mCoBG_GetBalloonGroundY(&this->actor.world.pos);
+
+ if (this->unk_18C == 0) {
+ xyz_t pos;
+ s32 utX;
+ s32 utZ;
+
+ mFI_Wpos2UtCenterWpos(&pos, this->actor.world.pos);
+ if ((common_data.clip.unk_074 != NULL) && (common_data.clip.unk_074->unk_38 != 0) &&
+ mFI_Wpos2UtNum(&utX, &utZ, pos)) {
+ common_data.clip.unk_074->unk_30(9500, utX, utZ, 1);
+ this->unk_18C = 1;
+ }
+ }
+ if (this->unk_18C == 1) {
+ if (this->actor.world.pos.y > (balloonGroundY + 500.0f)) {
+ Actor_delete(&this->actor);
+ }
+ }
+}
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/aFSN_actor_dt.s")
+void aFSN_setupAction(Fuusen* this, s32 processIndex, Game_Play* game_play) {
+ static FuusenInitFunc init_proc[4] = {
+ aFSN_birth_init,
+ aFSN_moving_init,
+ aFSN_wood_stop_init,
+ aFSN_escape_init,
+ };
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/func_80AAD270_jp.s")
+ static FuusenActionFunc act_proc[4] = {
+ aFSN_birth,
+ aFSN_moving,
+ aFSN_wood_stop,
+ aFSN_escape,
+ };
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/func_80AAD490_jp.s")
+ this->processNum = processIndex;
+ this->process = act_proc[processIndex];
+ init_proc[processIndex](this, game_play);
+}
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/func_80AAD4A0_jp.s")
+// Original name unknown.
+void func_80AADF10_jp(Fuusen* this, Game_Play* game_play) {
+ UNUSED UNK_TYPE1 pad[0x4];
+ void* segment;
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/func_80AAD4DC_jp.s")
+ segment = game_play->objectExchangeBank.status[this->actor.unk_026].segment;
+ if (this->segment != segment) {
+ SkeletonInfoR* skeletonInfo = &this->skeletonInfo;
+ skeletonInfo->skeleton = Lib_SegmentedToVirtual(&cKF_bs_r_act_balloon);
+ skeletonInfo->animation = Lib_SegmentedToVirtual(&cKF_ba_r_act_balloon);
+ this->segment = segment;
+ }
+}
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/func_80AAD580_jp.s")
+void aFSN_actor_move(Actor* thisx, Game_Play* game_play) {
+ Fuusen* this = THIS;
+ UNUSED UNK_TYPE1 pad[0x8];
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/func_80AAD5A4_jp.s")
+ func_80AADF10_jp(this, game_play);
+ if (this->birthTimer == 0) {
+ Actor_position_moveF(&this->actor);
+ } else if (this->birthTimer > 0) {
+ this->birthTimer--;
+ }
+ if (fuusen_DEBUG_mode_flag != 0) {
+ Player* player = get_player_actor_withoutCheck(game_play);
+ Debug_Display_new((sin_s(this->actor.yawTowardsPlayer + 0x8000) * 30.0f) + player->actor.world.pos.x,
+ player->actor.world.pos.y + 60.0f,
+ (cos_s(this->actor.yawTowardsPlayer + 0x8000) * 30.0f) + player->actor.world.pos.z, 0,
+ this->actor.yawTowardsPlayer + 0x8000, 0, 1.0f, 1.0f, 1.0f, 250, 100, 120, 128, 4,
+ game_play->state.gfxCtx);
+ }
+ cKF_SkeletonInfo_R_play(&this->skeletonInfo);
+ this->process(&this->actor, game_play);
+ fuusen_DEBUG_mode_flag = 0;
+}
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/func_80AADB9C_jp.s")
+// Original name unknown.
+Gfx* func_80AAE10C_jp(u8 red, u8 blue, u8 green, u8 alpha, Game_Play* game_play) {
+ GraphicsContext* gfxCtx = game_play->state.gfxCtx;
+ Gfx* gfx = GRAPH_ALLOC(gfxCtx, 1);
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/func_80AADDA8_jp.s")
+ if (gfx) {
+ gDPSetPrimColor(gfx, 0, 255, red, blue, green, alpha);
+ gSPEndDisplayList(gfx + 1);
+ return gfx;
+ }
+ return NULL;
+}
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/func_80AADEC4_jp.s")
+extern Gfx present_DL_mode[];
+extern Vtx present_DL_vtx[];
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/func_80AADF10_jp.s")
+#define OPEN_CUSTOM_POLY_OPA() \
+ { \
+ Gfx* __polyOpa = __gfxCtx->polyOpa.p; \
+ int __opa_opened = 0; \
+ do { \
+ } while (0)
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/aFSN_actor_move.s")
+#define CLOSE_CUSTOM_POLY_OPA() \
+ __gfxCtx->polyOpa.p = __polyOpa; \
+ (void)__opa_opened; \
+ } \
+ while (0)
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/func_80AAE10C_jp.s")
+void aFSN_actor_draw(Actor* thisx, Game_Play* game_play) {
+ static xyz_t offset0 = { 0.0f, 0.0f, 0.0f };
+ Fuusen* this = THIS;
+ s32 mtxIndex = game_play->state.frameCounter & 1;
+ UNUSED UNK_TYPE1 pad[0x8];
+ s16 objBankIndex;
+ void* segment;
+ Gfx* balloonGfx;
-#pragma GLOBAL_ASM("asm/jp/nonmatchings/overlays/actors/ovl_Fuusen/ac_fuusen/aFSN_actor_draw.s")
+ objBankIndex = this->actor.unk_026;
+ segment = game_play->objectExchangeBank.status[objBankIndex].segment;
+ balloonGfx =
+ func_80AAE10C_jp(balloon_prim_data[this->colorIndex].r, balloon_prim_data[this->colorIndex].g,
+ balloon_prim_data[this->colorIndex].b, balloon_prim_data[this->colorIndex].a, game_play);
+ if ((balloonGfx != NULL) &&
+ (!Camera2_CheckCullingMode() ||
+ !Camera2_CheckEnterCullingArea(this->actor.world.pos.x, this->actor.world.pos.z, 60.0f))) {
+ func_80AADF10_jp(this, game_play);
+ Matrix_push();
+ if ((this->processNum != FSN_PROCESS_ESCAPE) || (this->escapeTimer == 777) ||
+ ((this->processNum == FSN_PROCESS_ESCAPE) && (this->unk_18C == 0))) {
+ _texture_z_light_fog_prim(game_play->state.gfxCtx);
+ OPEN_DISPS(game_play->state.gfxCtx);
+ OPEN_CUSTOM_POLY_OPA();
+ Matrix_translate(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0);
+ Matrix_scale(0.01f, 0.01f, 0.01f, 1);
+ Matrix_RotateX(this->actor.shape.rot.x, MTXMODE_APPLY);
+ Matrix_RotateZ(this->actor.shape.rot.z, MTXMODE_APPLY);
+ Matrix_RotateY(this->actor.shape.rot.y, MTXMODE_APPLY);
+ gSPMatrix(__polyOpa++, _Matrix_to_Mtx_new(game_play->state.gfxCtx),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(__polyOpa++, present_DL_mode);
+ gSPDisplayList(__polyOpa++, present_DL_vtx);
+ CLOSE_CUSTOM_POLY_OPA();
+ CLOSE_DISPS(game_play->state.gfxCtx);
+ }
+ OPEN_DISPS(game_play->state.gfxCtx);
+ gSPSegment(POLY_OPA_DISP++, 0x06, segment);
+ gSPSegment(POLY_OPA_DISP++, 0x08, balloonGfx);
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetEnvColor(POLY_OPA_DISP++, balloon_env_data[this->colorIndex].r, balloon_env_data[this->colorIndex].g,
+ balloon_env_data[this->colorIndex].b, balloon_env_data[this->colorIndex].a);
+ CLOSE_DISPS(game_play->state.gfxCtx);
+ Setpos_HiliteReflect_init(&this->actor.world.pos, game_play);
+ cKF_Si3_draw_R_SV(game_play, &this->skeletonInfo, this->mtx[mtxIndex], NULL, NULL, &this->actor);
+ mAc_ActorShadowDraw_ShadowDrawFlagOn(&this->actor, game_play, 0, offset0, 170.0f);
+ Matrix_pull();
+ }
+}
diff --git a/src/overlays/actors/ovl_Fuusen/ac_fuusen.h b/src/overlays/actors/ovl_Fuusen/ac_fuusen.h
index 172a826..03b555b 100644
--- a/src/overlays/actors/ovl_Fuusen/ac_fuusen.h
+++ b/src/overlays/actors/ovl_Fuusen/ac_fuusen.h
@@ -4,15 +4,45 @@
#include "ultra64.h"
#include "m_actor.h"
#include "unk.h"
+#include "c_keyframe.h"
struct Game_Play;
struct Fuusen;
-typedef void (*FuusenActionFunc)(struct Fuusen*, struct Game_Play*);
+typedef void (*FuusenInitFunc)(struct Fuusen*, struct Game_Play*);
+typedef void (*FuusenActionFunc)(struct Actor*, struct Game_Play*);
+
+typedef enum FuusenProcess {
+ FSN_PROCESS_BIRTH,
+ FSN_PROCESS_MOVING,
+ FSN_PROCESS_WOOD_STOP,
+ FSN_PROCESS_ESCAPE,
+} FuusenProcess;
+
+typedef enum FuusenRand {
+ FSN_RAND_X,
+ FSN_RAND_Z,
+} FuusenRand;
typedef struct Fuusen {
/* 0x000 */ Actor actor;
- /* 0x174 */ UNK_TYPE1 unk_174[0x2D4];
+ /* 0x174 */ FuusenActionFunc process;
+ /* 0x178 */ void* segment;
+ /* 0x17C */ s32 processNum;
+ /* 0x180 */ u32 colorIndex;
+ /* 0x184 */ s32 escapeTimer;
+ /* 0x188 */ s32 birthTimer;
+ /* 0x18C */ s32 unk_18C;
+ /* 0x190 */ s32 shouldLookUp;
+ /* 0x194 */ s32 dataIndex;
+ /* 0x198 */ s16 heightAmplitudeCounter;
+ /* 0x19C */ f32 windPower;
+ /* 0x1A0 */ f32 heightOffset;
+ /* 0x1A4 */ u8 unk_1A4;
+ /* 0x1A8 */ SkeletonInfoR skeletonInfo;
+ /* 0x218 */ s_xyz jointTable[0x4];
+ /* 0x230 */ s_xyz morphTable[0x4];
+ /* 0x248 */ Mtx mtx[2][4];
} Fuusen; // size = 0x448
#endif
diff --git a/src/overlays/gamestates/ovl_play/m_play.h b/src/overlays/gamestates/ovl_play/m_play.h
index 27b28bc..7400a44 100644
--- a/src/overlays/gamestates/ovl_play/m_play.h
+++ b/src/overlays/gamestates/ovl_play/m_play.h
@@ -86,7 +86,7 @@ typedef struct Game_Play {
/* 0x1E1C */ MtxF viewProjectionMtxF;
/* 0x1E5C */ MtxF billboardMtxF;
/* 0x1E9C */ Mtx* unk_1E9C;
- /* 0x1EA0 */ s32 unk_1EA0;
+ /* 0x1EA0 */ u32 unk_1EA0;
/* 0x1EA4 */ UNK_TYPE1 unk_1EA4[0x1];
/* 0x1EA5 */ u8 unk_1EA5;
/* 0x1EA6 */ u8 unk_1EA6;