mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-05-22 22:24:16 -04:00
Merge pull request #215 from Cuyler36/ac_birth_control
Implement & link ac_birth_control
This commit is contained in:
@@ -388,6 +388,10 @@ ac_ball.c:
|
||||
.rodata: [0x80643A90,0x80643B60]
|
||||
.data: [0x8065FBF8, 0x8065FC58]
|
||||
.bss: [0x812F96E0, 0x812F96E8]
|
||||
ac_birth_control.c:
|
||||
.text: [0x80414598, 0x80414EC4]
|
||||
.rodata: [0x80643B90, 0x80643B98]
|
||||
.data: [0x8065FCB0, 0x8065FD28]
|
||||
ac_boat_demo.c:
|
||||
.text: [0x80414EC4, 0x80415BD8]
|
||||
.rodata: [0x80643B98, 0x80643BA0]
|
||||
|
||||
@@ -3,11 +3,23 @@
|
||||
|
||||
#include "types.h"
|
||||
#include "m_actor.h"
|
||||
#include "m_field_make.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct birth_control_s BIRTH_CONTROL_ACTOR;
|
||||
|
||||
struct birth_control_s {
|
||||
ACTOR actor_class;
|
||||
int setup_actor_flag;
|
||||
mFM_move_actor_c* move_actor_data;
|
||||
u16 move_actor_bitfield;
|
||||
s16 move_actor_list_exists_flag;
|
||||
int boat_spawned;
|
||||
};
|
||||
|
||||
extern ACTOR_PROFILE Birth_Control_Profile;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -227,8 +227,8 @@ typedef struct field_bg_info_s {
|
||||
|
||||
typedef struct field_fg_move_actor_s {
|
||||
mActor_name_t name_id;
|
||||
s8 ut_x;
|
||||
s8 ut_z;
|
||||
u8 ut_x;
|
||||
u8 ut_z;
|
||||
s8 npc_info_idx;
|
||||
s16 arg;
|
||||
} mFM_move_actor_c;
|
||||
|
||||
+19
-19
@@ -1715,25 +1715,25 @@ extern int mNT_check_unknown(mActor_name_t item_no);
|
||||
#define MISC_ACTOR_SAMPLE MISC_ACTOR_START
|
||||
|
||||
#define ACTOR_PROP_START 0xA000
|
||||
#define ACTOR_PROP_MAILBOX0 (ACTOR_PROP_START)
|
||||
#define ACTOR_PROP_MAILBOX1 (ACTOR_PROP_MAILBOX0 + 1)
|
||||
#define ACTOR_PROP_MAILBOX2 (ACTOR_PROP_MAILBOX1 + 1)
|
||||
#define ACTOR_PROP_MAILBOX3 (ACTOR_PROP_MAILBOX2 + 1)
|
||||
#define ACTOR_PROP_HANIWA0 (ACTOR_PROP_MAILBOX3 + 1)
|
||||
#define ACTOR_PROP_HANIWA1 (ACTOR_PROP_HANIWA0 + 1)
|
||||
#define ACTOR_PROP_HANIWA2 (ACTOR_PROP_HANIWA1 + 1)
|
||||
#define ACTOR_PROP_HANIWA3 (ACTOR_PROP_HANIWA2 + 1)
|
||||
#define SNOWMAN0 (ACTOR_PROP_HANIWA3 + 1)
|
||||
#define SNOWMAN1 (SNOWMAN0 + 1)
|
||||
#define SNOWMAN2 (SNOWMAN1 + 1)
|
||||
#define SNOWMAN3 (SNOWMAN2 + 1)
|
||||
#define SNOWMAN4 (SNOWMAN3 + 1)
|
||||
#define SNOWMAN5 (SNOWMAN4 + 1)
|
||||
#define SNOWMAN6 (SNOWMAN5 + 1)
|
||||
#define SNOWMAN7 (SNOWMAN6 + 1)
|
||||
#define SNOWMAN8 (SNOWMAN7 + 1)
|
||||
#define TRAIN_DOOR 0xA011
|
||||
#define ACTOR_PROP_VILLAGER_SIGNBOARD 0xA012
|
||||
#define ACTOR_PROP_MAILBOX0 (ACTOR_PROP_START + 0) // A000
|
||||
#define ACTOR_PROP_MAILBOX1 (ACTOR_PROP_START + 1) // A001
|
||||
#define ACTOR_PROP_MAILBOX2 (ACTOR_PROP_START + 2) // A002
|
||||
#define ACTOR_PROP_MAILBOX3 (ACTOR_PROP_START + 3) // A003
|
||||
#define ACTOR_PROP_HANIWA0 (ACTOR_PROP_START + 4) // A004
|
||||
#define ACTOR_PROP_HANIWA1 (ACTOR_PROP_START + 5) // A005
|
||||
#define ACTOR_PROP_HANIWA2 (ACTOR_PROP_START + 6) // A006
|
||||
#define ACTOR_PROP_HANIWA3 (ACTOR_PROP_START + 7) // A007
|
||||
#define SNOWMAN0 (ACTOR_PROP_START + 8) // A008
|
||||
#define SNOWMAN1 (ACTOR_PROP_START + 9) // A009
|
||||
#define SNOWMAN2 (ACTOR_PROP_START + 10) // A00A
|
||||
#define SNOWMAN3 (ACTOR_PROP_START + 11) // A00B
|
||||
#define SNOWMAN4 (ACTOR_PROP_START + 12) // A00C
|
||||
#define SNOWMAN5 (ACTOR_PROP_START + 13) // A00D
|
||||
#define SNOWMAN6 (ACTOR_PROP_START + 14) // A00E
|
||||
#define SNOWMAN7 (ACTOR_PROP_START + 15) // A00F
|
||||
#define SNOWMAN8 (ACTOR_PROP_START + 16) // A010
|
||||
#define TRAIN_DOOR (ACTOR_PROP_START + 17) // A011
|
||||
#define ACTOR_PROP_VILLAGER_SIGNBOARD (ACTOR_PROP_START + 18) // A012
|
||||
|
||||
#define SP_NPC_START 0xD000
|
||||
#define SP_NPC_ARTIST (SP_NPC_START + 0) // D000
|
||||
|
||||
@@ -0,0 +1,337 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ ACTOR_PROFILE Boat_Demo_Profile = {
|
||||
|
||||
static mDemo_Clip_c aBTD_clip;
|
||||
|
||||
#ifndef __INTELLISENSE__
|
||||
static u8 aBTD_island_prg[] = {
|
||||
#include "assets/aBTD_island_prg.inc"
|
||||
};
|
||||
@@ -37,6 +38,10 @@ static u8 aBTD_island_prg[] = {
|
||||
static u8 aBTD_island_ldr[] = {
|
||||
#include "assets/aBTD_island_ldr.inc"
|
||||
};
|
||||
#else
|
||||
extern u8 aBTD_island_prg[];
|
||||
extern u8 aBTD_island_ldr[];
|
||||
#endif
|
||||
|
||||
static void aBTD_setupAction(BOAT_DEMO_ACTOR* boat_demo, GAME_PLAY* play, int action);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user