mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-06-19 14:30:33 -04:00
338 lines
10 KiB
C
338 lines
10 KiB
C
#include "ac_birth_control.h"
|
|
|
|
#include "m_play.h"
|
|
#include "m_field_info.h"
|
|
#include "m_common_data.h"
|
|
#include "GBA2/gba2.h"
|
|
|
|
static void aBC_actor_move(ACTOR*, GAME*);
|
|
|
|
ACTOR_PROFILE Birth_Control_Profile = {
|
|
mAc_PROFILE_BIRTH_CONTROL,
|
|
ACTOR_PART_ITEM,
|
|
ACTOR_STATE_NO_MOVE_WHILE_CULLED | ACTOR_STATE_NO_DRAW_WHILE_CULLED,
|
|
EMPTY_NO,
|
|
ACTOR_OBJ_BANK_KEEP,
|
|
sizeof(BIRTH_CONTROL_ACTOR),
|
|
mActor_NONE_PROC1,
|
|
mActor_NONE_PROC1,
|
|
&aBC_actor_move,
|
|
mActor_NONE_PROC1,
|
|
NULL
|
|
};
|
|
|
|
static f32 aBC_pos_table[UT_BASE_NUM] = {
|
|
mFI_UT_WORLDSIZE_X_F * 0 + mFI_UT_WORLDSIZE_HALF_X_F, // 20.0f
|
|
mFI_UT_WORLDSIZE_X_F * 1 + mFI_UT_WORLDSIZE_HALF_X_F, // 60.0f
|
|
mFI_UT_WORLDSIZE_X_F * 2 + mFI_UT_WORLDSIZE_HALF_X_F, // 100.0f
|
|
mFI_UT_WORLDSIZE_X_F * 3 + mFI_UT_WORLDSIZE_HALF_X_F, // 140.0f
|
|
mFI_UT_WORLDSIZE_X_F * 4 + mFI_UT_WORLDSIZE_HALF_X_F, // 180.0f
|
|
mFI_UT_WORLDSIZE_X_F * 5 + mFI_UT_WORLDSIZE_HALF_X_F, // 220.0f
|
|
mFI_UT_WORLDSIZE_X_F * 6 + mFI_UT_WORLDSIZE_HALF_X_F, // 260.0f
|
|
mFI_UT_WORLDSIZE_X_F * 7 + mFI_UT_WORLDSIZE_HALF_X_F, // 300.0f
|
|
mFI_UT_WORLDSIZE_X_F * 8 + mFI_UT_WORLDSIZE_HALF_X_F, // 340.0f
|
|
mFI_UT_WORLDSIZE_X_F * 9 + mFI_UT_WORLDSIZE_HALF_X_F, // 380.0f
|
|
mFI_UT_WORLDSIZE_X_F * 10 + mFI_UT_WORLDSIZE_HALF_X_F, // 420.0f
|
|
mFI_UT_WORLDSIZE_X_F * 11 + mFI_UT_WORLDSIZE_HALF_X_F, // 460.0f
|
|
mFI_UT_WORLDSIZE_X_F * 12 + mFI_UT_WORLDSIZE_HALF_X_F, // 500.0f
|
|
mFI_UT_WORLDSIZE_X_F * 13 + mFI_UT_WORLDSIZE_HALF_X_F, // 540.0f
|
|
mFI_UT_WORLDSIZE_X_F * 14 + mFI_UT_WORLDSIZE_HALF_X_F, // 580.0f
|
|
mFI_UT_WORLDSIZE_X_F * 15 + mFI_UT_WORLDSIZE_HALF_X_F // 620.0f
|
|
};
|
|
|
|
static void aBC_deleteActor_part(GAME_PLAY* play, int part) {
|
|
mFI_block_tbl_c* last_block_table = &play->last_block_table;
|
|
s8 last_bx = last_block_table->block_x;
|
|
s8 last_bz = last_block_table->block_z;
|
|
s8 now_bx = play->block_table.block_x;
|
|
s8 now_bz = play->block_table.block_z;
|
|
s8 check_bx;
|
|
s8 check_bz;
|
|
ACTOR* actor = play->actor_info.list[part].actor;
|
|
|
|
while (TRUE) {
|
|
if (actor == NULL) {
|
|
break;
|
|
}
|
|
|
|
check_bx = actor->block_x;
|
|
check_bz = actor->block_z;
|
|
|
|
/* Delete any actors which aren't in the current block or the last block */
|
|
if (
|
|
(check_bx >= 0 && check_bx != last_bx && check_bx != now_bx) &&
|
|
(check_bz >= 0 && check_bz != last_bz && check_bz != now_bz)
|
|
) {
|
|
Actor_delete(actor);
|
|
}
|
|
|
|
actor = actor->next_actor;
|
|
}
|
|
}
|
|
|
|
static int aBC_setupOtherActor(GAME_PLAY* play, mActor_name_t actor_id, s16 profile, f32 pos_x, f32 pos_z, mActor_name_t clear_item) {
|
|
ACTOR* actor;
|
|
xyz_t pos;
|
|
int res = FALSE;
|
|
|
|
pos.x = pos_x;
|
|
pos.z = pos_z;
|
|
pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos2(pos, 0.0f);
|
|
actor = Actor_info_make_actor(
|
|
&play->actor_info,
|
|
(GAME*)play,
|
|
profile,
|
|
pos.x, pos.y, pos.z,
|
|
0, 0, 0,
|
|
play->block_table.block_x, play->block_table.block_z,
|
|
-1,
|
|
actor_id,
|
|
actor_id,
|
|
-1,
|
|
-1
|
|
);
|
|
|
|
if (actor != NULL) {
|
|
actor->restore_fg = TRUE;
|
|
mFI_SetFG_common(clear_item, pos, FALSE);
|
|
}
|
|
else {
|
|
res = TRUE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static void aBC_setupActor(BIRTH_CONTROL_ACTOR* birth_control, GAME_PLAY* play) {
|
|
mFI_block_tbl_c* block_table = &play->block_table;
|
|
mActor_name_t* item_p = block_table->items;
|
|
f32 base_x = block_table->pos_x;
|
|
f32 base_z = block_table->pos_z;
|
|
int setup_actor_flag = FALSE;
|
|
mActor_name_t clear_item;
|
|
int ut_z;
|
|
int ut_x;
|
|
|
|
for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) {
|
|
for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) {
|
|
switch (ITEM_NAME_GET_TYPE(*item_p)) {
|
|
case NAME_TYPE_ITEM2:
|
|
{
|
|
int idx = *item_p - ETC_START;
|
|
|
|
setup_actor_flag |= aBC_setupOtherActor(play, *item_p, move_obj_profile_table[idx], base_x + aBC_pos_table[ut_x], base_z + aBC_pos_table[ut_z], EMPTY_NO);
|
|
break;
|
|
}
|
|
|
|
case NAME_TYPE_PROPS:
|
|
{
|
|
int idx;
|
|
|
|
if (*item_p >= SNOWMAN0 && *item_p <= SNOWMAN8) {
|
|
clear_item = EMPTY_NO;
|
|
}
|
|
else {
|
|
clear_item = RSV_NO;
|
|
}
|
|
|
|
idx = *item_p - ACTOR_PROP_START;
|
|
setup_actor_flag |= aBC_setupOtherActor(play, *item_p, props_profile_table[idx], base_x + aBC_pos_table[ut_x], base_z + aBC_pos_table[ut_z], clear_item);
|
|
break;
|
|
}
|
|
|
|
case NAME_TYPE_STRUCT:
|
|
if (Common_Get(clip).structure_clip != NULL) {
|
|
STRUCTURE_ACTOR* actor = (*Common_Get(clip).structure_clip->setup_actor_proc)((GAME*)play, *item_p, -1, base_x + aBC_pos_table[ut_x], base_z + aBC_pos_table[ut_z]);
|
|
setup_actor_flag |= actor == NULL;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
item_p++;
|
|
}
|
|
}
|
|
|
|
birth_control->setup_actor_flag = setup_actor_flag;
|
|
}
|
|
|
|
static int aBC_setupCommonMvActor(GAME_PLAY* play, mFM_move_actor_c* mv_actor_list, int mv_actor_list_no, s16 profile, f32 pos_x, f32 pos_z) {
|
|
Actor_info* actor_info = &play->actor_info;
|
|
xyz_t pos;
|
|
f32 y;
|
|
int res = FALSE;
|
|
|
|
pos.x = pos_x;
|
|
pos.z = pos_z;
|
|
pos.y = mCoBG_GetBgY_OnlyCenter_FromWpos(pos, 0.0f);
|
|
|
|
if (Actor_info_make_actor(
|
|
actor_info,
|
|
(GAME*)play,
|
|
profile,
|
|
pos.x, pos.y, pos.z,
|
|
0, 0, 0,
|
|
play->block_table.block_x, play->block_table.block_z,
|
|
mv_actor_list_no,
|
|
mv_actor_list->name_id,
|
|
mv_actor_list->arg,
|
|
mv_actor_list->npc_info_idx,
|
|
-1
|
|
) != NULL) {
|
|
res = TRUE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static void aBC_setupMvActor(BIRTH_CONTROL_ACTOR* birth_control, GAME_PLAY* play) {
|
|
mFM_move_actor_c* mv_actor_list_p = birth_control->move_actor_data;
|
|
|
|
if (mv_actor_list_p != NULL) {
|
|
u16 mv_actor_bitfield = birth_control->move_actor_bitfield;
|
|
mFI_block_tbl_c* block_table = &play->block_table;
|
|
f32 base_x = block_table->pos_x;
|
|
f32 base_z = block_table->pos_z;
|
|
int was_born;
|
|
int i;
|
|
|
|
for (i = 0; i < mFM_MOVE_ACTOR_NUM; i++) {
|
|
if (((mv_actor_bitfield >> i) & 1) == 1) {
|
|
mActor_name_t mv_actor_name = mv_actor_list_p->name_id;
|
|
|
|
switch (ITEM_NAME_GET_TYPE(mv_actor_name)) {
|
|
case NAME_TYPE_ITEM2:
|
|
was_born = aBC_setupCommonMvActor(play, mv_actor_list_p, i, move_obj_profile_table[mv_actor_name - ETC_START], base_x + aBC_pos_table[mv_actor_list_p->ut_x], base_z + aBC_pos_table[mv_actor_list_p->ut_z]);
|
|
break;
|
|
case NAME_TYPE_ACTOR:
|
|
was_born = aBC_setupCommonMvActor(play, mv_actor_list_p, i, actor_profile_table[mv_actor_name - MISC_ACTOR_START], base_x + aBC_pos_table[mv_actor_list_p->ut_x], base_z + aBC_pos_table[mv_actor_list_p->ut_z]);
|
|
break;
|
|
case NAME_TYPE_SPNPC:
|
|
case NAME_TYPE_NPC:
|
|
if (Common_Get(clip).npc_clip != NULL && Common_Get(clip).npc_clip->setupActor_proc != NULL) {
|
|
was_born = (*Common_Get(clip).npc_clip->setupActor_proc)(play, mv_actor_name, mv_actor_list_p->npc_info_idx, i, mv_actor_list_p->arg, block_table->block_x, block_table->block_z, mv_actor_list_p->ut_x, mv_actor_list_p->ut_z);
|
|
}
|
|
else {
|
|
was_born = FALSE;
|
|
}
|
|
break;
|
|
default:
|
|
was_born = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (was_born == TRUE) {
|
|
mv_actor_bitfield = ~(1 << i) & mv_actor_bitfield;
|
|
}
|
|
}
|
|
|
|
mv_actor_list_p++;
|
|
}
|
|
|
|
birth_control->move_actor_bitfield = mv_actor_bitfield;
|
|
}
|
|
}
|
|
|
|
static int aBC_chk_near_boat_block(BIRTH_CONTROL_ACTOR* birth_control, GAME_PLAY* play) {
|
|
/* Check to spawn boat while in E-5 or F-4 */
|
|
static int chk_bx[] = { 5, 4 }; // 4 & 5 column
|
|
static int chk_bz[] = { 5, 6 }; // E & F row
|
|
int res = FALSE;
|
|
int i;
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
if (play->block_table.block_x == chk_bx[i] && play->block_table.block_z == chk_bz[i]) {
|
|
if (birth_control->boat_spawned == FALSE) {
|
|
mGcgba_InitVar();
|
|
birth_control->boat_spawned = TRUE;
|
|
}
|
|
|
|
res = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static void aBC_set_boat(BIRTH_CONTROL_ACTOR* birth_control, GAME_PLAY* play) {
|
|
if (mEv_CheckTitleDemo() <= 0 && aBC_chk_near_boat_block(birth_control, play) == TRUE) {
|
|
mActor_name_t* boat_ut_p = mFI_UtNum2UtFG(5 * UT_X_NUM + 5, 6 * UT_Z_NUM + 10); // Set boat at F-5, unit 5-10 (x-z)
|
|
|
|
if (boat_ut_p != NULL) {
|
|
mActor_name_t boat_item = *boat_ut_p;
|
|
|
|
switch (mGcgba_ConnectEnabled()) {
|
|
case GBA2_GBA_STATE_SUCCESS:
|
|
/* Successfully connected to the GBA */
|
|
mGcgba_InitVar();
|
|
boat_item = BOAT; // set boat
|
|
break;
|
|
default:
|
|
/* Failed to connect to the GBA */
|
|
mGcgba_InitVar();
|
|
boat_item = EMPTY_NO; // clear boat
|
|
break;
|
|
case GBA2_GBA_STATE_TRANSMITTING:
|
|
/* Still transmitting */
|
|
break;
|
|
}
|
|
|
|
*boat_ut_p = boat_item;
|
|
}
|
|
}
|
|
else {
|
|
/* We're not in a boat acre, so allow initial communication again */
|
|
birth_control->boat_spawned = FALSE;
|
|
}
|
|
}
|
|
|
|
static void aBC_actor_move(ACTOR* actorx, GAME* game) {
|
|
BIRTH_CONTROL_ACTOR* birth_control = (BIRTH_CONTROL_ACTOR*)actorx;
|
|
GAME_PLAY* play = (GAME_PLAY*)game;
|
|
|
|
if (Common_Get(bg_item_type) == 0) {
|
|
birth_control->setup_actor_flag |= mFI_ActorisBorn() == TRUE;
|
|
aBC_set_boat(birth_control, play);
|
|
}
|
|
|
|
if (mFI_ActorisBorn() == TRUE) {
|
|
int bx = play->block_table.block_x;
|
|
int bz = play->block_table.block_z;
|
|
|
|
birth_control->move_actor_data = mFI_MoveActorListDma(bx, bz);
|
|
mNpc_AddActor_inBlock(birth_control->move_actor_data, bx, bz);
|
|
|
|
if (birth_control->move_actor_data != NULL) {
|
|
birth_control->move_actor_bitfield = mFI_GetMoveActorBitData(bx, bz);
|
|
birth_control->move_actor_list_exists_flag = TRUE;
|
|
}
|
|
else {
|
|
birth_control->move_actor_bitfield = 0;
|
|
}
|
|
}
|
|
|
|
g_fdinfo->born_actor = FALSE;
|
|
|
|
if (play->game.pad_initialized == TRUE) {
|
|
if (birth_control->setup_actor_flag) {
|
|
aBC_deleteActor_part(play, ACTOR_PART_ITEM);
|
|
aBC_setupActor(birth_control, play);
|
|
}
|
|
|
|
if (birth_control->move_actor_list_exists_flag == TRUE && birth_control->move_actor_bitfield != 0) {
|
|
int bx = play->block_table.block_x;
|
|
int bz = play->block_table.block_z;
|
|
|
|
aBC_deleteActor_part(play, ACTOR_PART_NPC);
|
|
aBC_setupMvActor(birth_control, play);
|
|
mFI_SetMoveActorBitData(bx, bz, birth_control->move_actor_bitfield);
|
|
}
|
|
}
|
|
|
|
/* Only refresh the list when transitioning between acres or transitioning between scenes */
|
|
if (mFI_CheckPlayerWade(mFI_WADE_NONE) == TRUE && play->fb_fade_type == 0) {
|
|
birth_control->move_actor_list_exists_flag = FALSE;
|
|
}
|
|
}
|