From c39e9fbdd5740c9cb2160f3cb33c7961d1504a7f Mon Sep 17 00:00:00 2001 From: Cuyler36 Date: Tue, 3 Oct 2023 17:51:12 -0400 Subject: [PATCH] Partial implementation of m_event.c, link 3 TUs --- config/rel_slices.yml | 11 + include/ac_aprilfool_control.h | 20 + include/ac_aprilfool_control_h.h | 19 + include/ac_event_manager.h | 47 ++ include/ac_groundhog_control.h | 54 ++ include/ac_groundhog_control_h.h | 18 + include/ac_npc.h | 12 +- include/m_bgm.h | 3 + include/m_clip.h | 11 +- include/m_common_data.h | 12 +- include/m_event.h | 277 +++++++- include/m_name_table.h | 212 +++--- include/m_olib.h | 5 + rel/ac_aprilfool_control.c | 147 +++++ rel/ac_aprilfool_control/aPC_actor_dt.c | 4 - rel/ac_groundhog_control.c | 221 +++++++ rel/ac_set_ovl_insect.c | 2 +- rel/m_event.c | 819 ++++++++++++++++++++++++ rel/m_field_assessment.c | 158 +++-- rel/m_flashrom.c | 34 +- rel/m_play.c | 8 +- 21 files changed, 1910 insertions(+), 184 deletions(-) create mode 100644 include/ac_aprilfool_control_h.h create mode 100644 include/ac_groundhog_control_h.h create mode 100644 rel/ac_aprilfool_control.c delete mode 100644 rel/ac_aprilfool_control/aPC_actor_dt.c create mode 100644 rel/ac_groundhog_control.c create mode 100644 rel/m_event.c diff --git a/config/rel_slices.yml b/config/rel_slices.yml index a9558a86..b88fc202 100644 --- a/config/rel_slices.yml +++ b/config/rel_slices.yml @@ -80,6 +80,11 @@ m_fbdemo_fade.c: .text: [0x803A12F8, 0x803A1508] .rodata: [0x80641FC0, 0x80641FD8] .data: [0x80653558, 0x806535A0] +m_field_assessment.c: + .text: [0x803A1508, 0x803A22C4] + .rodata: [0x80641FD8, 0x80641FE0] + .data: [0x806535A0, 0x80653620] + .bss: [0x81295790, 0x812957A0] m_field_make.c: .text: [0x803A22C4, 0x803A4D68] .rodata: [0x80641FE0, 0x80642008] @@ -380,6 +385,12 @@ m_all_grow_ovl.c: .rodata: [0x80649098, 0x80649110] .data: [0x8069FA68, 0x8069FD08] .bss: [0x813013E0, 0x81301820] +ac_aprilfool_control.c: + .text: [0x80515340, 0x805155C8] + .data: [0x8069FD08, 0x8069FD88] +ac_groundhog_control.c: + .text: [0x805155C8, 0x80515C48] + .data: [0x8069FD88, 0x8069FDD0] ac_douzou.c: .text: [0x805AD6D8, 0x805AE704] .rodata: [0x8064A7C0, 0x8064A7E8] diff --git a/include/ac_aprilfool_control.h b/include/ac_aprilfool_control.h index 74d935c8..d2d582a4 100644 --- a/include/ac_aprilfool_control.h +++ b/include/ac_aprilfool_control.h @@ -3,13 +3,33 @@ #include "types.h" #include "m_actor.h" +#include "ac_aprilfool_control_h.h" #ifdef __cplusplus extern "C" { #endif +#define aAPC_GET_NPC_BIT(bitfield, data_idx) ((1 << (data_idx)) & (bitfield)) +#define aAPC_SET_NPC_BIT(bitfield, data_idx) ((bitfield) | (1 << (data_idx))) + +typedef int (*aAPC_TALK_CHK_PROC)(mActor_name_t); +typedef void (*aAPC_TALK_SET_PROC)(mActor_name_t); +typedef int (*aAPC_GET_MSG_NUM_PROC)(mActor_name_t, int); + +typedef struct aprilfool_control_clip_s { + aAPC_TALK_CHK_PROC talk_chk_proc; + aAPC_TALK_SET_PROC talk_set_proc; + aAPC_GET_MSG_NUM_PROC get_msg_num_proc; + aAPC_event_save_data_c* event_save_data_p; +} aAPC_Clip_c; + extern ACTOR_PROFILE Aprilfool_Control_Profile; +typedef struct aprilfool_control_s { + ACTOR actor_class; + aAPC_Clip_c clip; +} APRILFOOL_CONTROL_ACTOR; + #ifdef __cplusplus } #endif diff --git a/include/ac_aprilfool_control_h.h b/include/ac_aprilfool_control_h.h new file mode 100644 index 00000000..2215a3a2 --- /dev/null +++ b/include/ac_aprilfool_control_h.h @@ -0,0 +1,19 @@ +#ifndef AC_APRILFOOL_CONTROL_H_H +#define AC_APRILFOOL_CONTROL_H_H + +#include "types.h" +#include "m_private.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct aprilfool_event_save_data_s { + u16 talk_bitfield[PLAYER_NUM]; +} aAPC_event_save_data_c; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/ac_event_manager.h b/include/ac_event_manager.h index d9ae883f..e0431df6 100644 --- a/include/ac_event_manager.h +++ b/include/ac_event_manager.h @@ -3,11 +3,58 @@ #include "types.h" #include "m_actor.h" +#include "m_npc.h" +#include "m_olib.h" #ifdef __cplusplus extern "C" { #endif +typedef struct event_manager_actor_s EVENT_MANAGER_ACTOR; + +enum { + aEvMgr_EVENT_PLACE_SHRINE = 4, +}; + +typedef int (*aEvMgr_TITLE_FADE_PROC)(EVENT_MANAGER_ACTOR*, int, u8, int); + +typedef struct event_manager_clip_s { + EVENT_MANAGER_ACTOR* event_manager_actor; + aEvMgr_TITLE_FADE_PROC title_fade_proc; +} aEvMgr_Clip_c; + +typedef struct event_manager_field_info_s { + BlockOrUnit_c block_max; + Anmhome_c* reserve_buf; + int reserve_num; +} aEvMgr_field_info_c; + +struct event_manager_actor_s { + ACTOR actor_class; + int player_bx; + int player_bz; + int player_last_bx; + int player_last_bz; + u8 _184[0x1E8 - 0x184]; + aEvMgr_field_info_c field_info; + u8 _1F8[0x208 - 0x1F8]; + int change; + BlockOrUnit_c next_block; + BlockOrUnit_c pool_block; + int pool_block_exists; + BlockOrUnit_c station_block; + int station_block_exists; + BlockOrUnit_c shrine_block; + int shrine_block_exists; + BlockOrUnit_c player_home_block; + int player_home_exists; + BlockOrUnit_c dock_block; + int dock_block_exists; + int _250; + int _254; + aEvMgr_Clip_c clip; +}; + extern ACTOR_PROFILE Event_Manager_Profile; #ifdef __cplusplus diff --git a/include/ac_groundhog_control.h b/include/ac_groundhog_control.h index 36cb168f..8191cc4c 100644 --- a/include/ac_groundhog_control.h +++ b/include/ac_groundhog_control.h @@ -3,11 +3,65 @@ #include "types.h" #include "m_actor.h" +#include "ac_groundhog_control_h.h" #ifdef __cplusplus extern "C" { #endif +#define aGHC_TIME_CHECK(hour, min, sec) (Common_Get(time.now_sec) >= ((hour) * mTM_SECONDS_IN_HOUR + (min) * mTM_SECONDS_IN_MINUTE + (sec))) + +typedef struct groundhog_control_actor_s GROUNDHOG_CONTROL_ACTOR; + +enum { + aGHC_ACTION_BEFORE_800, + aGHC_ACTION_BIRTH_RESET_WAIT, + aGHC_ACTION_BIRTH_RESET, + aGHC_ACTION_RETIRE_RESET_WAIT, + aGHC_ACTION_RESET_SPEECH_BGM_START_WAIT, + aGHC_ACTION_SONCHO_SPEECH_START_WAIT, + aGHC_ACTION_SONCHO_SPEECH_END_WAIT, + aGHC_ACTION_FADE_OUT_START_WAIT, + aGHC_ACTION_AFTER_800, + + aGHC_ACTION_NUM +}; + +enum { + aGHC_ATTENTION_SONCHO, + aGHC_ATTENTION_GROUNDHOG, + + aGHC_ATTENTION_NUM +}; + +enum { + aGHC_EVENT_STATE_NONE, /* nothing to report */ + aGHC_EVENT_STATE_MAJIN_DONE, /* ac_ev_majin signals it is done */ + aGHC_EVENT_STATE_SONCHO_DONE, /* ac_ev_speech_soncho signals it is done */ + + aGHC_EVENT_STATE_NUM +}; + +typedef struct groundhog_control_clip_s { + int now_term; + ACTOR* groundhog_npc_actor; + ACTOR* attention_target_actor; + int fading_title; +} aGHC_Clip_c; + +typedef void (*aGHC_ACTION_PROC)(GROUNDHOG_CONTROL_ACTOR*, GAME_PLAY*); + +struct groundhog_control_actor_s { + ACTOR actor_class; + int action; + aGHC_ACTION_PROC action_proc; + int event_state; + int timer; + aGHC_Clip_c clip; + aGHC_event_area_c* event_area_p; + int attention_mode; +}; + extern ACTOR_PROFILE Groundhog_Control_Profile; #ifdef __cplusplus diff --git a/include/ac_groundhog_control_h.h b/include/ac_groundhog_control_h.h new file mode 100644 index 00000000..605f77cf --- /dev/null +++ b/include/ac_groundhog_control_h.h @@ -0,0 +1,18 @@ +#ifndef AC_GROUNDHOG_CONTROL_H_H +#define AC_GROUNDHOG_CONTROL_H_H + +#include "types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct groundhog_control_event_data_s { + int awaiting_birth; +} aGHC_event_area_c; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/ac_npc.h b/include/ac_npc.h index 1c8f33a7..028e9f01 100644 --- a/include/ac_npc.h +++ b/include/ac_npc.h @@ -20,11 +20,20 @@ typedef struct npc_draw_data_s { u8 _04[0x68]; // TODO } aNPC_draw_data_c; +enum { + aNPC_ATTENTION_TYPE_NONE, + aNPC_ATTENTION_TYPE_ACTOR, + aNPC_ATTENTION_TYPE_POSITION, + + aNPC_ATTENTION_TYPE_NUM +}; + typedef int (*aNPC_SETUP_ACTOR_PROC)(GAME_PLAY*, mActor_name_t, s8, int, s16, int, int, int, int); typedef void (*aNPC_DMA_DRAW_DATA_PROC)(aNPC_draw_data_c*, mActor_name_t); typedef void (*aNPC_FREE_OVERLAY_AREA_PROC)(ACTOR_DLFTBL*); typedef ACTOR* (*aNPC_GET_ACTOR_AREA_PROC)(size_t, const char*, int); typedef void (*aNPC_FREE_ACTOR_AREA_PROC)(ACTOR*); +typedef void (*aNPC_SET_ATTENTION_REQUEST_PROC)(u8, ACTOR*, xyz_t*); typedef int (*aNPC_FORCE_CALL_REQ_PROC)(NPC_ACTOR*, int); @@ -35,7 +44,8 @@ struct ac_npc_clip_s { aNPC_GET_ACTOR_AREA_PROC get_actor_area_proc; aNPC_FREE_ACTOR_AREA_PROC free_actor_area_proc; aNPC_DMA_DRAW_DATA_PROC dma_draw_data_proc; - void* _018[(0x124 - 0x018) / sizeof(void*)]; + aNPC_SET_ATTENTION_REQUEST_PROC set_attention_request_proc; + void* _01C[(0x124 - 0x01C) / sizeof(void*)]; aNPC_FORCE_CALL_REQ_PROC force_call_req_proc; void* _128; }; diff --git a/include/m_bgm.h b/include/m_bgm.h index 53cd6590..c27703d8 100644 --- a/include/m_bgm.h +++ b/include/m_bgm.h @@ -15,6 +15,9 @@ extern void mBGMPsComp_make_ps_wipe(u16 ps_wipe); extern void mBGMPsComp_delete_ps_demo(u8 bgm_num, u16 stop_type); extern void mBGMPsComp_make_ps_demo(u8 bgm_no, u16 stop_type); extern void mBGMPsComp_museum_status(int museum_status); +extern void mBGMPsComp_make_ps_quietField(u16 stop_type); +extern void mBGMPsComp_delete_ps_quietField(); +extern void mBGMPsComp_make_ps_co_quiet(u16 stop_type, s16 frames); #ifdef __cplusplus } diff --git a/include/m_clip.h b/include/m_clip.h index bc0ff0cf..12ac24dd 100644 --- a/include/m_clip.h +++ b/include/m_clip.h @@ -11,6 +11,9 @@ #include "bg_item_h.h" #include "ac_npc.h" #include "ac_tools.h" +#include "ac_aprilfool_control.h" +#include "ac_groundhog_control.h" +#include "ac_event_manager.h" #ifdef __cplusplus extern "C" { @@ -35,7 +38,13 @@ typedef struct clip_s { /* 0x0AC */ aGYO_Clip_c* gyo_clip; /* 0x0B0 */ void* _0B0[(0x0DC - 0x0B0) / sizeof(void*)]; /* 0x0DC */ aAL_Clip_c* animal_logo_clip; - /* 0x0E0 */ void* _0E0[(0x104 - 0x0E0) / sizeof(void*)]; + /* 0x0E0 */ void* _0E0[(0x0EC - 0x0E0) / sizeof(void*)]; + /* 0x0EC */ aAPC_Clip_c* aprilfool_control_clip; + /* 0x0F0 */ aEvMgr_Clip_c* event_manager_clip; + /* 0x0F4 */ aGHC_Clip_c* groundhog_control_clip; + /* 0x0F8 */ void* _0F8; + /* 0x0FC */ void* _0FC; + /* 0x100 */ void* _100; } Clip_c; extern void clip_clear(); diff --git a/include/m_common_data.h b/include/m_common_data.h index 5ddded76..0c03f3a8 100644 --- a/include/m_common_data.h +++ b/include/m_common_data.h @@ -94,7 +94,7 @@ typedef struct Save_s { /* 0x020340 */ Shop_c shop; /* Nook's shop */ /* 0x020480 */ Kabu_price_c kabu_price_schedule; /* Stalk Market info */ /* 0x020498 */ mEv_event_save_c event_save_data; - /* 0x020554 */ u8 _20554[0x20688 - 0x20554]; /* active event data? */ + /* 0x020554 */ mEv_save_common_data_c event_save_common; /* 0x020688 */ mActor_name_t fruit; /* town fruit type */ /* 0x02068A */ u8 house_arrangement; /* 2 bits for each player for the # of house they own */ /* 0x02068B */ u8 num_statues; /* number of statues built for players who have paid off their debts */ @@ -198,7 +198,8 @@ typedef struct common_data_s { /* 0x02666C */ s16 weather; /* 0x02666E */ s16 weather_intensity; /* 0x026670 */ lbRTC_time_c weather_time; - /* 0x026678 */ u8 _26678[0x2669C - 0x26678]; + /* 0x026678 */ u8 _26678[0x26684 - 0x26678]; + /* 0x026684 */ mEv_event_common_u special_event_common; /* 0x02669C */ mQst_not_saved_c quest; /* 0x0266A4 */ int scene_from_title_demo; /* next scene to be loaded when title demo finishes */ /* 0x0266A8 */ mNPS_schedule_c npc_schedule[SCHEDULE_NUM]; @@ -220,8 +221,9 @@ typedef struct common_data_s { /* 0x0285C1 */ u8 _285C1; /* 0x0285C2 */ u8 make_npc2_actor; /* 0x0285C3 */ u8 _285C3[0x0285C6 - 0x0285C3]; - /* 0x0285C6 */ u8 event_id; - /* 0x0285C7 */ u8 _285C7[0x0287F8 - 0x0285C7]; + /* 0x0285C6 */ u8 event_title_flags; + /* 0x0285C7 */ u8 event_title_fade_in_progress; + /* 0x0285C8 */ mEv_common_data_c event_common; /* 0x0287F8 */ s8 current_famicom_rom; /* 0x0287F9 */ s8 famicom_287F9; /* 0x0287FA */ u8 _287FA[0x28838 - 0x0287FA]; @@ -275,7 +277,7 @@ typedef struct common_data_s { /* 0X02DBAC */ int famicom_2DBAC; /* 0x02DBB0 */ s16 can_look_goki_count; /* 0x02DBB4 */ f32 rainbow_opacity; /* current opacity of rainbow (0.0f - 1.0f) */ - /* 0x02DBB8 */ u32 event_flags[7]; /* TODO: make array size a definition/enum */ + /* 0x02DBB8 */ u32 event_flags[mEv_EVENT_TYPE_NUM]; /* 0x02DBD4 */ xyz_t* pluss_bridge_pos; /* position of extra bridge */ /* 0x02DBD8 */ lbRTC_time_c auto_nwrite_time; /* cached notice time used for fishing tourney results? */ /* 0x02DBE0 */ u8 rhythym_updated; diff --git a/include/m_event.h b/include/m_event.h index 200e0763..f91ec0b9 100644 --- a/include/m_event.h +++ b/include/m_event.h @@ -6,11 +6,52 @@ #include "m_personal_id.h" #include "m_private.h" #include "m_time.h" +#include "m_olib.h" #ifdef __cplusplus extern "C" { #endif +#define mEv_TODAY_EVENT_NUM 16 + +#define mEv_SCHEDULE_LAST_WEEKDAY_OF_MONTH 6 /* day of last weekday of the month */ +#define mEv_SCHEDULE_WEEKLY 7 /* scheduled for the desired day this week (e.g. this saturday) */ + +#define mEv_SCHEDULE_MULTIDAY 0x40 /* event scheduled over more than a single day */ +#define mEv_SCHEDULE_TODAY 0x80 /* event will be active on the day loaded */ + +typedef union event_monthday_s { + struct { + s8 month; + s8 day; + }; + u16 raw; +} mEv_MonthDay_u; + +typedef struct event_today_s { + int type; + u32 active_hours; /* bitfield (24 bits) */ + mEv_MonthDay_u begin_date; + mEv_MonthDay_u end_date; + u16 status; + u16 pad; +} mEv_event_today_c; + +typedef struct event_date_s { + struct { + mEv_MonthDay_u month_day; + u8 _2; + u8 hour; + }; + u32 raw; +} mEv_schedule_date_u; + +typedef struct event_schedule_s { + mEv_schedule_date_u date[2]; /* 0 = begin, 1 = end */ + s16 _8; + s16 type; /* event type */ +} mEv_schedule_c; + /** * Event type definition * xxxyyyyy yyyyyyyy yyyyyyyy yyyyyyyy @@ -40,7 +81,7 @@ enum event_type { mEv_DAILY_EVENT, /* checked daily always? aSL_ReportShopOpen2Event has event 3 */ mEv_SPECL_EVENT, /* ??? secondary special npc event data? */ - mEv_EVENT_NUM + mEv_EVENT_TYPE_NUM }; enum events { @@ -111,16 +152,139 @@ enum week_type { }; enum event_table { - mEv_EVENT_MOTHERS_DAY = 23, - mEv_EVENT_FATHERS_DAY = 26, - mEv_EVENT_FISHING_TOURNEY_1 = 29, - mEv_EVENT_MUSHROOM_SEASON = 47, - mEv_EVENT_HALLOWEEN = 49, - mEv_EVENT_FISHING_TOURNEY_2 = 54, - mEv_EVENT_GHOST = 64, - mEv_EVENT_KK_SLIDER = 71, - mEv_EVENT_BROKER_SALE = 75, - mEv_EVENT_SHOP_SALE = 78, + mEv_EVENT_RUMOR_NEW_YEARS_DAY, + mEv_EVENT_NEW_YEARS_DAY, + mEv_EVENT_RUMOR_KAMAKURA, + mEv_EVENT_KAMAKURA, + mEv_EVENT_SONCHO_VACATION_JANUARY, + mEv_EVENT_SONCHO_VACATION_FEBRUARY, + mEv_EVENT_RUMOR_GROUNDHOG_DAY, + mEv_EVENT_GROUNDHOG_DAY, + mEv_EVENT_RUMOR_VALENTINES_DAY, + mEv_EVENT_VALENTINES_DAY, + mEv_EVENT_RUMOR_SPRING_SPORTS_FAIR, + mEv_EVENT_SPRING_EQUINOX, + mEv_EVENT_SPORTS_FAIR_BALL_TOSS, + mEv_EVENT_SPORTS_FAIR_AEROBICS, + mEv_EVENT_SPORTS_FAIR_TUG_OF_WAR, + mEv_EVENT_SPORTS_FAIR_FOOT_RACE, + mEv_EVENT_SPRING_SPORTS_FAIR, + mEv_EVENT_APRILFOOLS_DAY, + mEv_EVENT_RUMOR_APRILFOOLS_DAY, + mEv_EVENT_RUMOR_CHERRY_BLOSSOM_FESTIVAL, + mEv_EVENT_CHERRY_BLOSSOM_FESTIVAL, + mEv_EVENT_NATURE_DAY, + mEv_EVENT_SPRING_CLEANING, + mEv_EVENT_MOTHERS_DAY, + mEv_EVENT_SUMMER_CAMPER, + mEv_EVENT_GRADUATION_DAY, + mEv_EVENT_FATHERS_DAY, + mEv_EVENT_RUMOR_FISHING_TOURNEY_1, + mEv_EVENT_TALK_FISHING_TOURNEY_1, // for dialog? + mEv_EVENT_FISHING_TOURNEY_1, + mEv_EVENT_TOWN_DAY, + mEv_EVENT_RUMOR_FIREWORKS_SHOW, + mEv_EVENT_FIREWORKS_SHOW, + mEv_EVENT_RUMOR_MORNING_AEROBICS, + mEv_EVENT_TALK_MORNING_AEROBICS, + mEv_EVENT_MORNING_AEROBICS, + mEv_EVENT_RUMOR_METEOR_SHOWER, + mEv_EVENT_METEOR_SHOWER, + mEv_EVENT_FOUNDERS_DAY, + mEv_EVENT_LABOR_DAY, + mEv_EVENT_RUMOR_FALL_SPORTS_FAIR, + mEv_EVENT_AUTUMN_EQUINOX, + mEv_EVENT_HARVEST_MOON_DAY, + mEv_EVENT_HARVEST_MOON_FESTIVAL, + mEv_EVENT_EXPLORERS_DAY, + mEv_EVENT_RUMOR_MUSHROOM_SEASON, + mEv_EVENT_TALK_MUSHROOM_SEASON, + mEv_EVENT_MUSHROOM_SEASON, + mEv_EVENT_RUMOR_HALLOWEEN, + mEv_EVENT_HALLOWEEN, + mEv_EVENT_MAYORS_DAY, + mEv_EVENT_OFFICERS_DAY, + mEv_EVENT_RUMOR_FISHING_TOURNEY_2, + mEv_EVENT_TALK_FISHING_TOURNEY_2, + mEv_EVENT_FISHING_TOURNEY_2, + mEv_EVENT_RUMOR_HARVEST_FESTIVAL, + mEv_EVENT_HARVEST_FESTIVAL, + mEv_EVENT_SALE_DAY, + mEv_EVENT_SNOW_DAY, + mEv_EVENT_TOY_DAY_SONCHO, + mEv_EVENT_RUMOR_TOY_DAY, + mEv_EVENT_TOY_DAY_JINGLE, + mEv_EVENT_SNOWMAN_SEASON, + mEv_EVENT_RUMOR_NEW_YEARS_EVE_COUNTDOWN, + mEv_EVENT_NEW_YEARS_EVE_COUNTDOWN, + mEv_EVENT_CHERRY_BLOSSOM_PETALS, + mEv_EVENT_TALK_TOY_DAY, + + mEv_EVENT_PLAYER_BIRTHDAY, + + mEv_EVENT_DOZAEMON, + mEv_EVENT_KABU_PEDDLER, + mEv_EVENT_LOTTERY, + mEv_EVENT_KK_SLIDER, + + mEv_EVENT_HANDBILL_BROKER, + mEv_EVENT_HANDBILL_SHOP_SALE, + + mEv_EVENT_ARTIST, + mEv_EVENT_BROKER_SALE, + mEv_EVENT_DESIGNER, + mEv_EVENT_GYPSY, + mEv_EVENT_SHOP_SALE, + mEv_EVENT_CARPET_PEDDLER, + + mEv_EVENT_SONCHO_NEW_YEARS_DAY, + mEv_EVENT_SONCHO_GROUNDHOG_DAY, + mEv_EVENT_SONCHO_SPRING_SPORTS_FAIR, + mEv_EVENT_SONCHO_APRILFOOLS_DAY, + mEv_EVENT_SONCHO_CHERRY_BLOSSOM_FESTIVAL, + mEv_EVENT_SONCHO_NATURE_DAY, + mEv_EVENT_SONCHO_SPRING_CLEANING, + mEv_EVENT_SONCHO_MOTHERS_DAY, + mEv_EVENT_SONCHO_GRADUATION_DAY, + mEv_EVENT_SONCHO_FATHERS_DAY, + mEv_EVENT_SONCHO_FISHING_TOURNEY_1, + mEv_EVENT_SONCHO_TOWN_DAY, + mEv_EVENT_SONCHO_FIREWORKS_SHOW, + mEv_EVENT_SONCHO_METEOR_SHOWER, + mEv_EVENT_SONCHO_FOUNDERS_DAY, + mEv_EVENT_SONCHO_LABOR_DAY, + mEv_EVENT_SONCHO_FALL_SPORTS_FAIR, + mEv_EVENT_SONCHO_HARVEST_MOON_FESTIVAL, + mEv_EVENT_SONCHO_EXPLORERS_DAY, + mEv_EVENT_SONCHO_HALLOWEEN, + mEv_EVENT_SONCHO_MAYORS_DAY, + mEv_EVENT_SONCHO_OFFICERS_DAY, + mEv_EVENT_SONCHO_FISHING_TOURNEY_2, + mEv_EVENT_SONCHO_HARVEST_FESTIVAL, + mEv_EVENT_SONCHO_SALE_DAY, + mEv_EVENT_SONCHO_SNOW_DAY, + mEv_EVENT_SONCHO_TOY_DAY, + + mEv_EVENT_TALK_NEW_YEARS_COUNTDOWN, + mEv_EVENT_HARVEST_FESTIVAL_FRANKLIN, + + mEv_EVENT_WEATHER_CLEAR, + mEv_EVENT_WEATHER_SNOW, + mEv_EVENT_WEATHER_SPORTS_FAIR, + + mEv_EVENT_BRIDGE_MAKE, + mEv_EVENT_SONCHO_BRIDGE_MAKE, + + mEv_EVENT_GHOST, + mEv_EVENT_MASK_CAT, + + mEv_EVENT_74, // unused? + + mEv_EVENT_KOINOBORI, + + mEv_EVENT_76, // unused? + + mEv_EVENT_NUM }; #define mEv_STATUS_ACTIVE (1 << 0) /* event is active */ @@ -130,6 +294,7 @@ enum event_table { #define mEv_STATUS_RUN (1 << 4) /* event should run */ #define mEv_STATUS_ERROR (1 << 5) /* event is in error state */ #define mEv_STATUS_TALK (1 << 6) /* event requires talking to player */ +#define mEv_STATUS_EXIST (1 << 7) /* event is scheduled */ #define mEv_GHOST_HITODAMA_NUM 5 typedef struct ghost_spirit_block_data_s { @@ -211,7 +376,7 @@ typedef union { typedef struct special_event_s { lbRTC_time_c scheduled; u32 type; - mEv_special_u; + mEv_special_u event; } mEv_special_c; typedef struct save_event_data_s { @@ -220,6 +385,24 @@ typedef struct save_event_data_s { u32 flags; } mEv_event_save_c; +typedef struct broker_event_common_s { + PersonalID_c entered_pid; + int hide_npc; +} mEv_broker_common_c; + +typedef struct santa_event_common_s { + u8 present; + u8 talk_counter; + s8 bx; + s8 bz; + mActor_name_t last_talk_cloth; +} mEv_santa_event_common_c; + +typedef union { + mEv_broker_common_c broker; + mEv_santa_event_common_c santa; +} mEv_event_common_u; + typedef struct event_s { u8 day; u8 hour; @@ -233,18 +416,86 @@ typedef struct event_s { int unused[5]; } Event_c; +typedef struct event_info_s { + s8 type; + s8 id; + u16 year; + mEv_MonthDay_u start_date; + mEv_MonthDay_u end_date; +} mEv_info_c; + +typedef struct event_place_data_s { + BlockOrUnit_c block; + BlockOrUnit_c unit; + mActor_name_t actor_name; + s16 flag; +} mEv_place_data_c; + +typedef struct event_place_s { + mEv_info_c info; + mEv_place_data_c data; +} mEv_place_c; + +typedef struct event_area_s { + mEv_info_c info; + int data[11]; +} mEv_area_c; + +typedef struct event_common_s { + s16 _00; + s16 area_use_bitfield; + mEv_area_c area[5]; + s16 too_short; + s16 place_use_bitfield; + mEv_place_c place[10]; + s16 fieldday_event_id; + s16 fieldday_event_over_status; + u32 unused[2]; +} mEv_common_data_c; + +typedef struct event_save_event_info_s { + s8 type; + s8 flags; +} mEv_event_save_info_c; + +typedef struct event_common_save_data { + mEv_event_save_info_c special_event; + mEv_event_save_info_c weekly_event; + u16 dates[8]; + int area_use_bitfield; + mEv_area_c area[5]; + int last_date; + int _120; + u32 valentines_day_date; + u32 white_day_date; /* unused in AC */ + u16 ghost_day; + u16 bridge_day; // last date suspension bridge event was active + struct { + u8 used_all_locations:1; // set to true when tortimer has cycled through all possible bridge locations? + u8 locations_used:7; // index of river acre w/ possible bridge location currently at + } bridge_flags; + u8 ghost_event_type; // 0x72 will spawn wisp, 0x77 won't? + u8 soncho_event_type; // checked not equal to 0xFF for summer & fall fishing tournies + u8 current_event_state; // used to signal when you've received an item from gracie or woken gulliver up +} mEv_save_common_data_c; + extern int mEv_CheckFirstJob(); extern int mEv_CheckFirstIntro(); extern int mEv_CheckArbeit(); extern int mEv_CheckTitleDemo(); extern int mEv_check_status(int event, s16 status); extern s8* mEv_get_common_area(int type, s8 id); +extern s8* mEv_reserve_common_area(int type, s8 id); extern s8* mEv_get_save_area(int type, s8 id); +extern s8* mEv_reserve_save_area(int type, s8 id); +extern void mEv_actor_dying_message(int type, ACTOR* actor); extern int mEv_ArbeitPlayer(u32 player_no); extern u16 mEv_get_special_event_type(); -extern int mEv_ClearEventSaveInfo(mEv_event_save_c* event_save_data); +extern void mEv_ClearEventSaveInfo(mEv_event_save_c* event_save_data); extern void mEv_EventON(u32 event_kind); extern int mEv_CheckGateway(); +extern int mEv_check_schedule(int event); +extern mEv_place_data_c* mEv_get_common_place(int type, s8 id); extern int mEv_weekday2day(lbRTC_month_t month, int week_type, lbRTC_weekday_t weekday); extern void mEv_ClearEventInfo(); diff --git a/include/m_name_table.h b/include/m_name_table.h index eeb60f8b..8f3ca288 100644 --- a/include/m_name_table.h +++ b/include/m_name_table.h @@ -288,127 +288,127 @@ extern mActor_name_t bg_item_fg_sub_dig2take_conv(mActor_name_t item); /* begin environmental/nature objects */ #define ENV_START 0x0800 /* tree */ -#define TREE_SAPLING ENV_START -#define TREE_S0 (TREE_SAPLING + 1) -#define TREE_S1 (TREE_S0 + 1) -#define TREE_S2 (TREE_S1 + 1) -#define TREE (TREE_S2 + 1) /* fully grown */ +#define TREE_SAPLING (ENV_START + 0) +#define TREE_S0 (ENV_START + 1) +#define TREE_S1 (ENV_START + 2) +#define TREE_S2 (ENV_START + 3) +#define TREE (ENV_START + 4) /* fully grown */ /* apple tree */ -#define TREE_APPLE_SAPLING (TREE + 1) -#define TREE_APPLE_S0 (TREE_APPLE_SAPLING + 1) -#define TREE_APPLE_S1 (TREE_APPLE_S0 + 1) -#define TREE_APPLE_S2 (TREE_APPLE_S1 + 1) -#define TREE_APPLE_NOFRUIT_0 (TREE_APPLE_S2 + 1) /* fully grown, no fruit */ -#define TREE_APPLE_NOFRUIT_1 (TREE_APPLE_NOFRUIT_0 + 1) -#define TREE_APPLE_NOFRUIT_2 (TREE_APPLE_NOFRUIT_1 + 1) -#define TREE_APPLE_FRUIT (TREE_APPLE_NOFRUIT_2 + 1) +#define TREE_APPLE_SAPLING (ENV_START + 5) +#define TREE_APPLE_S0 (ENV_START + 6) +#define TREE_APPLE_S1 (ENV_START + 7) +#define TREE_APPLE_S2 (ENV_START + 8) +#define TREE_APPLE_NOFRUIT_0 (ENV_START + 9) /* fully grown, no fruit */ +#define TREE_APPLE_NOFRUIT_1 (ENV_START + 10) +#define TREE_APPLE_NOFRUIT_2 (ENV_START + 11) +#define TREE_APPLE_FRUIT (ENV_START + 12) /* orange tree */ -#define TREE_ORANGE_SAPLING (TREE_APPLE_FRUIT + 1) -#define TREE_ORANGE_S0 (TREE_ORANGE_SAPLING + 1) -#define TREE_ORANGE_S1 (TREE_ORANGE_S0 + 1) -#define TREE_ORANGE_S2 (TREE_ORANGE_S1 + 1) /* fully grown, no fruit */ -#define TREE_ORANGE_NOFRUIT_0 (TREE_ORANGE_S2 + 1) -#define TREE_ORANGE_NOFRUIT_1 (TREE_ORANGE_NOFRUIT_0 + 1) -#define TREE_ORANGE_NOFRUIT_2 (TREE_ORANGE_NOFRUIT_1 + 1) -#define TREE_ORANGE_FRUIT (TREE_ORANGE_NOFRUIT_2 + 1) +#define TREE_ORANGE_SAPLING (ENV_START + 13) +#define TREE_ORANGE_S0 (ENV_START + 14) +#define TREE_ORANGE_S1 (ENV_START + 15) +#define TREE_ORANGE_S2 (ENV_START + 16) /* fully grown, no fruit */ +#define TREE_ORANGE_NOFRUIT_0 (ENV_START + 17) +#define TREE_ORANGE_NOFRUIT_1 (ENV_START + 18) +#define TREE_ORANGE_NOFRUIT_2 (ENV_START + 19) +#define TREE_ORANGE_FRUIT (ENV_START + 20) /* peach tree */ -#define TREE_PEACH_SAPLING (TREE_ORANGE_FRUIT + 1) -#define TREE_PEACH_S0 (TREE_PEACH_SAPLING + 1) -#define TREE_PEACH_S1 (TREE_PEACH_S0 + 1) -#define TREE_PEACH_S2 (TREE_PEACH_S1 + 1) -#define TREE_PEACH_NOFRUIT_0 (TREE_PEACH_S2 + 1) /* fully grown, no fruit */ -#define TREE_PEACH_NOFRUIT_1 (TREE_PEACH_NOFRUIT_0 + 1) -#define TREE_PEACH_NOFRUIT_2 (TREE_PEACH_NOFRUIT_1 + 1) -#define TREE_PEACH_FRUIT (TREE_PEACH_NOFRUIT_2 + 1) +#define TREE_PEACH_SAPLING (ENV_START + 21) +#define TREE_PEACH_S0 (ENV_START + 22) +#define TREE_PEACH_S1 (ENV_START + 23) +#define TREE_PEACH_S2 (ENV_START + 24) +#define TREE_PEACH_NOFRUIT_0 (ENV_START + 25) /* fully grown, no fruit */ +#define TREE_PEACH_NOFRUIT_1 (ENV_START + 26) +#define TREE_PEACH_NOFRUIT_2 (ENV_START + 27) +#define TREE_PEACH_FRUIT (ENV_START + 28) /* pear tree */ -#define TREE_PEAR_SAPLING (TREE_PEACH_FRUIT + 1) -#define TREE_PEAR_S0 (TREE_PEAR_SAPLING + 1) -#define TREE_PEAR_S1 (TREE_PEAR_S0 + 1) -#define TREE_PEAR_S2 (TREE_PEAR_S1 + 1) -#define TREE_PEAR_NOFRUIT_0 (TREE_PEAR_S2 + 1) /* fully grown, no fruit */ -#define TREE_PEAR_NOFRUIT_1 (TREE_PEAR_NOFRUIT_0 + 1) -#define TREE_PEAR_NOFRUIT_2 (TREE_PEAR_NOFRUIT_1 + 1) -#define TREE_PEAR_FRUIT (TREE_PEAR_NOFRUIT_2 + 1) +#define TREE_PEAR_SAPLING (ENV_START + 29) +#define TREE_PEAR_S0 (ENV_START + 30) +#define TREE_PEAR_S1 (ENV_START + 31) +#define TREE_PEAR_S2 (ENV_START + 32) +#define TREE_PEAR_NOFRUIT_0 (ENV_START + 33) /* fully grown, no fruit */ +#define TREE_PEAR_NOFRUIT_1 (ENV_START + 34) +#define TREE_PEAR_NOFRUIT_2 (ENV_START + 35) +#define TREE_PEAR_FRUIT (ENV_START + 36) /* cherry tree */ -#define TREE_CHERRY_SAPLING (TREE_PEAR_FRUIT + 1) -#define TREE_CHERRY_S0 (TREE_CHERRY_SAPLING + 1) -#define TREE_CHERRY_S1 (TREE_CHERRY_S0 + 1) -#define TREE_CHERRY_S2 (TREE_CHERRY_S1 + 1) -#define TREE_CHERRY_NOFRUIT_0 (TREE_CHERRY_S2 + 1) /* fully grown, no fruit */ -#define TREE_CHERRY_NOFRUIT_1 (TREE_CHERRY_NOFRUIT_0 + 1) -#define TREE_CHERRY_NOFRUIT_2 (TREE_CHERRY_NOFRUIT_1 + 1) -#define TREE_CHERRY_FRUIT (TREE_CHERRY_NOFRUIT_2 + 1) +#define TREE_CHERRY_SAPLING (ENV_START + 37) +#define TREE_CHERRY_S0 (ENV_START + 38) +#define TREE_CHERRY_S1 (ENV_START + 39) +#define TREE_CHERRY_S2 (ENV_START + 40) +#define TREE_CHERRY_NOFRUIT_0 (ENV_START + 41) /* fully grown, no fruit */ +#define TREE_CHERRY_NOFRUIT_1 (ENV_START + 42) +#define TREE_CHERRY_NOFRUIT_2 (ENV_START + 43) +#define TREE_CHERRY_FRUIT (ENV_START + 44) /* money tree (1,000 Bells) */ -#define TREE_1000BELLS_SAPLING (TREE_CHERRY_FRUIT + 1) -#define TREE_1000BELLS_S0 (TREE_1000BELLS_SAPLING + 1) -#define TREE_1000BELLS_S1 (TREE_1000BELLS_S0 + 1) -#define TREE_1000BELLS_S2 (TREE_1000BELLS_S1 + 1) -#define TREE_1000BELLS (TREE_1000BELLS_S2 + 1) /* fully grown w/ bells */ +#define TREE_1000BELLS_SAPLING (ENV_START + 45) +#define TREE_1000BELLS_S0 (ENV_START + 46) +#define TREE_1000BELLS_S1 (ENV_START + 47) +#define TREE_1000BELLS_S2 (ENV_START + 48) +#define TREE_1000BELLS (ENV_START + 49) /* fully grown w/ bells */ /* money tree (10,000 Bells) */ -#define TREE_10000BELLS_SAPLING (TREE_1000BELLS + 1) -#define TREE_10000BELLS_S0 (TREE_10000BELLS_SAPLING + 1) -#define TREE_10000BELLS_S1 (TREE_10000BELLS_S0 + 1) -#define TREE_10000BELLS_S2 (TREE_10000BELLS_S1 + 1) -#define TREE_10000BELLS (TREE_10000BELLS_S2 + 1) /* fully grown w/ bells */ +#define TREE_10000BELLS_SAPLING (ENV_START + 50) +#define TREE_10000BELLS_S0 (ENV_START + 51) +#define TREE_10000BELLS_S1 (ENV_START + 52) +#define TREE_10000BELLS_S2 (ENV_START + 53) +#define TREE_10000BELLS (ENV_START + 54) /* fully grown w/ bells */ /* money tree (30,000 Bells) */ -#define TREE_30000BELLS_SAPLING (TREE_10000BELLS + 1) -#define TREE_30000BELLS_S0 (TREE_30000BELLS_SAPLING + 1) -#define TREE_30000BELLS_S1 (TREE_30000BELLS_S0 + 1) -#define TREE_30000BELLS_S2 (TREE_30000BELLS_S1 + 1) -#define TREE_30000BELLS (TREE_30000BELLS_S2 + 1) /* fully grown w/ bells */ +#define TREE_30000BELLS_SAPLING (ENV_START + 55) +#define TREE_30000BELLS_S0 (ENV_START + 56) +#define TREE_30000BELLS_S1 (ENV_START + 57) +#define TREE_30000BELLS_S2 (ENV_START + 58) +#define TREE_30000BELLS (ENV_START + 59) /* fully grown w/ bells */ /* flower leaves (unused growth stage) */ -#define FLOWER_LEAVES_PANSIES0 (TREE_30000BELLS + 1) /* white */ -#define FLOWER_LEAVES_PANSIES1 (FLOWER_LEAVES_PANSIES0 + 1) /* purple */ -#define FLOWER_LEAVES_PANSIES2 (FLOWER_LEAVES_PANSIES1 + 1) /* yellow */ -#define FLOWER_LEAVES_COSMOS0 (FLOWER_LEAVES_PANSIES2 + 1) /* yellow */ -#define FLOWER_LEAVES_COSMOS1 (FLOWER_LEAVES_COSMOS0 + 1) /* purple */ -#define FLOWER_LEAVES_COSMOS2 (FLOWER_LEAVES_COSMOS1 + 1) /* blue */ -#define FLOWER_LEAVES_TULIP0 (FLOWER_LEAVES_COSMOS2 + 1) /* red */ -#define FLOWER_LEAVES_TULIP1 (FLOWER_LEAVES_TULIP0 + 1) /* white */ -#define FLOWER_LEAVES_TULIP2 (FLOWER_LEAVES_TULIP1 + 1) /* yellow */ +#define FLOWER_LEAVES_PANSIES0 (ENV_START + 60) /* white */ +#define FLOWER_LEAVES_PANSIES1 (ENV_START + 61) /* purple */ +#define FLOWER_LEAVES_PANSIES2 (ENV_START + 62) /* yellow */ +#define FLOWER_LEAVES_COSMOS0 (ENV_START + 63) /* yellow */ +#define FLOWER_LEAVES_COSMOS1 (ENV_START + 64) /* purple */ +#define FLOWER_LEAVES_COSMOS2 (ENV_START + 65) /* blue */ +#define FLOWER_LEAVES_TULIP0 (ENV_START + 66) /* red */ +#define FLOWER_LEAVES_TULIP1 (ENV_START + 67) /* white */ +#define FLOWER_LEAVES_TULIP2 (ENV_START + 68) /* yellow */ /* flowers */ -#define FLOWER_PANSIES0 (FLOWER_LEAVES_TULIP2 + 1) /* white */ -#define FLOWER_PANSIES1 (FLOWER_PANSIES0 + 1) /* purple */ -#define FLOWER_PANSIES2 (FLOWER_PANSIES1 + 1) /* yellow */ -#define FLOWER_COSMOS0 (FLOWER_PANSIES2 + 1) /* yellow */ -#define FLOWER_COSMOS1 (FLOWER_COSMOS0 + 1) /* purple */ -#define FLOWER_COSMOS2 (FLOWER_COSMOS1 + 1) /* blue */ -#define FLOWER_TULIP0 (FLOWER_COSMOS2 + 1) /* red */ -#define FLOWER_TULIP1 (FLOWER_TULIP0 + 1) /* white */ -#define FLOWER_TULIP2 (FLOWER_TULIP1 + 1) /* yellow */ +#define FLOWER_PANSIES0 (ENV_START + 69) /* white */ +#define FLOWER_PANSIES1 (ENV_START + 70) /* purple */ +#define FLOWER_PANSIES2 (ENV_START + 71) /* yellow */ +#define FLOWER_COSMOS0 (ENV_START + 72) /* yellow */ +#define FLOWER_COSMOS1 (ENV_START + 73) /* purple */ +#define FLOWER_COSMOS2 (ENV_START + 74) /* blue */ +#define FLOWER_TULIP0 (ENV_START + 75) /* red */ +#define FLOWER_TULIP1 (ENV_START + 76) /* white */ +#define FLOWER_TULIP2 (ENV_START + 77) /* yellow */ /* dead sapling */ -#define DEAD_SAPLING (FLOWER_TULIP2 + 1) +#define DEAD_SAPLING (ENV_START + 78) /* money tree (100 Bells) */ -#define TREE_100BELLS_SAPLING (DEAD_SAPLING + 1) -#define TREE_100BELLS_S0 (TREE_100BELLS_SAPLING + 1) -#define TREE_100BELLS_S1 (TREE_100BELLS_S0 + 1) -#define TREE_100BELLS_S2 (TREE_100BELLS_S1 + 1) -#define TREE_100BELLS (TREE_100BELLS_S2 + 1) /* fully grown w/ bells */ +#define TREE_100BELLS_SAPLING (ENV_START + 79) +#define TREE_100BELLS_S0 (ENV_START + 80) +#define TREE_100BELLS_S1 (ENV_START + 81) +#define TREE_100BELLS_S2 (ENV_START + 82) +#define TREE_100BELLS (ENV_START + 83) /* fully grown w/ bells */ /* palm tree */ -#define TREE_PALM_SAPLING (TREE_100BELLS + 1) -#define TREE_PALM_S0 (TREE_PALM_SAPLING + 1) -#define TREE_PALM_S1 (TREE_PALM_S0 + 1) -#define TREE_PALM_S2 (TREE_PALM_S1 + 1) -#define TREE_PALM_NOFRUIT_0 (TREE_PALM_S2 + 1) /* fully grown, no fruit */ -#define TREE_PALM_NOFRUIT_1 (TREE_PALM_NOFRUIT_0 + 1) -#define TREE_PALM_NOFRUIT_2 (TREE_PALM_NOFRUIT_1 + 1) -#define TREE_PALM_FRUIT (TREE_PALM_NOFRUIT_2 + 1) -#define DEAD_PALM_SAPLING (TREE_PALM_FRUIT + 1) +#define TREE_PALM_SAPLING (ENV_START + 84) +#define TREE_PALM_S0 (ENV_START + 85) +#define TREE_PALM_S1 (ENV_START + 86) +#define TREE_PALM_S2 (ENV_START + 87) +#define TREE_PALM_NOFRUIT_0 (ENV_START + 88) /* fully grown, no fruit */ +#define TREE_PALM_NOFRUIT_1 (ENV_START + 89) +#define TREE_PALM_NOFRUIT_2 (ENV_START + 90) +#define TREE_PALM_FRUIT (ENV_START + 91) +#define DEAD_PALM_SAPLING (ENV_START + 92) /* cedar tree */ -#define CEDAR_TREE_SAPLING (DEAD_PALM_SAPLING + 1) -#define CEDAR_TREE_S0 (CEDAR_TREE_SAPLING + 1) -#define CEDAR_TREE_S1 (CEDAR_TREE_S0 + 1) -#define CEDAR_TREE_S2 (CEDAR_TREE_S1 + 1) -#define CEDAR_TREE (CEDAR_TREE_S2 + 1) /* fully grown */ -#define DEAD_CEDAR_SAPLING (CEDAR_TREE + 1) +#define CEDAR_TREE_SAPLING (ENV_START + 93) +#define CEDAR_TREE_S0 (ENV_START + 94) +#define CEDAR_TREE_S1 (ENV_START + 95) +#define CEDAR_TREE_S2 (ENV_START + 96) +#define CEDAR_TREE (ENV_START + 97) /* fully grown */ +#define DEAD_CEDAR_SAPLING (ENV_START + 98) /* gold tree */ -#define GOLD_TREE_SAPLING (DEAD_CEDAR_SAPLING + 1) -#define GOLD_TREE_S0 (GOLD_TREE_SAPLING + 1) -#define GOLD_TREE_S1 (GOLD_TREE_S0 + 1) -#define GOLD_TREE_S2 (GOLD_TREE_S1 + 1) -#define GOLD_TREE_SHOVEL (GOLD_TREE_S2 + 1) /* fully grown w/ golden shovel */ -#define GOLD_TREE (GOLD_TREE_SHOVEL + 1) /* fully grown */ -#define DEAD_GOLD_SAPLING (GOLD_TREE + 1) +#define GOLD_TREE_SAPLING (ENV_START + 99) +#define GOLD_TREE_S0 (ENV_START + 100) +#define GOLD_TREE_S1 (ENV_START + 101) +#define GOLD_TREE_S2 (ENV_START + 102) +#define GOLD_TREE_SHOVEL (ENV_START + 103) /* fully grown w/ golden shovel */ +#define GOLD_TREE (ENV_START + 104) /* fully grown */ +#define DEAD_GOLD_SAPLING (ENV_START + 105) /* end of environmental objects */ #define SIGNBOARD_START 0x0900 diff --git a/include/m_olib.h b/include/m_olib.h index 87fc7ba8..dc2bea2c 100644 --- a/include/m_olib.h +++ b/include/m_olib.h @@ -19,6 +19,11 @@ typedef struct rect_s { int l, r; } rect; +typedef struct generic_unit_s { + int z; + int x; +} BlockOrUnit_c; + extern void radianxy_by_2pos(xyz_t* dest, xyz_t* sub, xyz_t* min); extern s_xyz sanglexy_by_2pos(xyz_t* sub, xyz_t* min); diff --git a/rel/ac_aprilfool_control.c b/rel/ac_aprilfool_control.c new file mode 100644 index 00000000..e9f25665 --- /dev/null +++ b/rel/ac_aprilfool_control.c @@ -0,0 +1,147 @@ +#include "ac_aprilfool_control.h" + +#include "m_event.h" +#include "m_name_table.h" +#include "m_common_data.h" + +static void aAPC_actor_ct(ACTOR* actor, GAME* game); +static void aAPC_actor_dt(ACTOR* actor, GAME* game); + +ACTOR_PROFILE Aprilfool_Control_Profile = { + mAc_PROFILE_APRILFOOL_CONTROL, + ACTOR_PART_CONTROL, + ACTOR_STATE_NO_MOVE_WHILE_CULLED, + EMPTY_NO, + ACTOR_OBJ_BANK_3, + sizeof(APRILFOOL_CONTROL_ACTOR), + &aAPC_actor_ct, + &aAPC_actor_dt, + mActor_NONE_PROC1, + mActor_NONE_PROC1, + NULL +}; + +static int aAPC_talk_chk_proc(mActor_name_t actor_name); +static void aAPC_talk_set_proc(mActor_name_t actor_name); +static int aAPC_get_msg_num_proc(mActor_name_t actor_name, int update_talked); + +static void aAPC_actor_ct(ACTOR* actor, GAME* game) { + APRILFOOL_CONTROL_ACTOR* aprilfool_control = (APRILFOOL_CONTROL_ACTOR*)actor; + aAPC_event_save_data_c* save_data; + + if (Common_Get(clip).aprilfool_control_clip == NULL) { + Common_Get(clip).aprilfool_control_clip = &aprilfool_control->clip; + } + + save_data = (aAPC_event_save_data_c*)mEv_get_save_area(mEv_EVENT_APRILFOOLS_DAY, 0); + if (save_data == NULL) { + save_data = (aAPC_event_save_data_c*)mEv_reserve_save_area(mEv_EVENT_APRILFOOLS_DAY, 0); + bzero(save_data, sizeof(aAPC_event_save_data_c)); + } + + Common_Get(clip).aprilfool_control_clip->talk_chk_proc = &aAPC_talk_chk_proc; + Common_Get(clip).aprilfool_control_clip->talk_set_proc = &aAPC_talk_set_proc; + Common_Get(clip).aprilfool_control_clip->get_msg_num_proc = &aAPC_get_msg_num_proc; + Common_Get(clip).aprilfool_control_clip->event_save_data_p = save_data; +} + +static void aAPC_actor_dt(ACTOR* actor, GAME* game) { + Common_Get(clip).aprilfool_control_clip = NULL; + mEv_actor_dying_message(mEv_EVENT_APRILFOOLS_DAY, actor); +} + +typedef struct aprilfool_npc_data_s { + mActor_name_t actor_name; + u16 data_idx; +} aAPC_npc_data_c; + +static int aAPC_get_data_idx(mActor_name_t actor_name) { + static aAPC_npc_data_c npc_data_table[11] = { + { SP_NPC_STATION_MASTER, 0x0000 }, /* Porter */ + { SP_NPC_SHOP_MASTER, 0x0001 }, /* Tom Nook */ + { SP_NPC_CURATOR, 0x0002 }, /* Blathers */ + { SP_NPC_NEEDLEWORK0, 0x0003 }, /* Mable */ + { SP_NPC_NEEDLEWORK1, 0x0004 }, /* Sable */ + { SP_NPC_POLICE, 0x0005 }, /* Copper */ + { SP_NPC_POLICE2, 0x0006 }, /* Booker */ + { SP_NPC_POST_GIRL, 0x0007 }, /* Pelly */ + { SP_NPC_POST_GIRL2, 0x0008 }, /* Phyllis */ + { SP_NPC_POST_MAN, 0x0009 }, /* Pete */ + { SP_NPC_SENDO, 0x000A } /* Kapp'n */ + }; + + aAPC_npc_data_c* npc_data_p = npc_data_table; + int i; + int res = -1; + + for (i = 0; i < 11; i++) { + if (npc_data_p->actor_name == actor_name) { + res = npc_data_p->data_idx; + break; + } + + npc_data_p++; + } + + return res; +} + +static int aAPC_talk_chk_proc(mActor_name_t actor_name) { + int res = TRUE; + + if (mLd_PlayerManKindCheck() == FALSE) { + int data_idx = aAPC_get_data_idx(actor_name); + + if (data_idx != -1) { + u16 bitfield = Common_Get(clip).aprilfool_control_clip->event_save_data_p->talk_bitfield[Common_Get(player_no)]; + + if (aAPC_GET_NPC_BIT(bitfield, data_idx) == 0) { + res = FALSE; + } + } + } + + return res; +} + +static void aAPC_talk_set_proc(mActor_name_t actor_name) { + int data_idx = aAPC_get_data_idx(actor_name); + + if (data_idx != -1) { + u16* bitfield = &Common_Get(clip).aprilfool_control_clip->event_save_data_p->talk_bitfield[Common_Get(player_no)]; + data_idx = 1 << data_idx; + + bitfield[0] |= data_idx; + } +} + +static int aAPC_get_msg_num_proc(mActor_name_t actor_name, int update_talked) { + static int msg_num_table[11] = { + 0x3BB5, + 0x3BAC, + 0x3BB0, + 0x3BB1, + 0x3BB2, + 0x3BB3, + 0x3BB4, + 0x3BAE, + 0x3BAF, + 0x3BAD, + 0x3BB6 + }; + + int data_idx = aAPC_get_data_idx(actor_name); + int msg_num = -1; + + if (data_idx != -1) { + if (update_talked == TRUE) { + u16* bitfield = &Common_Get(clip).aprilfool_control_clip->event_save_data_p->talk_bitfield[Common_Get(player_no)]; + + bitfield[0] = aAPC_SET_NPC_BIT(bitfield[0], data_idx); + } + + msg_num = msg_num_table[data_idx]; + } + + return msg_num; +} diff --git a/rel/ac_aprilfool_control/aPC_actor_dt.c b/rel/ac_aprilfool_control/aPC_actor_dt.c deleted file mode 100644 index 46191f90..00000000 --- a/rel/ac_aprilfool_control/aPC_actor_dt.c +++ /dev/null @@ -1,4 +0,0 @@ -void aAPC_actor_dt(void * arg0_r3) { - common_data[2].x60F8 = 0; - mEv_actor_dying_message(0x11, arg0_r3); -} \ No newline at end of file diff --git a/rel/ac_groundhog_control.c b/rel/ac_groundhog_control.c new file mode 100644 index 00000000..0d0f9f1f --- /dev/null +++ b/rel/ac_groundhog_control.c @@ -0,0 +1,221 @@ +#include "ac_groundhog_control.h" + +#include "m_bgm.h" +#include "m_name_table.h" +#include "m_common_data.h" + +static void aGHC_actor_ct(ACTOR* actor, GAME* game); +static void aGHC_actor_dt(ACTOR* actor, GAME* game); +static void aGHC_actor_move(ACTOR* actor, GAME* game); + +ACTOR_PROFILE Groundhog_Control_Profile = { + mAc_PROFILE_GROUNDHOG_CONTROL, + ACTOR_PART_CONTROL, + ACTOR_STATE_NO_MOVE_WHILE_CULLED, + EMPTY_NO, + ACTOR_OBJ_BANK_3, + sizeof(GROUNDHOG_CONTROL_ACTOR), + &aGHC_actor_ct, + &aGHC_actor_dt, + &aGHC_actor_move, + mActor_NONE_PROC1, + NULL +}; + +static int aGHC_get_now_term(); +static void aGHC_setupAction(GROUNDHOG_CONTROL_ACTOR* groundhog_control, int action); + +static void aGHC_actor_ct(ACTOR* actor, GAME* game) { + GROUNDHOG_CONTROL_ACTOR* groundhog_control = (GROUNDHOG_CONTROL_ACTOR*)actor; + int action = aGHC_ACTION_BEFORE_800; + aGHC_event_area_c* event_area; + + if (aGHC_TIME_CHECK(8, 0, 0)) { + action = aGHC_ACTION_AFTER_800; + } + + if (Common_Get(clip).groundhog_control_clip == NULL) { + Common_Get(clip).groundhog_control_clip = &groundhog_control->clip; + Common_Get(clip).groundhog_control_clip->now_term = aGHC_get_now_term(); + } + + event_area = (aGHC_event_area_c*)mEv_get_common_area(mEv_EVENT_GROUNDHOG_DAY, 0); + + if (event_area == NULL) { + event_area = (aGHC_event_area_c*)mEv_reserve_common_area(mEv_EVENT_GROUNDHOG_DAY, 0); + } + else if (event_area->awaiting_birth == TRUE) { + action = aGHC_ACTION_BIRTH_RESET_WAIT; + groundhog_control->timer = 600; + } + + groundhog_control->event_area_p = event_area; + aGHC_setupAction(groundhog_control, action); +} + +static void aGHC_actor_dt(ACTOR* actor, GAME* game) { + Common_Get(clip).groundhog_control_clip = NULL; + mEv_actor_dying_message(mEv_EVENT_GROUNDHOG_DAY, actor); +} + +static int aGHC_get_now_term() { + int res; + + if (aGHC_TIME_CHECK(8, 0, 0)) { + res = 5; + } + else if (aGHC_TIME_CHECK(7, 59, 0)) { + res = 4; + } + else if (aGHC_TIME_CHECK(7, 55, 0)) { + res = 3; + } + else if (aGHC_TIME_CHECK(7, 45, 0)) { + res = 2; + } + else if (aGHC_TIME_CHECK(7, 30, 0)) { + res = 1; + } + else { + res = 0; + } + + return res; +} + +static void aGHC_search_soncho(GAME_PLAY* play) { + if (Common_Get(clip).groundhog_control_clip->attention_target_actor == NULL) { + Common_Get(clip).groundhog_control_clip->attention_target_actor = Actor_info_fgName_search(&play->actor_info, SP_NPC_EV_SPEECH_SONCHO, ACTOR_PART_NPC); + } +} + +static void aGHC_set_attention_request(int groundhog_is_target) { + ACTOR* attention_target = NULL; + + if (groundhog_is_target == FALSE) { + if (Common_Get(clip).groundhog_control_clip->attention_target_actor != NULL) { + attention_target = Common_Get(clip).groundhog_control_clip->attention_target_actor; + } + } + else if (Common_Get(clip).groundhog_control_clip->groundhog_npc_actor != NULL) { + attention_target = Common_Get(clip).groundhog_control_clip->groundhog_npc_actor; + } + + if (attention_target != NULL) { + (*Common_Get(clip).npc_clip->set_attention_request_proc)(aNPC_ATTENTION_TYPE_ACTOR, attention_target, NULL); + } +} + +static void aGHC_before_800(GROUNDHOG_CONTROL_ACTOR* groundhog_control, GAME_PLAY* play) { + if (aGHC_TIME_CHECK(8, 0, 0) && Common_Get(clip).event_manager_clip != NULL) { + EVENT_MANAGER_ACTOR* event_manager = Common_Get(clip).event_manager_clip->event_manager_actor; + Common_Get(clip).groundhog_control_clip->fading_title = TRUE; + + if ((*Common_Get(clip).event_manager_clip->title_fade_proc)(event_manager, mEv_EVENT_GROUNDHOG_DAY, 1, aEvMgr_EVENT_PLACE_SHRINE)) { + Common_Get(clip).groundhog_control_clip->fading_title = FALSE; + groundhog_control->event_area_p->awaiting_birth = TRUE; + } + } +} + +static void aGHC_birth_reset_wait(GROUNDHOG_CONTROL_ACTOR* groundhog_control, GAME_PLAY* play) { + groundhog_control->timer--; + + if (groundhog_control->timer <= 0) { + aGHC_setupAction(groundhog_control, aGHC_ACTION_BIRTH_RESET); + } +} + +static void aGHC_birth_reset(GROUNDHOG_CONTROL_ACTOR* groundhog_control, GAME_PLAY* play) { + int bx; + int bz; + + if (Common_Get(clip).npc_clip != NULL && Common_Get(clip).npc_clip->setupActor_proc != NULL && mFI_BlockKind2BkNum(&bx, &bz, mRF_BLOCKKIND_SHRINE) == TRUE) { + int spawned_actor = (*Common_Get(clip).npc_clip->setupActor_proc)(play, SP_NPC_EV_MAJIN, -1, -1, -1, bx, bz, 5, 8); + + if (spawned_actor == TRUE) { + ACTOR* groundhog_actor = Actor_info_fgName_search(&play->actor_info, SP_NPC_EV_MAJIN, ACTOR_PART_NPC); + + groundhog_actor->parent_actor = (ACTOR*)groundhog_control; + Common_Get(clip).groundhog_control_clip->groundhog_npc_actor = groundhog_actor; + groundhog_control->event_area_p->awaiting_birth = FALSE; + groundhog_control->attention_mode = aGHC_ATTENTION_GROUNDHOG; + mBGMPsComp_make_ps_quietField(360); + groundhog_control->timer = 240; + aGHC_setupAction(groundhog_control, aGHC_ACTION_RESET_SPEECH_BGM_START_WAIT); + } + } +} + +static void aGHC_reset_speech_bgm_start_wait(GROUNDHOG_CONTROL_ACTOR* groundhog_control, GAME_PLAY* play) { + groundhog_control->timer--; + + if (groundhog_control->timer <= 0) { + mBGMPsComp_make_ps_demo(252, 360); + aGHC_setupAction(groundhog_control, aGHC_ACTION_RETIRE_RESET_WAIT); + } +} + +static void aGHC_retire_reset_wait(GROUNDHOG_CONTROL_ACTOR* groundhog_control, GAME_PLAY* play) { + if (groundhog_control->event_state == aGHC_EVENT_STATE_MAJIN_DONE) { + groundhog_control->timer = 60; + Camera2_Inter_set_reverse_mode(play); + mBGMPsComp_delete_ps_demo(252, 360); + groundhog_control->attention_mode = aGHC_ATTENTION_SONCHO; + aGHC_setupAction(groundhog_control, aGHC_ACTION_SONCHO_SPEECH_START_WAIT); + } +} + +static void aGHC_soncho_speech_start_wait(GROUNDHOG_CONTROL_ACTOR* groundhog_control, GAME_PLAY* play) { + groundhog_control->timer--; + + if (groundhog_control->timer <= 0) { + aGHC_setupAction(groundhog_control, aGHC_ACTION_SONCHO_SPEECH_END_WAIT); + } +} + +static void aGHC_soncho_speech_end_wait(GROUNDHOG_CONTROL_ACTOR* groundhog_control, GAME_PLAY* play) { + if (groundhog_control->event_state == aGHC_EVENT_STATE_SONCHO_DONE) { + groundhog_control->timer = 20; + aGHC_setupAction(groundhog_control, aGHC_ACTION_FADE_OUT_START_WAIT); + } +} + +static void aGHC_fade_out_start_wait(GROUNDHOG_CONTROL_ACTOR* groundhog_control, GAME_PLAY* play) { + groundhog_control->timer--; + + if (groundhog_control->timer <= 0) { + Common_Set(event_title_fade_in_progress, TRUE); + mBGMPsComp_delete_ps_quietField(); + mBGMPsComp_make_ps_co_quiet(360, 60); + aGHC_setupAction(groundhog_control, aGHC_ACTION_AFTER_800); + } +} + +static void aGHC_setupAction(GROUNDHOG_CONTROL_ACTOR* groundhog_control, int action) { + static aGHC_ACTION_PROC process[aGHC_ACTION_NUM] = { + &aGHC_before_800, + &aGHC_birth_reset_wait, + &aGHC_birth_reset, + &aGHC_retire_reset_wait, + &aGHC_reset_speech_bgm_start_wait, + &aGHC_soncho_speech_start_wait, + &aGHC_soncho_speech_end_wait, + &aGHC_fade_out_start_wait, + (aGHC_ACTION_PROC)&none_proc1 + }; + + groundhog_control->action_proc = process[action]; + groundhog_control->action = action; +} + +static void aGHC_actor_move(ACTOR* actor, GAME* game) { + GROUNDHOG_CONTROL_ACTOR* groundhog_control = (GROUNDHOG_CONTROL_ACTOR*)actor; + GAME_PLAY* play = (GAME_PLAY*)game; + + Common_Get(clip).groundhog_control_clip->now_term = aGHC_get_now_term(); + aGHC_search_soncho(play); + aGHC_set_attention_request(groundhog_control->attention_mode); + (*groundhog_control->action_proc)(groundhog_control, play); + groundhog_control->event_state = aGHC_EVENT_STATE_NONE; +} diff --git a/rel/ac_set_ovl_insect.c b/rel/ac_set_ovl_insect.c index c849665b..e62e9e52 100644 --- a/rel/ac_set_ovl_insect.c +++ b/rel/ac_set_ovl_insect.c @@ -1267,7 +1267,7 @@ static int aSOI_check_countdown_event(SET_MANAGER* set_manager, mEv_gst_hitodama int res = FALSE; // Check that the ghost event is active - if (mEv_check_status(mEv_EVENT_GHOST, mEv_STATUS_ACTIVE) == TRUE) { + if (mEv_check_status(mEv_EVENT_NEW_YEARS_EVE_COUNTDOWN, mEv_STATUS_ACTIVE) == TRUE) { int n_bx = (u8)set_manager->player_pos.next_bx; int n_bz = (u8)set_manager->player_pos.next_bz; // idk if this is a fake match or not int pool_bx; diff --git a/rel/m_event.c b/rel/m_event.c new file mode 100644 index 00000000..ca5f3f00 --- /dev/null +++ b/rel/m_event.c @@ -0,0 +1,819 @@ +#include "m_event.h" + +#include "libultra/libultra.h" +#include "m_common_data.h" +#include "ac_aprilfool_control_h.h" +#include "m_play.h" +#include "m_scene_table.h" + +static int n_today_events; +static int status_edge; +static int funeral; +static int dead; +static lbRTC_year_t weekday1st_year; +static lbRTC_weekday_t weekday1st[lbRTC_MONTHS_MAX]; + +extern void mEv_ClearSpecialEvent(mEv_special_c* special_event) { + special_event->type = -1; + bzero(&special_event->event, sizeof(mEv_special_u)); + bzero(Common_GetPointer(event_common), sizeof(mEv_event_common_u)); +} + +extern void mEv_ClearEventKabuPeddler(mEv_kabu_peddler_c* kabu_peddler) { + if (kabu_peddler != NULL) { + mPr_ClearAnyPersonalID(kabu_peddler->spoken_pids, TOTAL_PLAYER_NUM); + } +} + +extern void mEv_ClearEventSaveInfo(mEv_event_save_c* save_event) { + mEv_ClearSpecialEvent(&save_event->special); + mEv_ClearEventKabuPeddler(&save_event->weekly.kabu_peddler); + save_event->flags = 0; +} + +extern void mEv_ClearEventInfo() { + u32* event_flag = Common_Get(event_flags); + int i; + + for (i = 0; i < mEv_EVENT_TYPE_NUM; i++) { + event_flag[0] = 0; + event_flag++; + } + + Common_Set(event_flags[1], Save_Get(event_save_data.flags)); + Common_Get(event_common).fieldday_event_id = -1; + Common_Get(event_common).fieldday_event_over_status = -1; +} + +extern void mEv_EventON(u32 event_kind) { + int type = mEv_GET_TYPE(event_kind); + u32 flag; + + if (type >= mEv_EVENT_TYPE_NUM) { + return; + } + + flag = Common_Get(event_flags[type]); + flag |= (1 << mEv_GET_SUBTYPE(event_kind)); + Common_Set(event_flags[type], flag); + + if (type != mEv_SAVED_EVENT) { + return; + } + + Save_Get(event_save_data).flags = Common_Get(event_flags[flag]); +} + +extern void mEv_EventOFF(u32 event_kind) { + int type = mEv_GET_TYPE(event_kind); + u32 flag; + + if (type >= mEv_EVENT_TYPE_NUM) { + return; + } + + flag = Common_Get(event_flags[type]); + flag &= ~(1 << mEv_GET_SUBTYPE(event_kind)); + Common_Set(event_flags[type], flag); + + if (type != mEv_SAVED_EVENT) { + return; + } + + Save_Get(event_save_data).flags = Common_Get(event_flags[flag]); +} + +extern int mEv_CheckEvent(u32 event_kind) { + int type = mEv_GET_TYPE(event_kind); + int res = FALSE; + + if (type < mEv_EVENT_TYPE_NUM && ((Common_Get(event_flags[type]) >> mEv_GET_SUBTYPE(event_kind)) & 1)) { + res = TRUE; + } + + return res; +} + +extern void mEv_ClearPersonalEventFlag(int player_no) { + mEv_EventOFF(mEv_SAVED_FIRSTJOB_PLR0 + player_no); + mEv_EventOFF(mEv_SAVED_FIRSTINTRO_PLR0 + player_no); + mEv_EventOFF(mEv_SAVED_HRAWAIT_PLR0 + player_no); + mEv_EventOFF(mEv_SAVED_HRATALK_PLR0 + player_no); + mEv_EventOFF(mEv_SAVED_FJOPENQUEST_PLR0 + player_no); + mEv_EventOFF(mEv_SAVED_GATEWAY_PLR0 + player_no); + + { + aAPC_event_save_data_c* data = (aAPC_event_save_data_c*)mEv_get_save_area(mEv_EVENT_APRILFOOLS_DAY, 0); + + if (data != NULL) { + data->talk_bitfield[player_no] = 0; + } + } +} + +extern void mEv_SetFirstJob() { + int player_no = Common_Get(player_no); + + if (player_no < PLAYER_NUM) { + mEv_EventON(mEv_SAVED_FIRSTJOB_PLR0 + player_no); + } +} + +extern int mEv_CheckRealArbeit() { + int player_no = Common_Get(player_no); + int res = FALSE; + + if ( + player_no < PLAYER_NUM && + ( + mEv_CheckEvent(mEv_SAVED_FIRSTJOB_PLR0 + player_no) == TRUE || + mEv_CheckEvent( mEv_SAVED_HRAWAIT_PLR0 + player_no) == TRUE + ) + ) { + res = TRUE; + } + + return res; +} + +extern int mEv_CheckArbeit() { + int player_no = Common_Get(player_no); + int res = FALSE; + + if ( + player_no < PLAYER_NUM && + ( + mEv_CheckEvent(mEv_SAVED_FIRSTJOB_PLR0 + player_no) == TRUE || + mEv_CheckEvent( mEv_SAVED_HRAWAIT_PLR0 + player_no) == TRUE || + mEv_CheckEvent( mEv_SAVED_HRATALK_PLR0 + player_no) == TRUE + ) + ) { + res = TRUE; + } + + return res; +} + +extern int mFI_CheckFirstJob() { + int player_no = Common_Get(player_no); + int res = FALSE; + + if ( + player_no < PLAYER_NUM && + mEv_CheckEvent(mEv_SAVED_FIRSTJOB_PLR0 + player_no) == TRUE + ) { + res = TRUE; + } + + return res; +} + +extern void mEv_UnSetFirstJob() { + int player_no = Common_Get(player_no); + + if (player_no < PLAYER_NUM) { + mEv_EventOFF(mEv_SAVED_FIRSTJOB_PLR0 + player_no); + mEv_EventON(mEv_SAVED_HRAWAIT_PLR0 + player_no); + } +} + +extern void mEv_SetFirstIntro() { + int player_no = Common_Get(player_no); + + if (player_no < PLAYER_NUM) { + mEv_EventON(mEv_SAVED_FIRSTINTRO_PLR0 + player_no); + } +} + +extern int mEv_CheckFirstIntro() { + int player_no = Common_Get(player_no); + int res = FALSE; + + if ( + player_no < PLAYER_NUM && + mEv_CheckEvent(mEv_SAVED_FIRSTINTRO_PLR0 + player_no) == TRUE + ) { + res = TRUE; + } + + return res; +} + +extern void mEv_UnSetFirstIntro() { + int player_no = Common_Get(player_no); + + if (player_no < PLAYER_NUM) { + mEv_EventOFF(mEv_SAVED_FIRSTINTRO_PLR0 + player_no); + } +} + +extern void mEv_SetGateway() { + int player_no = Common_Get(player_no); + + if (player_no < TOTAL_PLAYER_NUM) { + mEv_EventON(mEv_SAVED_GATEWAY_PLR0 + player_no); + } +} + +extern int mEv_CheckGateway() { + int player_no = Common_Get(player_no); + int res = FALSE; + + if ( + player_no < TOTAL_PLAYER_NUM && + mEv_CheckEvent(mEv_SAVED_GATEWAY_PLR0 + player_no) == TRUE + ) { + res = TRUE; + } + + return res; +} + +extern void mEv_UnSetGateway() { + int player_no = Common_Get(player_no); + + if (player_no < TOTAL_PLAYER_NUM) { + mEv_EventOFF(mEv_SAVED_GATEWAY_PLR0 + player_no); + } +} + +static int title_demo_number = -1; + +extern int mEv_CheckTitleDemo() { + return title_demo_number; +} + +extern void mEv_SetTitleDemo(int demo_number) { + title_demo_number = demo_number; +} + +extern void mEv_RenewalDataEveryDay() { + if (mTM_check_renew_time(mTM_RENEW_TIME_DAILY) == TRUE) { + int i; + + for (i = 0; i < PLAYER_NUM; i++) { + if (mEv_CheckEvent(mEv_SAVED_HRAWAIT_PLR0 + i) == TRUE) { + /* After a new day starts, turn off all players' 'wait a day' HRA event and turn on talk to Tom Nook HRA event */ + mEv_EventOFF(mEv_SAVED_HRAWAIT_PLR0 + i); + mEv_EventON(mEv_SAVED_HRATALK_PLR0 + i); + } + } + } +} + +extern void mEv_GetEventWeather(s16* weather, s16* intensity) { + intensity[0] = mEnv_WEATHER_INTENSITY_HEAVY; + + if (mEv_check_schedule(mEv_EVENT_WEATHER_CLEAR)) { + weather[0] = mEnv_WEATHER_CLEAR; + } + else if (mEv_check_schedule(mEv_EVENT_WEATHER_SNOW)) { + weather[0] = mEnv_WEATHER_SNOW; + } + else if (mEv_check_schedule(mEv_EVENT_WEATHER_SPORTS_FAIR)) { + weather[0] = mEnv_WEATHER_CLEAR; + } + else { + weather[0] = -1; // no event weather + } +} + +static lbRTC_day_t last_day_of_month(lbRTC_month_t month) { + static lbRTC_day_t last_day[lbRTC_MONTHS_MAX] = { + 31, 28, 31, 30, + 31, 30, 31, 31, + 30, 31, 30, 31 + }; + + lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time); + lbRTC_year_t year = rtc_time->year; + + if (month != lbRTC_FEBRUARY) { + return last_day[month - 1]; + } + else if (lbRTC_IS_LEAPYEAR(year)) { + return 29; + } + else { + return 28; + } +} + +static void init_weekday1st() { + lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time); + lbRTC_month_t month = rtc_time->month & 0xF; // ?? + lbRTC_month_t i; + lbRTC_weekday_t weekday; + + weekday1st_year = rtc_time->year; + + weekday = (rtc_time->weekday + (1 - rtc_time->day)) % lbRTC_WEEK; + if (weekday < 0) { + weekday += lbRTC_WEEK; + } + + weekday1st[month] = weekday; + + for (i = month + 1; i <= lbRTC_MONTHS_MAX; i++) { + weekday1st[i] = (weekday1st[i - 1] + last_day_of_month(i)) % lbRTC_WEEK; + } + + for (i = month - 1; i >= lbRTC_JANUARY; i--) { + weekday = (weekday1st[i + 1] - last_day_of_month(i)) % lbRTC_WEEK; + if (weekday < 0) { + weekday += lbRTC_WEEK; + } + + weekday1st[i] = weekday; + } +} + +static int check_date_range(u16 date, u16 lower_bound, u16 upper_bound) { + if (upper_bound < lower_bound) { + if (date < lower_bound && date > upper_bound) { + return FALSE; + } + else { + return TRUE; + } + } + else if (date < lower_bound || date > upper_bound) { + return FALSE; + } + else { + return TRUE; + } +} + +static int check_ymdh_range(u32 ymdh, u32 lower_bound, u32 upper_bound) { + int res = FALSE; + + if (ymdh >= lower_bound && ymdh <= upper_bound) { + res = TRUE; + } + + return res; +} + +static mEv_MonthDay_u after_n_day(mEv_MonthDay_u month_day, int n_day) { + mEv_MonthDay_u after = month_day; + + if (n_day >= 0) { + lbRTC_day_t last_day = last_day_of_month(after.month); + + after.day = after.day + n_day; + if (after.day > last_day) { + if (after.month == lbRTC_DECEMBER) { + after.month = lbRTC_JANUARY; + } + else { + after.month++; + } + + after.day -= last_day; + } + } + else { + after.day = after.day + n_day; + if ((after.day & 0x80) != 0 || after.day == 0) { + if (after.month == lbRTC_JANUARY) { + after.month = lbRTC_DECEMBER; + } + else { + after.month--; + } + + after.day += last_day_of_month(after.month); + } + } + + return after; +} + +extern lbRTC_day_t mEv_get_next_weekday(lbRTC_weekday_t weekday) { + lbRTC_weekday_t next_weekday; + lbRTC_day_t day; + lbRTC_day_t last_day; + + if (weekday >= Common_Get(time.rtc_time).weekday) { + next_weekday = weekday - Common_Get(time.rtc_time).weekday; + } + else { + next_weekday = lbRTC_WEEK - (Common_Get(time.rtc_time).weekday - weekday); + } + + day = Common_Get(time.rtc_time).day + next_weekday; + last_day = last_day_of_month(Common_Get(time.rtc_time).month); + + if (day > last_day) { + day -= last_day; + } + + return day; +} + +#define mEv_date_decode_weekday(day) ((day) & 0b00000111) // 0-6 (which weekday, Sunday-Saturday) +#define mEv_date_decode_week(day) (((day) & 0b00111000) >> 3) // 0-5 (which week of the month, 1st, 2nd, 3rd, ...) + +static lbRTC_day_t m_weekday2day(lbRTC_month_t month, u8 day_enc) { + int week = mEv_date_decode_week(day_enc); // get the week of the month + int weekday = mEv_date_decode_weekday(day_enc); // get the weekday + lbRTC_day_t day = 0; + lbRTC_day_t last_day = last_day_of_month(month); + + if (week == mEv_SCHEDULE_WEEKLY) { + if (month > Common_Get(time.rtc_time).month) { + week = 1; /* 1st week of this month */ + } + else if (month < Common_Get(time.rtc_time).month) { + week = mEv_SCHEDULE_LAST_WEEKDAY_OF_MONTH; /* last weekday of the month */ + } + else { + day = Common_Get(time.rtc_time).day - (Common_Get(time.rtc_time).weekday - weekday); + + if (day > last_day) { + week = mEv_SCHEDULE_LAST_WEEKDAY_OF_MONTH; + } + else { + week = 0; /* cleared */ + } + } + } + + if (week == mEv_SCHEDULE_LAST_WEEKDAY_OF_MONTH) { + int t_day = (last_day + weekday1st[month] - 1) % lbRTC_WEEK; /* get the weekday of the first day of next month */ + + if (t_day < weekday) { + day = (last_day - (t_day - weekday)) - lbRTC_WEEK; + } + else { + day = last_day - (t_day - weekday); + } + } + else if (week != 0) { + int t_day = weekday1st[month]; + + if (weekday < t_day) { + day = week * lbRTC_WEEK + (weekday - t_day) + 1; + } + else { + day = (week - 1) * lbRTC_WEEK + (weekday - t_day) + 1; + } + } + + return day; +} + +extern lbRTC_day_t mEv_weeday2day(lbRTC_month_t month, int week, int weekday) { + lbRTC_day_t day = 0; + lbRTC_day_t last_day = last_day_of_month(month); + + if (week == mEv_SCHEDULE_WEEKLY) { + if (month > Common_Get(time.rtc_time).month) { + week = 1; /* 1st week of this month */ + } + else if (month < Common_Get(time.rtc_time).month) { + week = mEv_SCHEDULE_LAST_WEEKDAY_OF_MONTH; /* last weekday of the month */ + } + else { + day = Common_Get(time.rtc_time).day - (Common_Get(time.rtc_time).weekday - weekday); + + if (day > last_day) { + week = mEv_SCHEDULE_LAST_WEEKDAY_OF_MONTH; + } + else { + week = 0; /* cleared */ + } + } + } + + if (week == mEv_SCHEDULE_LAST_WEEKDAY_OF_MONTH) { + int t_day = (last_day + weekday1st[month] - 1) % lbRTC_WEEK; /* get the weekday of the first day of next month */ + + if (t_day < weekday) { + day = (last_day - (t_day - weekday)) - lbRTC_WEEK; + } + else { + day = last_day - (t_day - weekday); + } + } + else if (week != 0) { + int t_day = weekday1st[month]; + + if (weekday < t_day) { + day = week * lbRTC_WEEK + (weekday - t_day) + 1; + } + else { + day = (week - 1) * lbRTC_WEEK + (weekday - t_day) + 1; + } + } + + return day; +} + +static int get_end_time(u32 active_hours) { + int hour; + int i; + + if (active_hours & ((1 << 24) - 1) == 0) { + return -1; /* no active hours */ + } + + hour = 23; + for (i = 0; i < 24; i++) { + if ((active_hours & (1 << 23)) & 1) { + break; + } + + active_hours <<= 1; /* move hours left by one bit, MSB is latest hour */ + hour--; + } + + return hour; +} + +static mEv_event_today_c event_today[mEv_TODAY_EVENT_NUM]; +static u8 index_today[mEv_EVENT_NUM]; + +extern int mEv_get_end_time(int event_type) { + u8 idx = index_today[event_type]; + + if (idx == 0xFF) { + return -1; + } + else { + return get_end_time(event_today[idx].active_hours); + } +} + +static int search_empty_event_today() { + int i; + + for (i = 0; i < mEv_TODAY_EVENT_NUM; i++) { + if (event_today[i].type == -1) { + return i; + } + } + + return i; +} + +static int add_event_today(mEv_MonthDay_u month_day, mEv_schedule_c* schedule) { + u8 idx = index_today[schedule->type]; + int res = FALSE; + + if (idx == 0xFF) { + idx = search_empty_event_today(); + + if (idx >= mEv_TODAY_EVENT_NUM) { + return FALSE; + } + + n_today_events++; + index_today[schedule->type] = idx; + } + + { + u8 start_hour = schedule->date[0].hour; + u8 end_hour = schedule->date[1].hour; + u32 i; + u32 n; + + if ((start_hour & mEv_SCHEDULE_TODAY) == 0) { + event_today[idx].begin_date = schedule->date[0].month_day; + event_today[idx].end_date = schedule->date[1].month_day; + } + else { + event_today[idx].begin_date = month_day; + event_today[idx].end_date = month_day; + start_hour &= ~mEv_SCHEDULE_TODAY; + end_hour &= ~mEv_SCHEDULE_TODAY; + } + + if ((start_hour & mEv_SCHEDULE_MULTIDAY) != 0) { + start_hour &= ~mEv_SCHEDULE_MULTIDAY; + end_hour &= ~mEv_SCHEDULE_MULTIDAY; + + if (month_day.raw != schedule->date[0].month_day.raw) { + start_hour = 0; + } + + if (month_day.raw != schedule->date[1].month_day.raw) { + end_hour = 23; + } + } + + n = 1; + for (i = 0; i < 24; i++) { + if (i >= start_hour && i <= end_hour) { + event_today[idx].active_hours |= n; + } + + n <<= 1; + } + + event_today[idx].type = schedule->type; + event_today[idx].status |= mEv_STATUS_EXIST; + } + + return res; +} + +static int check_and_clear_event_today(Event_c* event, int type) { + u8 idx = index_today[idx]; + + if (idx != 0xFF) { + mEv_event_today_c* today_event = &event_today[idx]; + + if ((today_event->status & mEv_STATUS_EXIST) == FALSE) { + int flags = 0; + mEv_place_data_c* place = mEv_get_common_place(today_event->type, 81); + + if (place != NULL && place->block.x == event->block_x && place->block.z == event->block_z) { + flags |= 0b00000001; // 1, in the block the event is supposed to exist + } + + if (mEv_check_status(today_event->type, mEv_STATUS_RUN)) { + flags |= 0b00000010; // 2, event is currently running + today_event->active_hours = 0x20000000; + } + + if (type == today_event->type && flags == 0) { + today_event->type = -1; + n_today_events--; + today_event->active_hours = 0; + today_event->end_date.raw = 0; + today_event->status = 0; + index_today[type] = 0xFF; + + return TRUE; + } + } + } + + return FALSE; +} + +static int delete_too_short_event(Event_c* event, int type, mEv_schedule_date_u date) { + u8 idx = index_today[type]; + + if (idx != 0xFF) { + mEv_event_today_c* today_event = &event_today[idx]; + mEv_schedule_date_u new_date; + + switch (today_event->type) { + case mEv_EVENT_NEW_YEARS_DAY: + case mEv_EVENT_GROUNDHOG_DAY: + case mEv_EVENT_SPORTS_FAIR_BALL_TOSS: + case mEv_EVENT_SPORTS_FAIR_AEROBICS: + case mEv_EVENT_SPORTS_FAIR_TUG_OF_WAR: + case mEv_EVENT_SPORTS_FAIR_FOOT_RACE: + case mEv_EVENT_CHERRY_BLOSSOM_FESTIVAL: + case mEv_EVENT_FISHING_TOURNEY_1: + case mEv_EVENT_FIREWORKS_SHOW: + case mEv_EVENT_MORNING_AEROBICS: + case mEv_EVENT_HARVEST_MOON_FESTIVAL: + case mEv_EVENT_FISHING_TOURNEY_2: + case mEv_EVENT_HARVEST_FESTIVAL: + { + new_date = date; + new_date.hour = mEv_get_end_time(today_event->type); + + break; + } + + case mEv_EVENT_HALLOWEEN: + case mEv_EVENT_TOY_DAY_JINGLE: + case mEv_EVENT_NEW_YEARS_EVE_COUNTDOWN: + { + new_date.raw = 0; + new_date.month_day = today_event->end_date; + new_date.hour = mEv_get_end_time(today_event->type); + + break; + } + + default: + { + return FALSE; + } + } + + if (new_date.raw != date.raw) { + return FALSE; + } + + if (Common_Get(time.rtc_time).min < 55) { + return FALSE; + } + + Common_Get(event_common).too_short = type; + } + + return TRUE; +} + +static void init_today_event() { + mEv_event_today_c* today_event = event_today; + int i; + + for (i = 0; i < mEv_TODAY_EVENT_NUM; i++) { + today_event->type = -1; + today_event->active_hours = 0; + today_event->end_date.raw = 0; + today_event->begin_date.raw = 0; + today_event->status = 0; + + today_event++; + } + + n_today_events = 0; + + { + u8* index_today_p = index_today; + + for (i = 0; i < mEv_EVENT_NUM; i++) { + index_today_p[0] = 0xFF; + index_today_p++; + } + } +} + +static void init_time_seat() { + mEv_event_today_c* today_event = event_today; + int i; + + for (i = 0; i < mEv_TODAY_EVENT_NUM; i++) { + today_event->active_hours = 0; + today_event->end_date.raw = 0; + today_event->begin_date.raw = 0; + today_event->status &= ~mEv_STATUS_EXIST; + } +} + +static int get_special_event_end_time(s16 event_type) { + int end_time = 0; + + switch (event_type) { + case mEv_EVENT_DESIGNER: + end_time = 5; + break; + case mEv_EVENT_ARTIST: + end_time = 5; + break; + case mEv_EVENT_CARPET_PEDDLER: + end_time = 5; + break; + case mEv_EVENT_GYPSY: + end_time = 20; + break; + case mEv_EVENT_BROKER_SALE: + end_time = 17; + break; + case mEv_EVENT_SHOP_SALE: + end_time = 23; + break; + } + + return end_time; +} + +static int init_special_init(int new_event) { + int res = FALSE; + + switch (Save_Get(scene_no)) { + case SCENE_BUGGY: + case SCENE_BROKER_SHOP: + { + if (gamePT->frame_counter == 0) { + return FALSE; + } + + break; + } + } + + switch (Save_Get(scene_no)) { + case SCENE_BUGGY: + case SCENE_BROKER_SHOP: + return FALSE; + + case SCENE_SHOP0: + case SCENE_CONVENI: + case SCENE_SUPER: + case SCENE_DEPART: + case SCENE_DEPART_2: + { + if (Save_Get(event_save_data).special.type == mEv_EVENT_SHOP_SALE) { + return FALSE; + } + } + + // fallthrough case + default: + { + + break; + } + } +} diff --git a/rel/m_field_assessment.c b/rel/m_field_assessment.c index cd725087..9132f2e6 100644 --- a/rel/m_field_assessment.c +++ b/rel/m_field_assessment.c @@ -4,11 +4,26 @@ #include "m_common_data.h" #include "m_all_grow.h" #include "libultra/libultra.h" -#include "libc64/qrand.h" static int l_good_block_num; static int l_field_assessment_rank; +static u8 l_block_rank_tree_num[mFAs_TREE_RANK_COUNT] = { 8, 11, 14, 17, 255 }; +static u8 l_block_rank_table[mFAs_TREE_RANK_COUNT] = { 0, 1, 2, 1, 0 }; +static u8 l_block_max_by_rank[mFAs_FIELDRANK_NUM] = { 0, 2, 4, 7, 12, 16, 255 }; +static int l_mfas_romf_check[5] = { 0, 0, 0, 0, 0 }; + +#ifdef MUST_MATCH +static FORCESTRIP int match_data_m_field_assessment() { + int a = l_block_rank_tree_num[0]; + int b = l_block_rank_table[0]; + int c = l_block_max_by_rank[0]; + int d = l_mfas_romf_check[0]; + + return a > b > c > d; +} +#endif + static void mFAs_ClearGoodField_common(mFAs_GoodField_c* good_field) { lbRTC_TimeCopy(&good_field->renew_time, &mTM_rtcTime_clear_code); good_field->perfect_day_streak = 0; @@ -31,7 +46,7 @@ static void mFAs_SetGoodField(int rank) { mFAs_GoodField_c* good_field = Save_GetPointer(good_field); lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time); if (rank == mFAs_FIELDRANK_SIX) { - if (mTM_IsTimeEqual(&mTM_rtcTime_clear_code, &good_field->renew_time) == TRUE) { + if (mTM_AreTimesEqual(&mTM_rtcTime_clear_code, &good_field->renew_time) == TRUE) { lbRTC_TimeCopy(&good_field->renew_time, rtc_time); good_field->perfect_day_streak = 0; } @@ -123,8 +138,9 @@ static int mFAs_GetBlockTreeNum2( } } else if (mFAs_CheckDust(item) == TRUE) { - int ut_x = IDX_2_UT_X(i); - int ut_z = IDX_2_UT_Z(i); + int ut_x = i & 15; + int ut_z = (i >> 4) & 15; + if ((dump_unit_info == NULL) || (dump_unit_info->block_data == NULL) || (dump_unit_info->unit_x < ut_x || dump_unit_info->unit_x - mAGrw_DUMP_WIDTH > ut_x) || @@ -143,8 +159,6 @@ static int mFAs_GetBlockTreeNum2( return trees; } -static u8 l_block_rank_tree_num[mFAs_TREE_RANK_COUNT] = { 8, 11, 14, 17, 255 }; - /* int tree_num, int grass_num */ typedef int (*mFAs_CheckProc)(int, int); @@ -212,53 +226,86 @@ static int mFAs_CheckBlockNum(int* block_num, int block_x, int block_z, int fail return res; } -static u8 l_block_rank_table[mFAs_TREE_RANK_COUNT] = { 0, 1, 2, 1, 0 }; -static u8 l_block_max_by_rank[mFAs_FIELDRANK_NUM] = { 0, 2, 4, 7, 12, 16, 255 }; -static int l_mfas_romf_check[5] = { 0, 0, 0, 0, 0 }; - -#pragma pool_data on -/* TODO: @nonmatching */ +/* @nonmatching - something going on with the stack causing an extra 0 register to be allocated */ +#ifndef MUST_MATCH static int mFAs_GetFieldGoodBlockNum_common(int* condition_num, int* block_x, int* block_z, int* block_num) { - int set_bad_block = FALSE; + int perfect_block_num; mFI_unit_c dump_unit; - int perfect_block_num = 0; mFM_fg_c* fg_block_items; - int bx, bz; - int condition_result; - int good_blocks = 0; + int bx; + int bz; int flower_num; int block_dust_num; - int total_flowers = 0; + int total_flowers; + int good_blocks; + int condition_result; int i; - int selected_block_x = 0; - int selected_block_z = 0; - int tree_num = 0; - int grass_num = 0; - int effective_grass_num = 0; - int total_trees = 0; - int total_grass = 0; + int selected_block_x; + int selected_block_z; + int tree_num; + int grass_num; + int effective_grass_num; + int total_trees; + int total_grass; int rank; - int good_block_num; mFI_unit_c* dump_info; int trees; - int dust_num = 0; + int dust_num; + int set_bad_block; - dump_unit.block_data = (void*)(set_bad_block); - dump_info = (void*)(set_bad_block); fg_block_items = Save_GetPointer(fg[0][0]); + perfect_block_num = 0; + good_blocks = 0; + total_flowers = 0; + selected_block_x = 0; + selected_block_z = 0; + total_trees = 0; + total_grass = 0; + dust_num = 0; + tree_num = 0; + grass_num = 0; + dump_info = NULL; + effective_grass_num = 0; + dump_unit.block_data = NULL; + set_bad_block = FALSE; + + //fg_block_items = Save_GetPointer(fg[0][0]); if (mFI_CheckFieldData()) { + /* @BUG - this method is broken when used during initial loading. + * + * The fdinfo structure still contains the info for the start demo scene, + * and thus cannot return the proper block info for the dump. It fails in + * mFI_BlockCheck. + */ + #ifndef BUGFIXES mAGrw_SearchDump(&dump_unit); + #else + if (mFI_BlockKind2BkNum(&dump_unit.block_x, &dump_unit.block_z, mRF_BLOCKKIND_DUMP)) { + mActor_name_t* dump_fg_p = Save_Get(fg[dump_unit.block_z - 1][dump_unit.block_x - 1]).items[0]; + int j; + + for (j = 0; j < UT_TOTAL_NUM; j++) { + if (dump_fg_p[j] == DUMP) { + dump_unit.unit_x = j % UT_X_NUM; + dump_unit.unit_z = j / UT_X_NUM; + dump_unit.block_data = dump_fg_p; + + break; + } + } + } + #endif } for (i = 0; i < FG_BLOCK_TOTAL_NUM; i++) { + bx = 1 + (i % 5); + bz = 1 + (i / 5); block_dust_num = 0; tree_num = 0; effective_grass_num = 0; grass_num = 0; flower_num = 0; - bx = 1 + (i % 5); - bz = 1 + (i / 5); if (dump_unit.block_data != NULL && dump_unit.block_x == bx && dump_unit.block_z == bz) { dump_info = &dump_unit; @@ -278,7 +325,7 @@ static int mFAs_GetFieldGoodBlockNum_common(int* condition_num, int* block_x, in condition_result = 1; } else { - condition_result = (fqrand() * 3.0f); + condition_result = RANDOM(3); } if (condition_result == 1 && block_x != NULL && block_z != NULL) { @@ -291,7 +338,7 @@ static int mFAs_GetFieldGoodBlockNum_common(int* condition_num, int* block_x, in if (block_dust_num != 0) { // bug here? this only executes when the value is not FALSE, but value is only // updated within the if statement block. - if (!set_bad_block) { + if (set_bad_block == FALSE) { selected_block_x = bx; selected_block_z = bz; @@ -300,7 +347,7 @@ static int mFAs_GetFieldGoodBlockNum_common(int* condition_num, int* block_x, in #endif } else { - if ((int)(fqrand() * 3.0f) == 1) { + if (RANDOM(3) == 1) { selected_block_x = bx; selected_block_z = bz; } @@ -333,15 +380,15 @@ static int mFAs_GetFieldGoodBlockNum_common(int* condition_num, int* block_x, in fg_block_items++; } - l_mfas_romf_check[1] = FG_BLOCK_TOTAL_NUM - (good_blocks + perfect_block_num); /* "bad" block count */ - good_block_num = perfect_block_num + good_blocks / 2; l_mfas_romf_check[0] = good_blocks; + l_mfas_romf_check[1] = FG_BLOCK_TOTAL_NUM - (good_blocks + perfect_block_num); /* "bad" block count */ l_mfas_romf_check[2] = total_trees; l_mfas_romf_check[3] = total_flowers; l_mfas_romf_check[4] = total_grass; + perfect_block_num += good_blocks / 2; if (dust_num >= mFAs_DUST_OVER_NUM) { - good_block_num = 0; + perfect_block_num = 0; Save_Set(dust_flag, TRUE); if (condition_num != NULL) { *condition_num = mFAs_CONDITION_DUST_OVER; @@ -357,9 +404,15 @@ static int mFAs_GetFieldGoodBlockNum_common(int* condition_num, int* block_x, in mFAs_ClearGoodField(); /* reset perfect town streak */ } - return good_block_num; + return perfect_block_num; } -#pragma pool_data reset +#else +#include "orderfloats/80641fd8_80641fdc.inc" + +static asm int mFAs_GetFieldGoodBlockNum_common(int* condition_num, int* block_x, int* block_z, int* block_num) { + #include "asm/803a1ae8.s" +} +#endif static int mFAs_GetFieldGoodBlockNum() { int block_x = 0; @@ -390,7 +443,30 @@ static int mFAs_GetDustNum(int* block_x, int* block_z) { fg_block_items = Save_GetPointer(fg[0][0]); if (mFI_CheckFieldData()) { + /* @BUG - this method is broken when used during initial loading. + * + * The fdinfo structure still contains the info for the start demo scene, + * and thus cannot return the proper block info for the dump. It fails in + * mFI_BlockCheck. + */ + #ifndef BUGFIXES mAGrw_SearchDump(&dump_unit); + #else + if (mFI_BlockKind2BkNum(&dump_unit.block_x, &dump_unit.block_z, mRF_BLOCKKIND_DUMP)) { + mActor_name_t* dump_fg_p = Save_Get(fg[dump_unit.block_z - 1][dump_unit.block_x - 1]).items[0]; + int j; + + for (j = 0; j < UT_TOTAL_NUM; j++) { + if (dump_fg_p[j] == DUMP) { + dump_unit.unit_x = j % UT_X_NUM; + dump_unit.unit_z = j / UT_X_NUM; + dump_unit.block_data = dump_fg_p; + + break; + } + } + } + #endif } for (bz = 0; bz < FG_BLOCK_Z_NUM; bz++) { @@ -436,7 +512,7 @@ static int mFAs_GetDustNum(int* block_x, int* block_z) { #endif } else { - if ((int)(fqrand() * 3.0f) == 1) { + if (RANDOM(3) == 1) { *block_x = bx + 1; *block_z = bz + 1; } @@ -514,7 +590,6 @@ extern int mFAs_GetFieldRank() { return l_field_assessment_rank; } -#pragma pool_data on extern void mFAs_PrintFieldAssessment(gfxprint_t* gfxprint) { gfxprint_color(gfxprint, 240, 50, 150, 255); gfxprint_locate8x8(gfxprint, 3, 14); @@ -524,4 +599,3 @@ extern void mFAs_PrintFieldAssessment(gfxprint_t* gfxprint) { gfxprint_locate8x8(gfxprint, 3, 16); gfxprint_printf(gfxprint, " %02d", l_field_assessment_rank); /* current field rank */ } -#pragma pool_data reset diff --git a/rel/m_flashrom.c b/rel/m_flashrom.c index 6ea03d89..c1babc35 100644 --- a/rel/m_flashrom.c +++ b/rel/m_flashrom.c @@ -72,14 +72,34 @@ extern int mFRm_get_msg_idx() { return l_mfrm_msg_idx; } -/* @fabricated - necessary for including some strings in .data */ +/* @fabricated - necessary for including some strings in .data & taken from DnM */ extern MATCH_FORCESTRIP void mFRm_PrintErrInfo(gfxprint_t* gfxprint) { - gfxprint_printf(gfxprint, "N"); - gfxprint_printf(gfxprint, "A"); - gfxprint_printf(gfxprint, "W"); - gfxprint_printf(gfxprint, "R"); - gfxprint_printf(gfxprint, "C"); - gfxprint_printf(gfxprint, "O"); + gfxprint_color(gfxprint, 250, 100, 250, 255); + gfxprint_locate8x8(gfxprint, 22, 3); + + if (l_mfrm_err_debug[0] != 0) { + gfxprint_printf(gfxprint, "N"); + } + + if (l_mfrm_err_debug[1] != 0) { + gfxprint_printf(gfxprint, "A"); + } + + if (l_mfrm_err_debug[2] != 0) { + gfxprint_printf(gfxprint, "W"); + } + + if (l_mfrm_err_debug[3] != 0) { + gfxprint_printf(gfxprint, "R"); + } + + if (l_mfrm_err_debug[4] != 0) { + gfxprint_printf(gfxprint, "C"); + } + + if (l_mfrm_err_debug[5] != 0) { + gfxprint_printf(gfxprint, "O"); + } } /** diff --git a/rel/m_play.c b/rel/m_play.c index 9cd8c971..794753f3 100644 --- a/rel/m_play.c +++ b/rel/m_play.c @@ -61,15 +61,15 @@ void Game_play_Reset_destiny(){ } void event_title_flag_on(){ - if(Common_Get(event_id) != 0){ + if(Common_Get(event_title_flags) != 0){ Common_Set(event_notification_active,1); } } void event_title_flag_off(){ - if(Common_Get(event_id) == 2){ - Common_Set(event_id,0); + if(Common_Get(event_title_flags) == 2){ + Common_Set(event_title_flags,0); Common_Set(event_notification_active,0); } @@ -807,7 +807,7 @@ int makeBumpTexture(GAME_PLAY* play, GRAPH* graph1, GRAPH* graph2){ CLOSE_DISP(graph1); } -void draw_version(GRAPH*) { +void draw_version(GRAPH* graph) { JW_JUTReport(0x82, 0x172, 1, "[CopyDate:%.19s]", boot_copyDate); JW_JUTReport(0x82, 0x180, 1, "[Date:%s]" , &__DateTime__); JW_JUTReport(0x82, 0x18E, 1, "[Creator:%s]", &__Creator__);