mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-05-28 07:54:55 -04:00
3114 lines
83 KiB
C
3114 lines
83 KiB
C
#include "m_event.h"
|
|
|
|
#include "libultra/libultra.h"
|
|
#include "_mem.h"
|
|
#include "lb_reki.h"
|
|
#include "ac_aprilfool_control_h.h"
|
|
#include "m_common_data.h"
|
|
#include "m_player_lib.h"
|
|
#include "m_play.h"
|
|
#include "m_scene_table.h"
|
|
#include "m_soncho.h"
|
|
|
|
enum {
|
|
mEv_INIT_NO_RENEWAL,
|
|
mEv_INIT_RENEWAL,
|
|
mEv_INIT_FORCE_RENEWAL,
|
|
|
|
mEv_INIT_NUM
|
|
};
|
|
|
|
static int n_today_events = 0;
|
|
static int status_edge = 0;
|
|
static int funeral = 0;
|
|
static int dead = 0;
|
|
static lbRTC_year_t weekday1st_year = 0;
|
|
static lbRTC_weekday_t weekday1st[lbRTC_MONTHS_MAX];
|
|
|
|
typedef union ymdh {
|
|
struct {
|
|
u8 year;
|
|
u8 month;
|
|
u8 day;
|
|
u8 hour;
|
|
};
|
|
u32 raw;
|
|
} mEv_ymdh_u;
|
|
|
|
extern void mEv_ClearSpecialEvent(mEv_special_c* special_event) {
|
|
special_event->type = -1;
|
|
bzero(&special_event->event, sizeof(mEv_special_u));
|
|
bzero(Common_GetPointer(special_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() {
|
|
mEv_event_save_c* event_save = Save_GetPointer(event_save_data);
|
|
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_Get(event_flags[1]) = event_save->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) {
|
|
u32 type = mEv_GET_TYPE(event_kind);
|
|
|
|
if (type < mEv_EVENT_TYPE_NUM) {
|
|
u32* flag_p = Common_GetPointer(event_flags[type]);
|
|
*flag_p |= (1 << mEv_GET_SUBTYPE(event_kind));
|
|
|
|
if (type == mEv_SAVED_EVENT) {
|
|
Save_Get(event_save_data).flags = *flag_p;
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void mEv_EventOFF(u32 event_kind) {
|
|
u32 type = mEv_GET_TYPE(event_kind);
|
|
|
|
if (type < mEv_EVENT_TYPE_NUM) {
|
|
u32* flag_p = Common_GetPointer(event_flags[type]);
|
|
u32 mask = 1 << mEv_GET_SUBTYPE(event_kind);
|
|
|
|
*flag_p &= ~mask;
|
|
if (type == mEv_SAVED_EVENT) {
|
|
Save_Get(event_save_data).flags = *flag_p;
|
|
}
|
|
}
|
|
}
|
|
|
|
extern int mEv_CheckEvent(u32 event_kind) {
|
|
u32 type = mEv_GET_TYPE(event_kind);
|
|
int res = FALSE;
|
|
|
|
if (type < mEv_EVENT_TYPE_NUM) {
|
|
u32* flags_p = Common_GetPointer(event_flags[type]);
|
|
|
|
if (((*flags_p) >> 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() {
|
|
if (Common_Get(player_no) < PLAYER_NUM) {
|
|
u32 ev = mEv_SAVED_FIRSTJOB_PLR0;
|
|
|
|
ev += Common_Get(player_no);
|
|
mEv_EventON(ev);
|
|
}
|
|
}
|
|
|
|
extern int mEv_CheckRealArbeit() {
|
|
u32 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() {
|
|
u32 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() {
|
|
u32 player_no = Common_Get(player_no);
|
|
int res = FALSE;
|
|
|
|
if (player_no < PLAYER_NUM) {
|
|
u32 ev = mEv_SAVED_FIRSTJOB_PLR0;
|
|
ev += player_no;
|
|
|
|
if (mEv_CheckEvent(ev) == TRUE) {
|
|
res = TRUE;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
extern void mEv_UnSetFirstJob() {
|
|
u32 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() {
|
|
u32 player_no = Common_Get(player_no);
|
|
|
|
if (player_no < PLAYER_NUM) {
|
|
u32 ev = mEv_SAVED_FIRSTINTRO_PLR0;
|
|
ev += player_no;
|
|
|
|
mEv_EventON(ev);
|
|
}
|
|
}
|
|
|
|
extern int mEv_CheckFirstIntro() {
|
|
u32 player_no = Common_Get(player_no);
|
|
int res = FALSE;
|
|
|
|
if (player_no < PLAYER_NUM) {
|
|
u32 ev = mEv_SAVED_FIRSTINTRO_PLR0;
|
|
ev += player_no;
|
|
|
|
if (mEv_CheckEvent(ev) == TRUE) {
|
|
res = TRUE;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
extern void mEv_UnSetFirstIntro() {
|
|
u32 player_no = Common_Get(player_no);
|
|
|
|
if (player_no < PLAYER_NUM) {
|
|
u32 ev = mEv_SAVED_FIRSTINTRO_PLR0;
|
|
ev += player_no;
|
|
mEv_EventOFF(ev);
|
|
}
|
|
}
|
|
|
|
extern void mEv_SetGateway() {
|
|
u32 player_no = Common_Get(player_no);
|
|
|
|
if (player_no < TOTAL_PLAYER_NUM) {
|
|
u32 ev = mEv_SAVED_GATEWAY_PLR0;
|
|
ev += player_no;
|
|
mEv_EventON(ev);
|
|
}
|
|
}
|
|
|
|
extern int mEv_CheckGateway() {
|
|
u32 player_no = Common_Get(player_no);
|
|
int res = FALSE;
|
|
|
|
if (player_no < TOTAL_PLAYER_NUM) {
|
|
u32 ev = mEv_SAVED_GATEWAY_PLR0;
|
|
ev += player_no;
|
|
|
|
if (mEv_CheckEvent(ev) == TRUE) {
|
|
res = TRUE;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
extern void mEv_UnSetGateway() {
|
|
u32 player_no = Common_Get(player_no);
|
|
|
|
if (player_no < TOTAL_PLAYER_NUM) {
|
|
u32 ev = mEv_SAVED_GATEWAY_PLR0;
|
|
ev += player_no;
|
|
|
|
mEv_EventOFF(ev);
|
|
}
|
|
}
|
|
|
|
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++) {
|
|
|
|
u32 check_event = mEv_SAVED_HRAWAIT_PLR0 + i;
|
|
if (mEv_CheckEvent(check_event) == 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(check_event);
|
|
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
|
|
}
|
|
}
|
|
|
|
#include "m_event_schedule.c_inc"
|
|
|
|
static int event_rumor_table[] = {
|
|
mEv_EVENT_RUMOR_NEW_YEARS_DAY,
|
|
mEv_EVENT_RUMOR_KAMAKURA,
|
|
mEv_EVENT_RUMOR_VALENTINES_DAY,
|
|
mEv_EVENT_RUMOR_GROUNDHOG_DAY,
|
|
mEv_EVENT_RUMOR_APRILFOOLS_DAY,
|
|
mEv_EVENT_RUMOR_CHERRY_BLOSSOM_FESTIVAL,
|
|
mEv_EVENT_RUMOR_SPRING_SPORTS_FAIR,
|
|
mEv_EVENT_RUMOR_HARVEST_FESTIVAL,
|
|
mEv_EVENT_76,
|
|
mEv_EVENT_RUMOR_FISHING_TOURNEY_1,
|
|
mEv_EVENT_TALK_FISHING_TOURNEY_1,
|
|
mEv_EVENT_RUMOR_MORNING_AEROBICS,
|
|
mEv_EVENT_TALK_MORNING_AEROBICS,
|
|
mEv_EVENT_RUMOR_FIREWORKS_SHOW,
|
|
mEv_EVENT_76,
|
|
mEv_EVENT_RUMOR_METEOR_SHOWER,
|
|
mEv_EVENT_RUMOR_HARVEST_MOON_DAY,
|
|
mEv_EVENT_RUMOR_FALL_SPORTS_FAIR,
|
|
mEv_EVENT_RUMOR_MUSHROOM_SEASON,
|
|
mEv_EVENT_TALK_MUSHROOM_SEASON,
|
|
mEv_EVENT_RUMOR_HALLOWEEN,
|
|
mEv_EVENT_RUMOR_FISHING_TOURNEY_2,
|
|
mEv_EVENT_TALK_FISHING_TOURNEY_2,
|
|
mEv_EVENT_RUMOR_TOY_DAY,
|
|
mEv_EVENT_RUMOR_NEW_YEARS_EVE_COUNTDOWN
|
|
};
|
|
|
|
static int n_event_rumors = ARRAY_COUNT(event_rumor_table);
|
|
|
|
static u16 special_event_types[] = {
|
|
mEv_EVENT_SHOP_SALE,
|
|
mEv_EVENT_DESIGNER,
|
|
mEv_EVENT_BROKER_SALE,
|
|
mEv_EVENT_ARTIST,
|
|
mEv_EVENT_CARPET_PEDDLER,
|
|
mEv_EVENT_GYPSY
|
|
};
|
|
|
|
static int n_special_event_type = ARRAY_COUNT(special_event_types);
|
|
|
|
static int 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_year_t year = Common_Get(time.rtc_time.year);
|
|
lbRTC_day_t day = last_day[month - 1];
|
|
|
|
if (month != lbRTC_FEBRUARY) {
|
|
return day;
|
|
}
|
|
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;
|
|
lbRTC_month_t temp;
|
|
lbRTC_month_t i;
|
|
int weekday;
|
|
|
|
month = rtc_time->month & 0xF;
|
|
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, temp = month + 1; temp <= lbRTC_MONTHS_MAX; i++, temp++) {
|
|
int last = last_day_of_month(i);
|
|
int t = (weekday1st[i] + (u8)last) % lbRTC_WEEK;
|
|
|
|
if (t < 0) {
|
|
t += lbRTC_WEEK;
|
|
}
|
|
|
|
weekday1st[temp] = t;
|
|
}
|
|
|
|
for (temp = month - 1, i = month; temp >= lbRTC_JANUARY; i--, temp--) {
|
|
lbRTC_day_t last_day = last_day_of_month(temp);
|
|
|
|
weekday = (weekday1st[i] - last_day) % lbRTC_WEEK;
|
|
if (weekday < 0) {
|
|
weekday += lbRTC_WEEK;
|
|
}
|
|
|
|
weekday1st[temp] = weekday;
|
|
}
|
|
}
|
|
|
|
static int check_date_range(u16 date, u16 lower_bound, u16 upper_bound) {
|
|
int res;
|
|
|
|
if (lower_bound > upper_bound) {
|
|
res = FALSE;
|
|
if (lower_bound <= date || date <= upper_bound) {
|
|
res = TRUE;
|
|
}
|
|
}
|
|
else {
|
|
res = FALSE;
|
|
if (lower_bound <= date && date <= upper_bound) {
|
|
res = TRUE;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int check_ymdh_range(u32 ymdh, u32 lower_bound, u32 upper_bound) {
|
|
int res = FALSE;
|
|
|
|
if (lower_bound <= ymdh && ymdh <= upper_bound) {
|
|
res = TRUE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static u16 after_n_day(u16 month_day, int n_day) {
|
|
mEv_MonthDay_u after;
|
|
u8 day;
|
|
|
|
after.raw = month_day;
|
|
|
|
if (n_day >= 0) {
|
|
day = last_day_of_month(after.month);
|
|
|
|
after.day = after.day + n_day;
|
|
if (after.day > day) {
|
|
if (after.month == lbRTC_DECEMBER) {
|
|
after.month = lbRTC_JANUARY;
|
|
}
|
|
else {
|
|
after.month++;
|
|
}
|
|
|
|
after.day -= 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--;
|
|
}
|
|
|
|
day = last_day_of_month(after.month);
|
|
after.day += day;
|
|
}
|
|
}
|
|
|
|
return after.raw;
|
|
}
|
|
|
|
extern lbRTC_day_t mEv_get_next_weekday(lbRTC_weekday_t weekday) {
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
lbRTC_weekday_t next_weekday;
|
|
lbRTC_day_t day;
|
|
lbRTC_day_t last_day;
|
|
|
|
if (weekday >= rtc_time->weekday) {
|
|
day = rtc_time->day + (weekday - rtc_time->weekday);
|
|
}
|
|
else {
|
|
day = rtc_time->day + (lbRTC_WEEK - (rtc_time->weekday - weekday));
|
|
}
|
|
|
|
last_day = last_day_of_month(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) {
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
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;
|
|
int last_day = last_day_of_month(month);
|
|
|
|
if (week == mEv_SCHEDULE_EVERY_WEEK) {
|
|
if (month > rtc_time->month) {
|
|
week = 1; /* 1st week of this month */
|
|
}
|
|
else if (month < rtc_time->month) {
|
|
week = mEv_SCHEDULE_LAST_WEEKDAY_OF_MONTH; /* last weekday of the month */
|
|
}
|
|
else {
|
|
day = rtc_time->day - (rtc_time->weekday - weekday);
|
|
|
|
if (day > (u8)last_day) {
|
|
week = mEv_SCHEDULE_LAST_WEEKDAY_OF_MONTH;
|
|
}
|
|
else {
|
|
week = 0; /* cleared */
|
|
}
|
|
}
|
|
}
|
|
|
|
if (week == mEv_SCHEDULE_LAST_WEEKDAY_OF_MONTH) {
|
|
lbRTC_day_t d = last_day;
|
|
int t_day = (-1 + d + weekday1st[month]) % lbRTC_WEEK; /* get the weekday of the first day of next month */
|
|
|
|
if (weekday <= t_day) {
|
|
day = d - (t_day - weekday);
|
|
}
|
|
else {
|
|
day = (d - (t_day - weekday)) - lbRTC_WEEK;
|
|
}
|
|
}
|
|
else if (week != 0) {
|
|
int t_day = weekday1st[month];
|
|
|
|
if (weekday >= t_day) {
|
|
day = 1 + (week - 1) * lbRTC_WEEK + (weekday - t_day);
|
|
}
|
|
else {
|
|
day = 1 + week * lbRTC_WEEK + (weekday - t_day);
|
|
}
|
|
}
|
|
|
|
return day;
|
|
}
|
|
|
|
static lbRTC_weekday_t weekday1st[lbRTC_MONTHS_MAX];
|
|
|
|
extern int mEv_weekday2day(lbRTC_month_t month, int week, int weekday) {
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
lbRTC_day_t day = 0;
|
|
|
|
if (week == mEv_SCHEDULE_EVERY_WEEK) {
|
|
if (month > rtc_time->month) {
|
|
week = 1; /* 1st week of this month */
|
|
}
|
|
else if (month < rtc_time->month) {
|
|
week = mEv_SCHEDULE_LAST_WEEKDAY_OF_MONTH; /* last weekday of the month */
|
|
}
|
|
else {
|
|
day = rtc_time->day - (rtc_time->weekday - weekday);
|
|
week = 0; /* cleared */
|
|
}
|
|
}
|
|
|
|
if (week == mEv_SCHEDULE_LAST_WEEKDAY_OF_MONTH) {
|
|
lbRTC_day_t last_day = last_day_of_month(month);
|
|
int t_day = (-1 + last_day + weekday1st[month]) % lbRTC_WEEK; /* get the weekday of the first day of next month */
|
|
|
|
if (weekday <= t_day) {
|
|
day = last_day - (t_day - weekday);
|
|
}
|
|
else {
|
|
day = (last_day - (t_day - weekday)) - lbRTC_WEEK;
|
|
}
|
|
}
|
|
else if (week != 0) {
|
|
int t_day = weekday1st[month];
|
|
|
|
if (weekday >= t_day) {
|
|
day = 1 + (week - 1) * lbRTC_WEEK + (weekday - t_day);
|
|
}
|
|
else {
|
|
day = 1 + week * lbRTC_WEEK + (weekday - t_day);
|
|
}
|
|
}
|
|
|
|
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)) != 0) {
|
|
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];
|
|
mEv_event_today_c* ev_today = &event_today[idx];
|
|
|
|
if (idx == 0xFF) {
|
|
return -1;
|
|
}
|
|
else {
|
|
return get_end_time(ev_today->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(u16 month_day, mEv_schedule_c* schedule) {
|
|
mEv_event_today_c* ev_today;
|
|
u8 idx = index_today[schedule->type];
|
|
int res = FALSE;
|
|
|
|
if (idx != 0xFF) {
|
|
ev_today = &event_today[idx];
|
|
res = FALSE;
|
|
}
|
|
else {
|
|
int idx = search_empty_event_today();
|
|
|
|
if (idx >= mEv_TODAY_EVENT_NUM) {
|
|
return FALSE;
|
|
}
|
|
|
|
index_today[schedule->type] = idx;
|
|
ev_today = &event_today[idx];
|
|
n_today_events++;
|
|
}
|
|
|
|
{
|
|
u8 start_hour = schedule->date[0].d.hour;
|
|
u8 end_hour = schedule->date[1].d.hour;
|
|
u32 n;
|
|
lbRTC_hour_t i;
|
|
|
|
if ((start_hour & mEv_SCHEDULE_TODAY) != 0) {
|
|
ev_today->begin_date.raw = month_day;
|
|
ev_today->end_date.raw = month_day;
|
|
start_hour &= ~mEv_SCHEDULE_TODAY;
|
|
end_hour &= ~mEv_SCHEDULE_TODAY;
|
|
}
|
|
else {
|
|
ev_today->begin_date.raw = schedule->date[0].md;
|
|
ev_today->end_date.raw = schedule->date[1].md;
|
|
}
|
|
|
|
if ((start_hour & mEv_SCHEDULE_MULTIDAY) != 0) {
|
|
start_hour &= ~mEv_SCHEDULE_MULTIDAY;
|
|
end_hour &= ~mEv_SCHEDULE_MULTIDAY;
|
|
|
|
if (month_day != schedule->date[0].md) {
|
|
start_hour = 0;
|
|
}
|
|
|
|
if (month_day != schedule->date[1].md) {
|
|
end_hour = 23;
|
|
}
|
|
}
|
|
|
|
n = 1;
|
|
for (i = 0; i < 24; i++) {
|
|
if (start_hour <= i && i <= end_hour) {
|
|
ev_today->active_hours |= n;
|
|
}
|
|
|
|
n <<= 1;
|
|
}
|
|
}
|
|
|
|
ev_today->type = schedule->type;
|
|
ev_today->status |= mEv_STATUS_EXIST;
|
|
|
|
return res;
|
|
}
|
|
|
|
static int check_and_clear_event_today(Event_c* event, int type) {
|
|
u8 idx = index_today[type];
|
|
|
|
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;
|
|
today_event->active_hours = 0;
|
|
today_event->end_date.raw = 0;
|
|
today_event->status = 0;
|
|
n_today_events--;
|
|
index_today[type] = 0xFF;
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static int delete_too_short_event(Event_c* event, int type, u32 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.raw = date;
|
|
new_date.d.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.md = today_event->end_date.raw;
|
|
new_date.d.hour = mEv_get_end_time(today_event->type);
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (new_date.raw != date) {
|
|
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() {
|
|
int i;
|
|
|
|
for (i = 0; i < mEv_TODAY_EVENT_NUM; i++) {
|
|
mEv_event_today_c* ev_today = &event_today[i];
|
|
|
|
ev_today->type = -1;
|
|
ev_today->active_hours = 0;
|
|
ev_today->begin_date.raw = ev_today->end_date.raw = 0;
|
|
ev_today->status = 0;
|
|
}
|
|
|
|
n_today_events = 0;
|
|
for (i = 0; i < mEv_EVENT_NUM; i++) {
|
|
index_today[i] = 0xFF;
|
|
}
|
|
}
|
|
|
|
static void init_time_seat() {
|
|
int i;
|
|
|
|
for (i = 0; i < mEv_TODAY_EVENT_NUM; i++) {
|
|
mEv_event_today_c* ev_today = &event_today[i];
|
|
|
|
ev_today->active_hours = 0;
|
|
ev_today->begin_date.raw = ev_today->end_date.raw = 0;
|
|
ev_today->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;
|
|
}
|
|
|
|
#define mEv_MonthDay(m, d) (((u8)(m) << 8) | ((u8)(d)))
|
|
#define mEv_MonthDay_GetDay(md) ((md) & 0xFF)
|
|
#define mEv_MonthDay_GetMonth(md) (((md) >> 8) & 0xFF)
|
|
#define mEv_MonthDay_SetDay(md, d) (((md) & 0xFF00) | (u8)(d))
|
|
#define mEv_MonthDay_SetMonth(md, m) (((md) & 0xFF) | ((u8)(m) << 8))
|
|
|
|
#define mEv_YearMonthDayHour(y, m, d, h) ((u32)(((u8)(y) << 24) | ((u8)(m) << 16) | ((u8)(d) << 8) | ((u8)(h))))
|
|
|
|
/* @nonmatching TODO: This function needs a lot of help matching. Current best scratch: https://decomp.me/scratch/0EXoP */
|
|
static int init_special_event(int new_event) {
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
mEv_special_c* special_ev = &Save_Get(event_save_data).special;
|
|
int res = FALSE;
|
|
|
|
switch (Common_Get(last_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_common).special_event.type == mEv_EVENT_SHOP_SALE) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// fallthrough case
|
|
default:
|
|
{
|
|
mEv_ymdh_u rtc_ymdh;
|
|
mEv_ymdh_u special_ymdh;
|
|
mEv_ymdh_u special_end_ymdh;
|
|
mEv_MonthDay_u special_monthday;
|
|
mEv_schedule_date_u rtc_sched;
|
|
u16 special_end_monthday;
|
|
u16 sale_day_monthday;
|
|
mEv_save_common_data_c* ev_save_common = Save_GetPointer(event_save_common);
|
|
|
|
//u16 rtc_monthday = mEv_MonthDay(Common_Get(time.rtc_time.month), Common_Get(time.rtc_time.day));
|
|
//u32 rtc_ymdh = (u32)(((Common_Get(time.rtc_time.year) % 100) << 24) | (rtc_monthday << 8) | Common_Get(time.rtc_time.hour));
|
|
// u32 special_ymdh = (u32)(((Save_Get(event_year_ymd.year) % 100) << 24) | (Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL0] << 8));
|
|
// u32 special_end_ymdh = (u32)(
|
|
// (((Save_Get(event_year_ymd.year) % 100) - ((Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL2] < Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL0] && rtc_monthday < Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL0]) ? 1 : 2)) << 24) |
|
|
// (Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL0] << 8) |
|
|
// (u8)get_special_event_end_time(Save_Get(event_save_common).special_event.type)
|
|
// );
|
|
|
|
rtc_sched.raw = 0;
|
|
rtc_sched.d.month = rtc_time->month;
|
|
rtc_sched.d.day = rtc_time->day;
|
|
|
|
rtc_ymdh.raw = (rtc_sched.md) << 8;
|
|
rtc_ymdh.year = rtc_time->year % 100;
|
|
rtc_ymdh.hour = rtc_time->hour;
|
|
|
|
special_ymdh.raw = ev_save_common->dates[mEv_SAVE_DATE_SPECIAL0] << 8;
|
|
special_ymdh.year = Save_Get(event_year) % 100;
|
|
|
|
//special_end_ymdh.raw = (special_ymdh.month_day.raw) << 8;
|
|
special_end_ymdh.year = (Save_Get(event_year) % 100) + ((ev_save_common->dates[mEv_SAVE_DATE_SPECIAL0] > ev_save_common->dates[mEv_SAVE_DATE_SPECIAL2] && ev_save_common->dates[mEv_SAVE_DATE_SPECIAL0] > rtc_sched.md) ? 0 : -1);
|
|
special_end_ymdh.hour = get_special_event_end_time(ev_save_common->special_event.type);
|
|
|
|
|
|
if (check_ymdh_range(rtc_ymdh.raw, special_ymdh.raw, special_end_ymdh.raw) == FALSE || new_event) {
|
|
int seed = Common_Get(now_private)->player_ID.player_id;
|
|
s16 type;
|
|
int next_event_day_gap;
|
|
|
|
res |= TRUE;
|
|
mEv_ClearSpecialEvent(special_ev);
|
|
seed += 1 + rtc_time->year - rtc_time->month + rtc_time->day + rtc_time->hour;
|
|
/* Sale Day */
|
|
sale_day_monthday = after_n_day(((lbRTC_NOVEMBER) << 8) | m_weekday2day(lbRTC_NOVEMBER, mEv_SCHEDULE_4TH_WEEKDAY(lbRTC_THURSDAY)), 1);
|
|
|
|
do {
|
|
sad_label:
|
|
/* Select a new unique random event */
|
|
do {
|
|
type = special_event_types[seed % n_special_event_type];
|
|
seed++;
|
|
} while (type == Save_Get(event_save_common).special_event.type);
|
|
|
|
mFAs_SetFieldRank();
|
|
next_event_day_gap = 1 +
|
|
((rtc_time->day + rtc_time->month * rtc_time->sec) %
|
|
((mFAs_FIELDRANK_SIX + 1) - mFAs_GetFieldRank()));
|
|
|
|
if (next_event_day_gap == 1) {
|
|
next_event_day_gap = 2; // minimum of 2 days between special events
|
|
}
|
|
|
|
special_monthday.raw = after_n_day(rtc_sched.md, next_event_day_gap);
|
|
if ((u16)rtc_sched.md <= sale_day_monthday && (u16)sale_day_monthday <= (u32)special_monthday.raw) {
|
|
/* Force the next special event to be Crazy Redd since Sale Day falls between now and the rolled event date */
|
|
special_monthday.raw = sale_day_monthday;
|
|
type = mEv_EVENT_BROKER_SALE;
|
|
}
|
|
|
|
/* Set event start hour */
|
|
Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL3] = 6;
|
|
|
|
switch (type) {
|
|
case mEv_EVENT_GYPSY:
|
|
break;
|
|
|
|
case mEv_EVENT_SHOP_SALE:
|
|
{
|
|
lbRTC_day_t last_day = last_day_of_month(special_monthday.month);
|
|
|
|
if (
|
|
special_monthday.day != last_day &&
|
|
(special_monthday.raw < mEv_MonthDay(lbRTC_JANUARY, 1) || special_monthday.raw > mEv_MonthDay(lbRTC_JANUARY, 3)) &&
|
|
mEv_CheckEvent(mEv_SAVED_RENEWSHOP) != TRUE
|
|
) {
|
|
/* Set shop sale starting hour randomly between 12PM and 7PM */
|
|
Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL3] = 12 + RANDOM(8);
|
|
goto hate_gotos;
|
|
}
|
|
goto sad_label;
|
|
}
|
|
|
|
case mEv_EVENT_BROKER_SALE:
|
|
{
|
|
if (special_monthday.raw != mEv_MonthDay(lbRTC_JULY, 4)) {
|
|
/* Set broker sale start hour to 6PM when it's not the Fireworks Festival */
|
|
Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL3] = 18;
|
|
goto hate_gotos;
|
|
}
|
|
goto sad_label;
|
|
}
|
|
|
|
default:
|
|
goto hate_gotos;
|
|
break;
|
|
}
|
|
} while (special_monthday.raw == mEv_MonthDay(lbRTC_DECEMBER, 31));
|
|
|
|
Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL3] = 21; // default event start time is 9pm?
|
|
|
|
hate_gotos:
|
|
{
|
|
mEv_save_common_data_c* ev_save_common = Save_GetPointer(event_save_common);
|
|
u16 year;
|
|
|
|
special_end_monthday = after_n_day(special_monthday.raw, type != mEv_EVENT_SHOP_SALE); // ??
|
|
year = rtc_time->year;
|
|
ev_save_common->special_event.type = type;
|
|
ev_save_common->dates[mEv_SAVE_DATE_SPECIAL0] = rtc_sched.md; // current date
|
|
ev_save_common->dates[mEv_SAVE_DATE_SPECIAL1] = special_monthday.raw; // start date
|
|
ev_save_common->dates[mEv_SAVE_DATE_SPECIAL2] = special_end_monthday; // end date
|
|
Save_Set(event_year, year);
|
|
Save_Get(post_office).leaflet_recipient_flags.event_flags = 0b1111; // deliver leaflet to all players if necessary for event
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static int update_special_event(mEv_schedule_c* sched) {
|
|
s16 type = Save_Get(event_save_common).special_event.type;
|
|
int active = TRUE;
|
|
|
|
switch (sched->type) {
|
|
case mEv_EVENT_ARTIST:
|
|
case mEv_EVENT_BROKER_SALE:
|
|
case mEv_EVENT_DESIGNER:
|
|
case mEv_EVENT_GYPSY:
|
|
case mEv_EVENT_SHOP_SALE:
|
|
case mEv_EVENT_CARPET_PEDDLER:
|
|
{
|
|
if (type != sched->type) {
|
|
sched->date[1].raw = 0;
|
|
sched->date[0].raw = 0;
|
|
active = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case mEv_EVENT_HANDBILL_SHOP_SALE:
|
|
{
|
|
if (type != mEv_EVENT_SHOP_SALE) {
|
|
sched->date[1].raw = 0;
|
|
sched->date[0].raw = 0;
|
|
active = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case mEv_EVENT_HANDBILL_BROKER:
|
|
{
|
|
if (type != mEv_EVENT_BROKER_SALE) {
|
|
sched->date[1].raw = 0;
|
|
sched->date[0].raw = 0;
|
|
active = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
active = FALSE;
|
|
break;
|
|
}
|
|
|
|
return active;
|
|
}
|
|
|
|
extern u16 mEv_get_bargain_day() {
|
|
u16 bargain_day = 0;
|
|
|
|
if (Save_Get(event_save_common).special_event.type == mEv_EVENT_SHOP_SALE) {
|
|
bargain_day = Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL1];
|
|
}
|
|
|
|
return bargain_day;
|
|
}
|
|
|
|
static int is_special_event_valid() {
|
|
mEv_schedule_date_u date;
|
|
|
|
date.raw = 0;
|
|
date.d.month = Common_Get(time.rtc_time.month);
|
|
date.d.day = Common_Get(time.rtc_time.day);
|
|
|
|
return check_date_range(
|
|
date.md,
|
|
Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL0],
|
|
Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL2]
|
|
);
|
|
}
|
|
|
|
extern u16 mEv_get_special_event_day() {
|
|
u16 day = 0;
|
|
|
|
if (is_special_event_valid()) {
|
|
day = Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL1];
|
|
}
|
|
|
|
return day;
|
|
}
|
|
|
|
extern u16 mEv_get_special_event_type() {
|
|
u16 type = 0;
|
|
|
|
if (is_special_event_valid()) {
|
|
type = Save_Get(event_save_common).special_event.type;
|
|
}
|
|
|
|
return type;
|
|
}
|
|
|
|
extern int mEv_get_event_place(int event, int* bx, int* bz) {
|
|
mEv_place_data_c* place;
|
|
|
|
if (mEv_check_status(event, mEv_STATUS_RUN) != FALSE) {
|
|
place = mEv_get_common_place(event, 81);
|
|
|
|
if (place != NULL) {
|
|
*bx = place->block.x;
|
|
*bz = place->block.z;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern int mEv_bridge_time_check() {
|
|
lbRTC_time_c rtc_time = Common_Get(time.rtc_time);
|
|
|
|
return lbRTC_IsEqualDate(
|
|
Save_Get(bridge).build_date.year, Save_Get(bridge).build_date.month, Save_Get(bridge).build_date.day,
|
|
rtc_time.year, rtc_time.month, rtc_time.day
|
|
);
|
|
}
|
|
|
|
static void init_weekly_event() {
|
|
u16 sched_date;
|
|
lbRTC_time_c* rtc_time = &Common_Get(time.rtc_time);
|
|
mEv_kabu_peddler_c* kabu_peddler_data = &Save_Get(event_save_data).weekly.kabu_peddler;
|
|
mEv_MonthDay_u today_date;
|
|
u8 flag = 0;
|
|
u16 ghost_date;
|
|
u16 ghost_date2;
|
|
u16 monday_date;
|
|
u16 friday_date;
|
|
u16* event_dates = Save_Get(event_save_common).dates;
|
|
|
|
today_date.month = rtc_time->month;
|
|
today_date.day = rtc_time->day;
|
|
sched_date = event_dates[mEv_SAVE_DATE_WEEKLY];
|
|
|
|
switch (rtc_time->weekday) {
|
|
case lbRTC_SUNDAY:
|
|
{
|
|
/* Update Joan's data */
|
|
if (today_date.raw != sched_date) {
|
|
mEv_ClearEventKabuPeddler(kabu_peddler_data);
|
|
sched_date = today_date.raw;
|
|
event_dates[mEv_SAVE_DATE_WEEKLY] = sched_date;
|
|
Save_Get(event_save_common).weekly_event.type = mEv_EVENT_KABU_PEDDLER;
|
|
flag = 1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case lbRTC_SATURDAY:
|
|
{
|
|
/* Update K.K. Slider's data */
|
|
if (today_date.raw != sched_date) {
|
|
sched_date = today_date.raw;
|
|
event_dates[mEv_SAVE_DATE_WEEKLY] = sched_date;
|
|
Save_Get(event_save_common).weekly_event.type = mEv_EVENT_KK_SLIDER;
|
|
flag = 1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
monday_date = after_n_day(today_date.raw, lbRTC_MONDAY - rtc_time->weekday);
|
|
friday_date = after_n_day(today_date.raw, lbRTC_FRIDAY - rtc_time->weekday);
|
|
|
|
/* Check if we should reschedule Gulliver */
|
|
if (sched_date == 0 || check_date_range(sched_date, monday_date, friday_date) == FALSE) {
|
|
u8 ofs = 1 + (today_date.raw + rtc_time->hour) % 5;
|
|
/* Schedule a new date for the event between Monday & Friday */
|
|
sched_date = after_n_day(today_date.raw, ofs - rtc_time->weekday);
|
|
event_dates[mEv_SAVE_DATE_WEEKLY] = sched_date;
|
|
Save_Get(event_save_common).weekly_event.type = mEv_EVENT_DOZAEMON; // Gulliver
|
|
Save_Get(event_save_common).current_event_state = 0;
|
|
}
|
|
|
|
/* Check if Guillver should spawn today */
|
|
if (sched_date == today_date.raw) {
|
|
flag = mEv_EVENT_DOZAEMON;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Check if we should schedule Tortimer's 3rd bridge event */
|
|
if (rtc_time->weekday == lbRTC_SATURDAY || (rtc_time->weekday != lbRTC_SUNDAY && sched_date != today_date.raw)) {
|
|
/* Gulliver wasn't scheduled today, so check the criteria is met */
|
|
if (
|
|
Common_Get(player_no) != mPr_FOREIGNER &&
|
|
Save_Get(now_npc_max) >= ANIMAL_NUM_MAX &&
|
|
Save_Get(bridge).exists != TRUE &&
|
|
mSC_LightHouse_travel_check() == FALSE
|
|
) {
|
|
flag = mEv_EVENT_SONCHO_BRIDGE_MAKE;
|
|
}
|
|
|
|
/* Update bridge location seed and date */
|
|
if (flag == mEv_EVENT_SONCHO_BRIDGE_MAKE && Save_Get(event_save_common).bridge_day != today_date.raw) {
|
|
Save_Get(event_save_common).bridge_day = today_date.raw;
|
|
Save_Get(event_save_common).bridge_flags.raw++;
|
|
}
|
|
}
|
|
|
|
/* Check if Blanca should spawn */
|
|
if (
|
|
flag != mEv_EVENT_DOZAEMON &&
|
|
flag != mEv_EVENT_SONCHO_BRIDGE_MAKE &&
|
|
(mGH_check_birth2() || mMC_check_birth())
|
|
) {
|
|
flag = mEv_EVENT_MASK_NPC;
|
|
}
|
|
|
|
/* Initialize Wisp */
|
|
Save_Get(event_save_common).weekly_event.flags = flag;
|
|
Save_Get(event_save_common).ghost_event_type = mEv_EVENT_NUM; // Wisp is not set to spawn
|
|
ghost_date = Save_Get(event_save_common).ghost_day;
|
|
monday_date = after_n_day(today_date.raw, -lbRTC_WEEK);
|
|
friday_date = after_n_day(today_date.raw, 4);
|
|
|
|
/* Check if we should refresh Wisp's spawn date */
|
|
if (ghost_date == 0 || check_date_range(ghost_date, monday_date, friday_date) == FALSE) {
|
|
ghost_date = after_n_day(today_date.raw, 2 + RANDOM(3));
|
|
Save_Get(event_save_common).ghost_day = ghost_date;
|
|
}
|
|
|
|
/* Spawn Wisp if his scheduled appearance date is within [today-7, today] */
|
|
if (check_date_range(ghost_date, monday_date, today_date.raw)) {
|
|
Save_Get(event_save_common).ghost_event_type = mEv_EVENT_GHOST;
|
|
}
|
|
}
|
|
|
|
static void update_soncho_event(mEv_schedule_c* sched) {
|
|
switch (sched->type) {
|
|
case mEv_EVENT_SONCHO_VACATION_JANUARY:
|
|
case mEv_EVENT_SONCHO_VACATION_FEBRUARY:
|
|
{
|
|
if (mSC_LightHouse_Event_Start() == FALSE) {
|
|
sched->date[1].raw = 0;
|
|
sched->date[0].raw = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case mEv_EVENT_SONCHO_FISHING_TOURNEY_1:
|
|
{
|
|
if (Save_Get(event_save_common).soncho_event_type != 0xFF) {
|
|
sched->date[1].raw = 0;
|
|
sched->date[0].raw = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case mEv_EVENT_SONCHO_FISHING_TOURNEY_2:
|
|
{
|
|
if (Save_Get(event_save_common).soncho_event_type != 0xFF) {
|
|
sched->date[1].raw = 0;
|
|
sched->date[0].raw = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void update_soncho_event2(mEv_schedule_c* sched) {
|
|
switch (sched->type) {
|
|
case mEv_EVENT_SONCHO_VACATION_JANUARY:
|
|
case mEv_EVENT_SONCHO_VACATION_FEBRUARY:
|
|
case mEv_EVENT_SONCHO_NEW_YEARS_DAY:
|
|
case mEv_EVENT_SONCHO_GROUNDHOG_DAY:
|
|
case mEv_EVENT_SONCHO_SPRING_SPORTS_FAIR:
|
|
case mEv_EVENT_SONCHO_APRILFOOLS_DAY:
|
|
case mEv_EVENT_SONCHO_CHERRY_BLOSSOM_FESTIVAL:
|
|
case mEv_EVENT_SONCHO_NATURE_DAY:
|
|
case mEv_EVENT_SONCHO_SPRING_CLEANING:
|
|
case mEv_EVENT_SONCHO_MOTHERS_DAY:
|
|
case mEv_EVENT_SONCHO_GRADUATION_DAY:
|
|
case mEv_EVENT_SONCHO_FATHERS_DAY:
|
|
case mEv_EVENT_SONCHO_FISHING_TOURNEY_1:
|
|
case mEv_EVENT_SONCHO_TOWN_DAY:
|
|
case mEv_EVENT_SONCHO_FIREWORKS_SHOW:
|
|
case mEv_EVENT_SONCHO_METEOR_SHOWER:
|
|
case mEv_EVENT_SONCHO_FOUNDERS_DAY:
|
|
case mEv_EVENT_SONCHO_LABOR_DAY:
|
|
case mEv_EVENT_SONCHO_FALL_SPORTS_FAIR:
|
|
case mEv_EVENT_SONCHO_HARVEST_MOON_FESTIVAL:
|
|
case mEv_EVENT_SONCHO_EXPLORERS_DAY:
|
|
case mEv_EVENT_SONCHO_HALLOWEEN:
|
|
case mEv_EVENT_SONCHO_MAYORS_DAY:
|
|
case mEv_EVENT_SONCHO_OFFICERS_DAY:
|
|
case mEv_EVENT_SONCHO_FISHING_TOURNEY_2:
|
|
case mEv_EVENT_SONCHO_HARVEST_FESTIVAL:
|
|
case mEv_EVENT_SONCHO_SALE_DAY:
|
|
case mEv_EVENT_SONCHO_SNOW_DAY:
|
|
case mEv_EVENT_SONCHO_TOY_DAY:
|
|
case mEv_EVENT_TALK_NEW_YEARS_COUNTDOWN:
|
|
{
|
|
if (Save_Get(event_save_common).weekly_event.flags == mEv_EVENT_SONCHO_BRIDGE_MAKE) {
|
|
Save_Get(event_save_common).weekly_event.flags = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Update the event type to prefer these events over the fishing tourney event if they coincide */
|
|
switch (sched->type) {
|
|
case mEv_EVENT_SONCHO_FATHERS_DAY:
|
|
case mEv_EVENT_SONCHO_OFFICERS_DAY:
|
|
Save_Get(event_save_common).soncho_event_type = sched->type;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void update_sports_fair(mEv_schedule_c* sched, lbRTC_day_t* equinox_day) {
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
|
|
switch (sched->type) {
|
|
case mEv_EVENT_SPRING_EQUINOX:
|
|
case mEv_EVENT_SONCHO_SPRING_SPORTS_FAIR:
|
|
{
|
|
if (
|
|
rtc_time->month != lbRTC_MARCH ||
|
|
rtc_time->day != lbRk_VernalEquinoxDay(rtc_time->year)
|
|
) {
|
|
sched->date[1].raw = 0;
|
|
sched->date[0].raw = 0;
|
|
}
|
|
else {
|
|
sched->date[0].d.day = rtc_time->day;
|
|
sched->date[1].d.day = rtc_time->day;
|
|
*equinox_day = rtc_time->day;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case mEv_EVENT_RUMOR_SPRING_SPORTS_FAIR:
|
|
{
|
|
int vernal_day = lbRk_VernalEquinoxDay(rtc_time->year);
|
|
|
|
sched->date[0].d.day = vernal_day - 10;
|
|
sched->date[1].d.day = vernal_day - 1;
|
|
break;
|
|
}
|
|
|
|
case mEv_EVENT_AUTUMN_EQUINOX:
|
|
case mEv_EVENT_SONCHO_FALL_SPORTS_FAIR:
|
|
{
|
|
if (
|
|
rtc_time->month != lbRTC_SEPTEMBER ||
|
|
rtc_time->day != lbRk_AutumnalEquinoxDay(rtc_time->year)
|
|
) {
|
|
sched->date[1].raw = 0;
|
|
sched->date[0].raw = 0;
|
|
}
|
|
else {
|
|
sched->date[0].d.day = rtc_time->day;
|
|
sched->date[1].d.day = rtc_time->day;
|
|
*equinox_day = rtc_time->day;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case mEv_EVENT_RUMOR_FALL_SPORTS_FAIR:
|
|
{
|
|
int autumnal_day = lbRk_AutumnalEquinoxDay(rtc_time->year);
|
|
|
|
sched->date[0].d.day = autumnal_day - 10;
|
|
sched->date[1].d.day = autumnal_day - 1;
|
|
break;
|
|
}
|
|
|
|
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_SPORTS_FAIR:
|
|
case mEv_EVENT_WEATHER_SPORTS_FAIR:
|
|
{
|
|
if (*equinox_day == 0) {
|
|
sched->date[1].raw = 0;
|
|
sched->date[0].raw = 0;
|
|
}
|
|
else {
|
|
sched->date[0].d.day = *equinox_day;
|
|
sched->date[1].d.day = *equinox_day;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void update_event_rumor(mEv_schedule_c* sched) {
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
int equinox_day;
|
|
|
|
switch (sched->type) {
|
|
case mEv_EVENT_RUMOR_SPRING_SPORTS_FAIR:
|
|
{
|
|
equinox_day = lbRk_VernalEquinoxDay(rtc_time->year);
|
|
sched->date[0].d.day = equinox_day - 10;
|
|
sched->date[1].d.day = equinox_day - 1;
|
|
break;
|
|
}
|
|
|
|
case mEv_EVENT_TALK_FISHING_TOURNEY_1:
|
|
sched->date[1].d.day = lbRTC_Weekly_day(rtc_time->year, lbRTC_JUNE, mEv_SCHEDULE_LAST_WEEKDAY_OF_MONTH, lbRTC_SUNDAY);
|
|
break;
|
|
|
|
case mEv_EVENT_RUMOR_HARVEST_MOON_DAY:
|
|
{
|
|
lbRTC_ymd_c harvest_moon_ymd;
|
|
lbRTC_time_c harvest_moon_day;
|
|
lbRTC_day_t beg_day;
|
|
lbRTC_month_t beg_month;
|
|
lbRTC_day_t end_day;
|
|
lbRTC_month_t end_month;
|
|
|
|
lbRk_HarvestMoonDay(&harvest_moon_ymd, rtc_time->year);
|
|
harvest_moon_day.year = harvest_moon_ymd.year;
|
|
harvest_moon_day.month = harvest_moon_ymd.month;
|
|
harvest_moon_day.day = harvest_moon_ymd.day;
|
|
|
|
/* Calculate rumor end date */
|
|
lbRTC_Sub_DD(&harvest_moon_day, 1);
|
|
end_month = harvest_moon_day.month;
|
|
end_day = harvest_moon_day.day;
|
|
|
|
/* Calculate rumor start date */
|
|
lbRTC_Sub_DD(&harvest_moon_day, lbRTC_WEEK - 1);
|
|
|
|
beg_month = harvest_moon_day.month;
|
|
beg_day = harvest_moon_day.day;
|
|
sched->date[0].d.month = beg_month;
|
|
sched->date[0].d.day = beg_day;
|
|
sched->date[1].d.month = end_month;
|
|
sched->date[1].d.day = end_day;
|
|
break;
|
|
}
|
|
|
|
case mEv_EVENT_RUMOR_FALL_SPORTS_FAIR:
|
|
{
|
|
equinox_day = lbRk_AutumnalEquinoxDay(rtc_time->year);
|
|
sched->date[0].d.day = equinox_day - 10;
|
|
sched->date[1].d.day = equinox_day - 1;
|
|
break;
|
|
}
|
|
|
|
case mEv_EVENT_TALK_FISHING_TOURNEY_2:
|
|
sched->date[1].d.day = lbRTC_Weekly_day(rtc_time->year, lbRTC_NOVEMBER, mEv_SCHEDULE_LAST_WEEKDAY_OF_MONTH, lbRTC_SUNDAY);
|
|
break;
|
|
|
|
case mEv_EVENT_RUMOR_HARVEST_FESTIVAL:
|
|
sched->date[1].d.day = lbRTC_Weekly_day(rtc_time->year, lbRTC_NOVEMBER, 4, lbRTC_THURSDAY) - 1; // 4th Thursday in November
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void update_weekly_event(mEv_schedule_c* sched) {
|
|
s16 type = Save_Get(event_save_common).weekly_event.type;
|
|
|
|
switch (sched->type) {
|
|
case mEv_EVENT_KK_SLIDER:
|
|
case mEv_EVENT_KABU_PEDDLER:
|
|
{
|
|
if (type != sched->type) {
|
|
sched->date[1].raw = 0;
|
|
sched->date[0].raw = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case mEv_EVENT_DOZAEMON:
|
|
{
|
|
if (Save_Get(event_save_common).weekly_event.flags == mEv_EVENT_SONCHO_BRIDGE_MAKE || type != sched->type) {
|
|
sched->date[1].raw = 0;
|
|
sched->date[0].raw = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case mEv_EVENT_SONCHO_BRIDGE_MAKE:
|
|
case mEv_EVENT_MASK_NPC:
|
|
{
|
|
if (Save_Get(event_save_common).weekly_event.flags != sched->type) {
|
|
sched->date[1].raw = 0;
|
|
sched->date[0].raw = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case mEv_EVENT_BRIDGE_MAKE:
|
|
{
|
|
if (Save_Get(bridge).pending != TRUE || Save_Get(bridge).exists || mEv_bridge_time_check() == lbRTC_OVER) {
|
|
sched->date[1].raw = 0;
|
|
sched->date[0].raw = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case mEv_EVENT_GHOST:
|
|
{
|
|
if (Save_Get(event_save_common).ghost_event_type != mEv_EVENT_GHOST) {
|
|
sched->date[1].raw = 0;
|
|
sched->date[0].raw = 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// forward declarations
|
|
static int clear_active(int type);
|
|
static int set_active(int type);
|
|
|
|
static void update_active(Event_c* event) {
|
|
mEv_place_data_c* place_data;
|
|
mEv_event_today_c* today_event;
|
|
int hour = Common_Get(time.rtc_time.hour);
|
|
int i;
|
|
|
|
/* Update active events */
|
|
for (i = 0; i < mEv_TODAY_EVENT_NUM; i++) {
|
|
today_event = &event_today[i];
|
|
|
|
if (today_event->type != -1 && index_today[today_event->type] != 0xFF) {
|
|
if (mEv_check_status(today_event->type, mEv_STATUS_ERROR) != FALSE) {
|
|
continue;
|
|
}
|
|
|
|
if (today_event->type == mEv_EVENT_SPORTS_FAIR &&
|
|
Common_Get(event_common).fieldday_event_over_status != today_event->type) {
|
|
if (clear_active(today_event->type)) {
|
|
event->changed_num++;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if ((today_event->active_hours & mEv_EVENT_HOUR_START_EVENT)) {
|
|
if (set_active(today_event->type)) {
|
|
event->changed_num++;
|
|
}
|
|
|
|
today_event->active_hours &= ~mEv_EVENT_HOUR_START_EVENT;
|
|
}
|
|
else if (
|
|
today_event->type >= mEv_EVENT_ARTIST && today_event->type <= mEv_EVENT_CARPET_PEDDLER &&
|
|
today_event->type == Save_Get(event_save_common).delete_event_id
|
|
) {
|
|
if (clear_active(today_event->type)) {
|
|
event->changed_num++;
|
|
}
|
|
|
|
Save_Get(event_save_common).delete_event_id = 0;
|
|
today_event->active_hours = mEv_EVENT_HOUR_CLEAR_EVENT;
|
|
}
|
|
else if ((today_event->active_hours & (1 << hour))) {
|
|
if (Common_Get(event_common).fieldday_event_over_status != -1 &&
|
|
(today_event->type == mEv_EVENT_SPORTS_FAIR_BALL_TOSS ||
|
|
today_event->type == mEv_EVENT_SPORTS_FAIR_TUG_OF_WAR ||
|
|
today_event->type == mEv_EVENT_SPORTS_FAIR_FOOT_RACE)) {
|
|
if (clear_active(today_event->type)) {
|
|
event->changed_num++;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
if (today_event->type != 0 && today_event->type == Common_Get(event_common).too_short) {
|
|
today_event->active_hours |= mEv_EVENT_HOUR_TOO_SHORT_EVENT;
|
|
}
|
|
else if (set_active(today_event->type)) {
|
|
event->changed_num++;
|
|
}
|
|
}
|
|
else {
|
|
place_data = mEv_get_common_place(today_event->type, 81);
|
|
|
|
if (today_event->type != 0 && today_event->type == Common_Get(event_common).too_short) {
|
|
Common_Get(event_common).too_short = 0;
|
|
}
|
|
else if (place_data != NULL) {
|
|
if (place_data->block.x != event->block_x || place_data->block.z != event->block_z) {
|
|
if (clear_active(today_event->type)) {
|
|
event->changed_num++;
|
|
}
|
|
}
|
|
} else {
|
|
if (clear_active(today_event->type)) {
|
|
event->changed_num++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((today_event->active_hours & mEv_EVENT_HOUR_CLEAR_EVENT) &&
|
|
mEv_check_status(today_event->type, mEv_STATUS_RUN) == FALSE) {
|
|
today_event->active_hours = 0;
|
|
}
|
|
}
|
|
|
|
/* Update active rumors */
|
|
mEv_clear_rumor();
|
|
for (i = 0; i < n_event_rumors; i++) {
|
|
if (mEv_check_status(event_rumor_table[i], mEv_STATUS_ACTIVE)) {
|
|
mEv_spread_rumor(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
static u32 decode_date(u32 d) {
|
|
mEv_schedule_date_u date;
|
|
mEv_save_common_data_c* ev_common = Save_GetPointer(event_save_common);
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
int month;
|
|
int day;
|
|
int hour;
|
|
|
|
date.raw = d;
|
|
|
|
/* Process month */
|
|
month = date.d.month;
|
|
if ((month & mEv_SCHEDULE_USE_SAVE_MONTH)) {
|
|
date.md = Save_Get(event_save_common).dates[month & 0xF];
|
|
}
|
|
else if ((month & mEv_SCHEDULE_NOW_MONTH)) {
|
|
date.d.month = rtc_time->month;
|
|
}
|
|
else if ((month & mEv_SCHEDULE_HARVEST_MOON_DATE)) {
|
|
lbRTC_ymd_c harvest_moon_ymd;
|
|
|
|
lbRk_HarvestMoonDay(&harvest_moon_ymd, rtc_time->year);
|
|
date.d.month = harvest_moon_ymd.month;
|
|
date.d.day = harvest_moon_ymd.day;
|
|
}
|
|
|
|
/* Process day */
|
|
day = date.d.day;
|
|
if ((day & mEv_SCHEDULE_WEEKLY)) {
|
|
date.d.day = m_weekday2day(date.d.month, day & ~mEv_SCHEDULE_DAY_AFTER);
|
|
|
|
if ((day & mEv_SCHEDULE_DAY_AFTER)) {
|
|
date.md = after_n_day(date.md, 1);
|
|
}
|
|
}
|
|
else if ((day & mEv_SCHEDULE_LAST_DAY_OF_MONTH)) {
|
|
date.d.day = last_day_of_month(date.d.month);
|
|
}
|
|
else if ((day & mEv_SCHEDULE_TOWN_DAY)) {
|
|
date.d.day = (date.d.day & ~mEv_SCHEDULE_TOWN_DAY) | Save_Get(town_day);
|
|
}
|
|
|
|
/* Process hour */
|
|
hour = date.d.hour;
|
|
if ((hour & mEv_SCHEDULE_USE_SAVE_SLOT_VALUE)) {
|
|
date.d.hour = Save_Get(event_save_common).dates[(hour & 0x1F) % 8] | (hour & 0xC0);
|
|
}
|
|
|
|
return date.raw;
|
|
}
|
|
|
|
static int set_one_time_active(int event) {
|
|
u8 idx = index_today[event];
|
|
|
|
if (idx != 0xFF) {
|
|
mEv_event_today_c* ev_today = &event_today[idx];
|
|
ev_today->active_hours |= mEv_EVENT_HOUR_START_EVENT;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static int first_enter_check() {
|
|
switch (Common_Get(last_scene_no)) {
|
|
case SCENE_START_DEMO:
|
|
case SCENE_START_DEMO2:
|
|
case SCENE_PLAYERSELECT:
|
|
case SCENE_PLAYERSELECT_2:
|
|
case SCENE_PLAYERSELECT_3:
|
|
case SCENE_PLAYERSELECT_SAVE:
|
|
case SCENE_START_DEMO3:
|
|
return TRUE;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static int effective_scene() {
|
|
switch (Save_Get(scene_no)) {
|
|
case SCENE_START_DEMO:
|
|
case SCENE_START_DEMO2:
|
|
case SCENE_PLAYERSELECT:
|
|
case SCENE_PLAYERSELECT_2:
|
|
case SCENE_PLAYERSELECT_3:
|
|
case SCENE_PLAYERSELECT_SAVE:
|
|
case SCENE_START_DEMO3:
|
|
return FALSE;
|
|
|
|
default:
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
static void update_schedule_today(Event_c* event) {
|
|
int month;
|
|
u8 equinox_day = 0;
|
|
mEv_schedule_date_u today_date;
|
|
mEv_MonthDay_u birthday_date;
|
|
mEv_schedule_c sched;
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
mEv_schedule_c* sched_p = &sched;
|
|
Private_c* priv = &Save_Get(private[Common_Get(player_no)]);
|
|
int i;
|
|
int type;
|
|
|
|
if (mEv_ArbeitPlayer_kari(Common_Get(player_no)) == FALSE) {
|
|
month = rtc_time->month;
|
|
|
|
today_date.d.month = month;
|
|
today_date.d.day = rtc_time->day;
|
|
today_date.d.hour = rtc_time->hour;
|
|
today_date.d._2 = 0;
|
|
Save_Get(event_save_common).dates[mEv_SAVE_DATE_TODAY] = today_date.md;
|
|
|
|
birthday_date.month = priv->birthday.month;
|
|
birthday_date.day = priv->birthday.day;
|
|
Save_Get(event_save_common).dates[mEv_SAVE_DATE_BIRTHDAY] = birthday_date.raw;
|
|
|
|
Save_Get(event_save_common).soncho_event_type = 0xFF;
|
|
|
|
/* Process every event */
|
|
for (i = 0; i < ARRAY_COUNT(event_schedule_data); i++) {
|
|
memcpy(sched_p, &event_schedule_data[i], sizeof(mEv_schedule_c));
|
|
|
|
/* Perform necessary adjustments */
|
|
update_soncho_event(sched_p);
|
|
update_sports_fair(sched_p, &equinox_day);
|
|
update_event_rumor(sched_p);
|
|
update_special_event(sched_p);
|
|
update_weekly_event(sched_p);
|
|
|
|
if (sched.type == mEv_EVENT_SUMMER_CAMPER) {
|
|
mEv_MonthDay_u camper_date;
|
|
|
|
switch (month) {
|
|
case lbRTC_JUNE:
|
|
case lbRTC_JULY:
|
|
case lbRTC_AUGUST:
|
|
sched.date[0].d.month = today_date.d.month;
|
|
break;
|
|
}
|
|
|
|
sched.date[0].raw = decode_date(sched.date[0].raw);
|
|
camper_date.month = sched.date[0].d.month;
|
|
camper_date.day = sched.date[0].d.day;
|
|
|
|
/* Move back to the previous week if processing on Sunday */
|
|
if (rtc_time->weekday == lbRTC_SUNDAY) {
|
|
camper_date.raw = after_n_day(camper_date.raw, -lbRTC_WEEK);
|
|
sched.date[0].d.month = camper_date.month;
|
|
sched.date[0].d.day = camper_date.day;
|
|
}
|
|
|
|
/* Summer campers only stick around for one day */
|
|
camper_date.raw = after_n_day(camper_date.raw, 1);
|
|
sched.date[1].d.month = camper_date.month;
|
|
sched.date[1].d.day = camper_date.day;
|
|
}
|
|
else {
|
|
sched.date[0].raw = decode_date(sched.date[0].raw);
|
|
sched.date[1].raw = decode_date(sched.date[1].raw);
|
|
}
|
|
|
|
/* Check & add event if it is currently active */
|
|
if (check_date_range(today_date.md, sched.date[0].md, sched.date[1].md)) {
|
|
update_soncho_event2(sched_p);
|
|
add_event_today(today_date.md, sched_p);
|
|
}
|
|
}
|
|
|
|
type = 0;
|
|
switch (Common_Get(last_scene_no)) {
|
|
case SCENE_KAMAKURA:
|
|
type = mEv_EVENT_KAMAKURA;
|
|
break;
|
|
case SCENE_BROKER_SHOP:
|
|
type = mEv_EVENT_BROKER_SALE;
|
|
break;
|
|
case SCENE_BUGGY:
|
|
type = mEv_EVENT_GYPSY;
|
|
break;
|
|
case SCENE_SHOP0:
|
|
case SCENE_CONVENI:
|
|
case SCENE_SUPER:
|
|
case SCENE_DEPART:
|
|
case SCENE_DEPART_2:
|
|
if (mEv_CheckEvent(mEv_SPNPC_EVENT)) {
|
|
type = mEv_EVENT_SHOP_SALE;
|
|
}
|
|
break;
|
|
case SCENE_TENT:
|
|
type = mEv_EVENT_SUMMER_CAMPER;
|
|
break;
|
|
}
|
|
|
|
if (type != 0 && gamePT->frame_counter == 0) {
|
|
mEv_schedule_c new_ev_sched = {
|
|
{
|
|
{ 100, 0, 0, 23 },
|
|
{ 100, 0, 0, 0 },
|
|
},
|
|
0,
|
|
0
|
|
};
|
|
|
|
new_ev_sched.type = type;
|
|
new_ev_sched.date[1].d.month = rtc_time->month;
|
|
new_ev_sched.date[0].d.month = rtc_time->month;
|
|
new_ev_sched.date[1].d.day = rtc_time->day;
|
|
new_ev_sched.date[0].d.day = rtc_time->day;
|
|
add_event_today(today_date.md, &new_ev_sched);
|
|
set_one_time_active(type);
|
|
}
|
|
|
|
type = 0;
|
|
switch (Save_Get(scene_no)) {
|
|
case SCENE_KAMAKURA:
|
|
type = mEv_EVENT_KAMAKURA;
|
|
break;
|
|
case SCENE_BROKER_SHOP:
|
|
type = mEv_EVENT_BROKER_SALE;
|
|
break;
|
|
case SCENE_BUGGY:
|
|
type = mEv_EVENT_GYPSY;
|
|
break;
|
|
case SCENE_SHOP0:
|
|
case SCENE_CONVENI:
|
|
case SCENE_SUPER:
|
|
case SCENE_DEPART:
|
|
case SCENE_DEPART_2:
|
|
if (mEv_CheckEvent(mEv_SPNPC_EVENT)) {
|
|
type = mEv_EVENT_SHOP_SALE;
|
|
}
|
|
break;
|
|
case SCENE_TENT:
|
|
type = mEv_EVENT_SUMMER_CAMPER;
|
|
break;
|
|
}
|
|
|
|
if (type != 0) {
|
|
mEv_schedule_c new_ev_sched = {
|
|
{
|
|
{ 100, 0, 0, 23 },
|
|
{ 100, 0, 0, 0 },
|
|
},
|
|
0,
|
|
0
|
|
};
|
|
|
|
new_ev_sched.type = type;
|
|
new_ev_sched.date[1].d.month = rtc_time->month;
|
|
new_ev_sched.date[0].d.month = rtc_time->month;
|
|
new_ev_sched.date[1].d.day = rtc_time->day;
|
|
new_ev_sched.date[0].d.day = rtc_time->day;
|
|
add_event_today(today_date.md, &new_ev_sched);
|
|
}
|
|
|
|
if (first_enter_check()) {
|
|
for (i = 0; i < mEv_EVENT_NUM; i++) {
|
|
delete_too_short_event(event, i, today_date.raw);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < mEv_EVENT_NUM; i++) {
|
|
check_and_clear_event_today(event, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void calc_start_block(int* bx, int* bz) {
|
|
if (Common_Get(door_data).next_scene_id == 0) {
|
|
*bx = 3;
|
|
*bz = 2;
|
|
|
|
if (Common_Get(clip).demo_clip != NULL && Common_Get(clip).demo_clip->type == mDemo_CLIP_TYPE_RIDE_OFF_DEMO) {
|
|
*bz = 1;
|
|
}
|
|
}
|
|
else if (Common_Get(door_data).next_scene_id == SCENE_RANDOM_NPC_TEST) {
|
|
*bx = Common_Get(door_data).exit_position.x / mFI_BK_WORLDSIZE_X;
|
|
*bz = Common_Get(door_data).exit_position.z / mFI_BK_WORLDSIZE_Z;
|
|
}
|
|
}
|
|
|
|
static void init_event(Event_c* event, int renewal_flag) {
|
|
event->month = 99;
|
|
event->day = 99;
|
|
event->hour = 99;
|
|
event->state = 0;
|
|
event->_02 = 0;
|
|
event->changed_num = 0;
|
|
event->block_z = 0;
|
|
event->block_x = 0;
|
|
|
|
calc_start_block(&event->block_x, &event->block_z);
|
|
funeral = FALSE;
|
|
dead = FALSE;
|
|
init_today_event();
|
|
|
|
if (renewal_flag != mEv_INIT_NO_RENEWAL) {
|
|
mEv_RenewalDataEveryDay();
|
|
init_weekday1st();
|
|
|
|
if (init_special_event(FALSE)) {
|
|
Save_Get(event_save_common).special_event.flags = 1;
|
|
}
|
|
|
|
init_weekly_event();
|
|
|
|
if (mEv_LivePlayer(Common_Get(player_no)) && mEv_LiveSonchoPresent() == FALSE) {
|
|
update_schedule_today(event);
|
|
event->month = Common_Get(time.rtc_time.month);
|
|
event->day = Common_Get(time.rtc_time.day);
|
|
event->hour = Common_Get(time.rtc_time.hour);
|
|
update_active(event);
|
|
update_save_area();
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void mEv_init(Event_c* event) {
|
|
int renewal_flag = mEv_INIT_NO_RENEWAL;
|
|
|
|
if (mEv_CheckTitleDemo() == 0 && effective_scene()) {
|
|
renewal_flag = mEv_INIT_RENEWAL;
|
|
}
|
|
|
|
init_event(event, renewal_flag);
|
|
}
|
|
|
|
extern void mEv_init_force(Event_c* event) {
|
|
int renewal_flag = mEv_INIT_NO_RENEWAL;
|
|
|
|
if (mEv_CheckTitleDemo() == 0) {
|
|
renewal_flag = mEv_INIT_FORCE_RENEWAL;
|
|
}
|
|
|
|
init_event(event, renewal_flag);
|
|
}
|
|
|
|
extern void mEv_2nd_init(Event_c* event) {
|
|
/* Disable morning aerobics if it is scheduled and the weather is rain */
|
|
if (Common_Get(weather) == mEnv_WEATHER_RAIN) {
|
|
u8 index = index_today[mEv_EVENT_MORNING_AEROBICS];
|
|
|
|
if (index != 0xFF) {
|
|
mEv_event_today_c* ev_today = &event_today[index];
|
|
|
|
mEv_clear_status(mEv_EVENT_MORNING_AEROBICS, mEv_STATUS_ACTIVE);
|
|
ev_today->type = -1;
|
|
index_today[mEv_EVENT_MORNING_AEROBICS] = 0xFF;
|
|
}
|
|
}
|
|
}
|
|
|
|
extern int mEv_PlayerOK() {
|
|
int res = FALSE;
|
|
|
|
if (mPlib_able_player_warp_forEvent() && mPlib_Get_unable_wade() == FALSE) {
|
|
res = TRUE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
extern void mEv_run(Event_c* event) {
|
|
status_edge = 0;
|
|
|
|
if (mEv_CheckTitleDemo() == 0) {
|
|
if (Save_Get(scene_no) == SCENE_START_DEMO || Save_Get(scene_no) == SCENE_START_DEMO2 ||
|
|
Save_Get(scene_no) == SCENE_START_DEMO3 || Save_Get(scene_no) == SCENE_PLAYERSELECT ||
|
|
Save_Get(scene_no) == SCENE_PLAYERSELECT_2 || Save_Get(scene_no) == SCENE_PLAYERSELECT_3 ||
|
|
Save_Get(scene_no) == SCENE_PLAYERSELECT_SAVE) {
|
|
return;
|
|
}
|
|
|
|
/* If the player is transitioning acres update the event's acre */
|
|
if (mFI_CheckPlayerWade(mFI_WADE_START) == TRUE) {
|
|
mFI_GetNextBlockNum(&event->block_x, &event->block_z);
|
|
}
|
|
|
|
if (mDemo_CheckDemo() == FALSE && mEv_PlayerOK() && mEv_LivePlayer(Common_Get(player_no)) &&
|
|
mEv_LiveSonchoPresent() == FALSE) {
|
|
lbRTC_day_t hour = (u32)Common_Get(time.rtc_time.hour);
|
|
lbRTC_day_t day = Common_Get(time.rtc_time.day);
|
|
|
|
if (event->day != day) {
|
|
mEv_RenewalDataEveryDay();
|
|
event->state = 2;
|
|
init_time_seat();
|
|
init_weekly_event();
|
|
update_schedule_today(event);
|
|
event->month = Common_Get(time.rtc_time.month);
|
|
event->day = day;
|
|
event->hour = hour;
|
|
update_active(event);
|
|
mEv_2nd_init(event);
|
|
mCD_calendar_wellcome_on();
|
|
} else if ((event->hour != hour)) {
|
|
event->hour = hour;
|
|
event->state = 1;
|
|
update_active(event);
|
|
} else if (mFI_CheckPlayerWade(mFI_WADE_END) == TRUE) {
|
|
update_active(event);
|
|
}
|
|
|
|
if (funeral) {
|
|
funeral = FALSE;
|
|
update_save_area();
|
|
}
|
|
}
|
|
|
|
if (dead != 0) {
|
|
dead--;
|
|
|
|
if (dead < 0 || dead > 4) {
|
|
dead = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static mActor_name_t l_ev_structure_table[] = {
|
|
BROKER_TENT,
|
|
FORTUNE_TENT,
|
|
DESIGNER_CAR,
|
|
KAMAKURA,
|
|
SAKURA_TABLE0,
|
|
AEROBICS_RADIO,
|
|
FIREWORKS_STALL0,
|
|
FIREWORKS_STALL1,
|
|
NEWYEAR_SHRINE0,
|
|
NEWYEAR_SHRINE1,
|
|
NEWYEAR_TABLE,
|
|
NEWYEAR_COUNTDOWN0,
|
|
NEWYEAR_COUNTDOWN1,
|
|
SPORTSFAIR_BALLS_RED,
|
|
SPORTSFAIR_BALLS_WHITE,
|
|
SPORTSFAIR_BASKET_RED,
|
|
SPORTSFAIR_BASKET_WHITE,
|
|
FISHCHECK_STAND0,
|
|
FISHCHECK_STAND1,
|
|
GHOG,
|
|
TENT,
|
|
SAKURA_TABLE1
|
|
};
|
|
|
|
static int num_of_l_ev_structure = ARRAY_COUNT(l_ev_structure_table);
|
|
|
|
extern void mEv_finish(Event_c* event) {
|
|
int ut_x;
|
|
int ut_z;
|
|
int bx;
|
|
int bz;
|
|
int i;
|
|
int bx_max = mFI_GetBlockXMax() - 1;
|
|
int bz_max = mFI_GetBlockZMax() - 1;
|
|
|
|
if (mFI_GET_TYPE(mFI_GetFieldId()) == mFI_FIELD_FG) {
|
|
|
|
for (i = 0; i < num_of_l_ev_structure; i++) {
|
|
for (bx = 1; bx < bx_max; bx++) {
|
|
for (bz = 1; bz < bz_max; bz++) {
|
|
int ut;
|
|
mActor_name_t structure = l_ev_structure_table[i];
|
|
|
|
for (ut = 0; mFI_SearchFGInBlock(&ut_x, &ut_z, structure, bx, bz); ut) {
|
|
mFI_SetFGStructure_common(structure, bx, bz, ut_x, ut_z, mFI_SET_STRUCTURE_REMOVE);
|
|
ut++;
|
|
if (ut > UT_TOTAL_NUM) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extern int mEv_check_schedule(int event) {
|
|
int hour = Common_Get(time.rtc_time.hour);
|
|
u8 index = index_today[event];
|
|
mEv_event_today_c* ev_today = &event_today[index];
|
|
|
|
if (index == 0xFF) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ((ev_today->status & mEv_STATUS_STOP)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ((ev_today->active_hours & mEv_EVENT_HOUR_TOO_SHORT_EVENT)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ((ev_today->active_hours & (1 << hour)) != 0) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern int mEv_check_run_today(int event) {
|
|
u8 index = index_today[event];
|
|
mEv_event_today_c* ev_today = &event_today[index];
|
|
|
|
if (index == 0xFF) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ((ev_today->status & mEv_STATUS_STOP)) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (ev_today->active_hours != 0) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern void mEv_set_status(int event, s16 status) {
|
|
u8 index = index_today[event];
|
|
mEv_event_today_c* ev_today = &event_today[index];
|
|
|
|
if (index != 0xFF) {
|
|
if (status == mEv_STATUS_ERROR) {
|
|
ev_today->status = 0;
|
|
}
|
|
|
|
status_edge |= status;
|
|
ev_today->status |= status;
|
|
}
|
|
}
|
|
|
|
static int set_active(int event) {
|
|
u8 index = index_today[event];
|
|
mEv_event_today_c* ev_today = &event_today[index];
|
|
int res = FALSE;
|
|
|
|
if (index != 0xFF) {
|
|
if ((ev_today->status & mEv_STATUS_ACTIVE) == 0) {
|
|
res = TRUE; // status updated
|
|
}
|
|
|
|
status_edge |= mEv_STATUS_ACTIVE;
|
|
ev_today->status |= mEv_STATUS_ACTIVE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
extern void mEv_clear_status(int event, s16 status) {
|
|
u8 index = index_today[event];
|
|
mEv_event_today_c* ev_today = &event_today[index];
|
|
|
|
if (index != 0xFF) {
|
|
ev_today->status &= ~status;
|
|
}
|
|
}
|
|
|
|
static int clear_active(int event) {
|
|
u8 index = index_today[event];
|
|
mEv_event_today_c* ev_today = &event_today[index];
|
|
int res = FALSE;
|
|
|
|
if (index != 0xFF) {
|
|
if ((ev_today->status & mEv_STATUS_ACTIVE) != 0) {
|
|
res = TRUE; // status updated
|
|
}
|
|
|
|
ev_today->status &= ~mEv_STATUS_ACTIVE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
extern int mEv_check_status(int event, s16 status) {
|
|
u8 index = index_today[event];
|
|
mEv_event_today_c* ev_today = &event_today[index];
|
|
|
|
if (index == 0xFF) {
|
|
return FALSE;
|
|
}
|
|
|
|
/* Default to 'false' if the event is in an error state */
|
|
if (status != mEv_STATUS_ERROR && (ev_today->status & mEv_STATUS_ERROR)) {
|
|
return FALSE;
|
|
}
|
|
|
|
return (ev_today->status & status) != 0;
|
|
}
|
|
|
|
extern int mEv_check_status_edge(s16 status) {
|
|
/* @BUG - developers almost certainly meant to use & here instead of | */
|
|
#ifndef BUGFIXES
|
|
if ((status_edge | status) != 0) {
|
|
#else
|
|
if ((status_edge & status) != 0) {
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern void mEv_set_keep(int event) {
|
|
int flags = Common_Get(event_keep_flags[event >> 5]);
|
|
flags |= (1 << (event & 0x1F));
|
|
Common_Set(event_keep_flags[event >> 5], flags);
|
|
}
|
|
|
|
extern void mEv_clear_keep(int event) {
|
|
int flags = Common_Get(event_keep_flags[event >> 5]);
|
|
flags &= ~(1 << (event & 0x1F));
|
|
Common_Set(event_keep_flags[event >> 5], flags);
|
|
}
|
|
|
|
extern int mEv_check_keep(int event) {
|
|
if ((Common_Get(event_keep_flags[event >> 5]) & (1 << (event & 0x1F)))) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern u8* mEv_reserve_save_area(int type, u8 id) {
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
int index = index_today[type];
|
|
mEv_event_today_c* ev_today = &event_today[index];
|
|
mEv_save_common_data_c* ev_save_common = Save_GetPointer(event_save_common);
|
|
int i;
|
|
int free_slot_idx = -1;
|
|
u8* data;
|
|
u8* ret;
|
|
int exist_slot = -1;
|
|
|
|
for (i = 0; i < mEv_AREA_NUM; i++) {
|
|
if (((1 << i) & ev_save_common->area_use_bitfield) == 0) {
|
|
free_slot_idx = i;
|
|
continue;
|
|
}
|
|
else if (id != mEv_EVENT_NUM && ev_save_common->area[i].info.id == mEv_EVENT_NUM) {
|
|
exist_slot = i;
|
|
}
|
|
|
|
if (type == ev_save_common->area[i].info.type && id == ev_save_common->area[i].info.id) {
|
|
free_slot_idx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (free_slot_idx == -1 && exist_slot != -1) {
|
|
free_slot_idx = exist_slot;
|
|
}
|
|
|
|
if (free_slot_idx != -1) {
|
|
mEv_area_c* const area = &ev_save_common->area[free_slot_idx];
|
|
mEv_info_c* const info = &area->info;
|
|
ev_save_common->area_use_bitfield |= (1 << free_slot_idx);
|
|
ev_save_common->area[free_slot_idx].info.type = type;
|
|
ev_save_common->area[free_slot_idx].info.id = id;
|
|
|
|
// issue seems to stem from ev_today->begin_date.month being used twice which promotes it to r11?
|
|
if ((u16)ev_today->begin_date.month > (u32)ev_today->end_date.month && (u16)ev_today->begin_date.month > (u32)rtc_time->month) {
|
|
ev_save_common->area[free_slot_idx].info.year = rtc_time->year - 1;
|
|
}
|
|
else {
|
|
ev_save_common->area[free_slot_idx].info.year = rtc_time->year;
|
|
}
|
|
|
|
data = (u8*)ev_save_common->area[free_slot_idx].data;
|
|
ev_save_common->area[free_slot_idx].info.year = rtc_time->year; // ????
|
|
ev_save_common->area[free_slot_idx].info.start_date.month = ev_today->begin_date.month;
|
|
ev_save_common->area[free_slot_idx].info.start_date.day = ev_today->begin_date.day;
|
|
ev_save_common->area[free_slot_idx].info.end_date.month = ev_today->end_date.month;
|
|
ev_save_common->area[free_slot_idx].info.end_date.day = ev_today->end_date.day;
|
|
memset(data, 0, sizeof(ev_save_common->area[free_slot_idx].data));
|
|
ret = data;
|
|
}
|
|
else {
|
|
ret = NULL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
extern u8* mEv_get_save_area(int type, u8 id) {
|
|
mEv_save_common_data_c* ev_save_common = Save_GetPointer(event_save_common);
|
|
int i;
|
|
|
|
for (i = 0; i < mEv_AREA_NUM; i++) {
|
|
if (((1 << i) & ev_save_common->area_use_bitfield) != 0) {
|
|
if (type == ev_save_common->area[i].info.type && id == ev_save_common->area[i].info.id) {
|
|
return (u8*)ev_save_common->area[i].data;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
extern int mEv_clear_save_area(int type, u8 id) {
|
|
mEv_save_common_data_c* ev_save_common = Save_GetPointer(event_save_common);
|
|
int i;
|
|
|
|
for (i = 0; i < mEv_AREA_NUM; i++) {
|
|
if (((1 << i) & ev_save_common->area_use_bitfield) != 0) {
|
|
if (type == ev_save_common->area[i].info.type && id == ev_save_common->area[i].info.id) {
|
|
ev_save_common->area_use_bitfield &= ~(1 << i);
|
|
return sizeof(ev_save_common->area[i].data);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int update_save_area() {
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
mEv_save_common_data_c* ev_save_common = Save_GetPointer(event_save_common);
|
|
int i;
|
|
int num_updated = 0;
|
|
u16 today_date;
|
|
u16 year;
|
|
u16 begin_date;
|
|
u16 end_date;
|
|
|
|
mEv_area_c* area;
|
|
|
|
for (i = 0; i < mEv_AREA_NUM; i++) {
|
|
area = &ev_save_common->area[i];
|
|
if (((1 << i) & ev_save_common->area_use_bitfield) != 0) {
|
|
if (area->info.start_date.month > area->info.end_date.month &&
|
|
area->info.start_date.month > rtc_time->month) {
|
|
year = rtc_time->year - 1;
|
|
} else {
|
|
year = rtc_time->year;
|
|
}
|
|
|
|
today_date = (rtc_time->month << 8) | rtc_time->day;
|
|
begin_date = (area->info.start_date.month << 8) | area->info.start_date.day;
|
|
end_date = (area->info.end_date.month << 8) | area->info.end_date.day;
|
|
|
|
if ((mEv_check_status(area->info.type, mEv_STATUS_ACTIVE) == FALSE &&
|
|
mEv_check_status(area->info.type, mEv_STATUS_RUN) == FALSE &&
|
|
mEv_ArbeitPlayer(Common_Get(player_no)) == FALSE) ||
|
|
check_date_range(today_date, begin_date, end_date) == FALSE || year != area->info.year) {
|
|
ev_save_common->area_use_bitfield &= ~(1 << i);
|
|
num_updated++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return num_updated;
|
|
}
|
|
|
|
extern u8* mEv_reserve_common_area(int type, u8 id) {
|
|
mEv_common_data_c* ev_common = Common_GetPointer(event_common);
|
|
int i;
|
|
int exist_slot = -1;
|
|
u8* data;
|
|
u8* res;
|
|
|
|
for (i = 0; i < mEv_AREA_NUM; i++) {
|
|
if (((1 << i) & ev_common->area_use_bitfield) == 0) {
|
|
exist_slot = i;
|
|
}
|
|
else if (type == ev_common->area[i].info.type && id == ev_common->area[i].info.id) {
|
|
exist_slot = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (exist_slot != -1) {
|
|
ev_common->area_use_bitfield |= (1 << exist_slot);
|
|
data = (u8*)ev_common->area[exist_slot].data;
|
|
ev_common->area[exist_slot].info.type = type;
|
|
ev_common->area[exist_slot].info.id = id;
|
|
memset(data, 0, sizeof(ev_common->area[exist_slot].data));
|
|
res = data;
|
|
}
|
|
else {
|
|
res = NULL;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
extern u8* mEv_get_common_area(int type, u8 id) {
|
|
mEv_common_data_c* ev_common = Common_GetPointer(event_common);
|
|
int i;
|
|
|
|
for (i = 0; i < mEv_AREA_NUM; i++) {
|
|
if (((1 << i) & ev_common->area_use_bitfield) != 0) {
|
|
if (type == ev_common->area[i].info.type && id == ev_common->area[i].info.id) {
|
|
return (u8*)ev_common->area[i].data;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
extern int mEv_clear_common_area(int type, u8 id) {
|
|
mEv_common_data_c* ev_common = Common_GetPointer(event_common);
|
|
int i;
|
|
|
|
for (i = 0; i < mEv_AREA_NUM; i++) {
|
|
if (((1 << i) & ev_common->area_use_bitfield) != 0) {
|
|
if (type == ev_common->area[i].info.type && id == ev_common->area[i].info.id) {
|
|
ev_common->area_use_bitfield &= ~(1 << i);
|
|
return sizeof(ev_common->area[i].data);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
extern mEv_place_data_c* mEv_reserve_common_place(int type, u8 id) {
|
|
mEv_common_data_c* ev_common = Common_GetPointer(event_common);
|
|
int i;
|
|
int exist_slot = -1;
|
|
mEv_place_data_c* data;
|
|
mEv_place_data_c* res;
|
|
|
|
for (i = 0; i < mEv_PLACE_NUM; i++) {
|
|
if (((1 << i) & ev_common->place_use_bitfield) == 0) {
|
|
exist_slot = i;
|
|
}
|
|
else if (type == ev_common->place[i].info.type && id == ev_common->place[i].info.id) {
|
|
exist_slot = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (exist_slot != -1) {
|
|
ev_common->place_use_bitfield |= (1 << exist_slot);
|
|
data = &ev_common->place[exist_slot].data;
|
|
ev_common->place[exist_slot].info.type = type;
|
|
ev_common->place[exist_slot].info.id = id;
|
|
memset(data, 0, sizeof(ev_common->place[exist_slot].data));
|
|
res = data;
|
|
}
|
|
else {
|
|
res = NULL;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
extern mEv_place_data_c* mEv_get_common_place(int type, u8 id) {
|
|
mEv_common_data_c* ev_common = Common_GetPointer(event_common);
|
|
int i;
|
|
|
|
for (i = 0; i < mEv_PLACE_NUM; i++) {
|
|
if (((1 << i) & ev_common->place_use_bitfield) != 0) {
|
|
if (type == ev_common->place[i].info.type && id == ev_common->place[i].info.id) {
|
|
return &ev_common->place[i].data;
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
extern int mEv_clear_common_place(int type, u8 id) {
|
|
mEv_common_data_c* ev_common = Common_GetPointer(event_common);
|
|
int i;
|
|
|
|
for (i = 0; i < mEv_PLACE_NUM; i++) {
|
|
if (((1 << i) & ev_common->place_use_bitfield) != 0) {
|
|
if (type == ev_common->place[i].info.type && id == ev_common->place[i].info.id) {
|
|
ev_common->place_use_bitfield &= ~(1 << i);
|
|
return sizeof(ev_common->place[i].data);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
extern int mEv_use_block_by_other_event(int type, BlockOrUnit_c* block) {
|
|
mEv_common_data_c* ev_common = Common_GetPointer(event_common);
|
|
int i;
|
|
|
|
for (i = 0; i < mEv_PLACE_NUM; i++) {
|
|
if (((1 << i) & ev_common->place_use_bitfield) != 0) {
|
|
if (
|
|
ev_common->place[i].data.block.x == block->x &&
|
|
ev_common->place[i].data.block.z == block->z &&
|
|
ev_common->place[i].info.type != type
|
|
) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern void mEv_erase_FG_all_in_common_place() {
|
|
mEv_common_data_c* ev_common = Common_GetPointer(event_common);
|
|
int i;
|
|
|
|
for (i = 0; i < mEv_PLACE_NUM; i++) {
|
|
if (((1 << i) & ev_common->place_use_bitfield) != 0) {
|
|
mEv_place_data_c* place_data = &ev_common->place[i].data;
|
|
|
|
if (ITEM_NAME_GET_TYPE(place_data->actor_name) == NAME_TYPE_STRUCT) {
|
|
mFI_SetFGStructure_common(
|
|
place_data->actor_name,
|
|
place_data->block.x,
|
|
place_data->block.z,
|
|
place_data->unit.x,
|
|
place_data->unit.z,
|
|
mFI_SET_STRUCTURE_REMOVE
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int n_rumor = 0;
|
|
static int rumor_table[40];
|
|
|
|
extern void mEv_clear_rumor() {
|
|
n_rumor = 0;
|
|
}
|
|
|
|
extern int mEv_spread_rumor(int type) {
|
|
rumor_table[n_rumor++] = type;
|
|
return n_rumor;
|
|
}
|
|
|
|
extern int mEv_get_rumor() {
|
|
if (n_rumor != 0) {
|
|
return rumor_table[gamePT->frame_counter % n_rumor] | mEv_SET(mEv_TYPE3_EVENT, 0);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
extern void mEv_actor_dying_message(int type, ACTOR* actor) {
|
|
xyz_t pos = actor->world.position;
|
|
mEv_common_data_c* ev_common = Common_GetPointer(event_common);
|
|
mActor_name_t actor_name = actor->npc_id;
|
|
int i;
|
|
|
|
for (i = 0; i < mEv_PLACE_NUM; i++) {
|
|
if (((1 << i) & ev_common->place_use_bitfield) != 0) {
|
|
mEv_place_data_c* place_data = &ev_common->place[i].data;
|
|
|
|
if (
|
|
ev_common->place[i].info.type == type &&
|
|
place_data->actor_name == actor_name
|
|
) {
|
|
/* Check if the actor world position should be transferred to event data */
|
|
if (place_data->flag & 1) {
|
|
mFI_Wpos2BlockNum(&place_data->block.x, &place_data->block.z, pos);
|
|
mFI_Wpos2UtNum_inBlock(&place_data->unit.x, &place_data->unit.z, pos);
|
|
}
|
|
|
|
funeral = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
mEv_set_status(type, mEv_STATUS_STOP);
|
|
dead = 3;
|
|
}
|
|
|
|
extern int mEv_LiveSonchoPresent() {
|
|
if (Common_Get(demo_profiles[1]) == mAc_PROFILE_PRESENT_DEMO) {
|
|
return TRUE;
|
|
}
|
|
|
|
if (Common_Get(clip).demo_clip2 != NULL && Common_Get(clip).demo_clip2->type == mDemo_CLIP_TYPE_PRESENT_DEMO) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern int mEv_LivePlayer(u32 player_no) {
|
|
if (mEv_CheckTitleDemo() != 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (Common_Get(reset_flag) != 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (player_no < mPr_FOREIGNER) {
|
|
if (
|
|
mEv_CheckEvent(mEv_SAVED_GATEWAY_PLR0 + player_no) == TRUE ||
|
|
mEv_CheckEvent(mEv_SAVED_FIRSTINTRO_PLR0 + player_no) == TRUE
|
|
) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if (player_no < mPr_PLAYER_NUM) {
|
|
if (mEv_CheckEvent(mEv_SAVED_GATEWAY_PLR0 + player_no) == TRUE) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
else {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
extern int mEv_ArbeitPlayer_kari(u32 player_no) {
|
|
if (player_no < mPr_FOREIGNER && mEv_CheckEvent(mEv_SAVED_FIRSTJOB_PLR0 + player_no) == TRUE) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern int mEv_ArbeitPlayer(u32 player_no) {
|
|
if (
|
|
player_no < mPr_FOREIGNER &&
|
|
(mEv_CheckEvent(mEv_SAVED_FIRSTJOB_PLR0 + player_no) == TRUE ||
|
|
mEv_CheckEvent(mEv_SAVED_HRAWAIT_PLR0 + player_no) == TRUE)
|
|
) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern void mEv_make_new_special_event() {
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
mEv_schedule_c sched;
|
|
mEv_schedule_date_u today_date;
|
|
mEv_schedule_c* sched_p = &sched;
|
|
|
|
today_date.d.month = rtc_time->month;
|
|
today_date.d.day = rtc_time->day;
|
|
today_date.d._2 = 0;
|
|
today_date.d.hour = rtc_time->hour;
|
|
|
|
if (init_special_event(TRUE)) {
|
|
int i;
|
|
|
|
Save_Get(event_save_common).special_event.flags = 1;
|
|
for (i = 0; i < ARRAY_COUNT(event_schedule_data); i++) {
|
|
memcpy(sched_p, &event_schedule_data[i], sizeof(mEv_schedule_c));
|
|
|
|
if (update_special_event(sched_p)) {
|
|
sched.date[0].raw = decode_date(sched.date[0].raw);
|
|
sched.date[1].raw = decode_date(sched.date[1].raw);
|
|
|
|
if (check_date_range(today_date.md, sched.date[0].md, sched.date[1].md)) {
|
|
add_event_today(today_date.md, sched_p);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extern int mEv_GetMonth(Event_c* event) {
|
|
return event->month;
|
|
}
|
|
|
|
extern int mEv_GetDay(Event_c* event) {
|
|
return event->day;
|
|
}
|
|
|
|
extern int mEv_GetHour(Event_c* event) {
|
|
return event->hour;
|
|
}
|
|
|
|
extern void mEv_debug_print4f(gfxprint_t* gfxprint) {
|
|
//int x = 0;
|
|
int i;
|
|
int event_idx = 0;
|
|
|
|
for (i = 0; i < mEv_TODAY_EVENT_NUM; i++) {
|
|
if (event_today[i].type != -1 && mEv_check_status(event_today[i].type, mEv_STATUS_ACTIVE)) {
|
|
gfxprint_color(gfxprint, 245, 200, 170, 255);
|
|
gfxprint_locate8x8(gfxprint, 3 + event_idx * 3, 5);
|
|
gfxprint_printf(gfxprint, "%3d", event_today[i].type);
|
|
event_idx++;
|
|
//x += 3;
|
|
|
|
if (event_idx >= 9) {
|
|
if (mEv_check_status(event_today[i].type, mEv_STATUS_ERROR) == FALSE) {
|
|
gfxprint_color(gfxprint, 245, 150, 120, 255);
|
|
}
|
|
else if (mEv_check_status(event_today[i].type, mEv_STATUS_RUN)) {
|
|
gfxprint_color(gfxprint, 180, 150, 160, 255);
|
|
}
|
|
else {
|
|
gfxprint_color(gfxprint, 140, 120, 120, 255);
|
|
}
|
|
|
|
gfxprint_locate8x8(gfxprint, 9 + event_idx * 3, 5);
|
|
gfxprint_printf(gfxprint, "+");
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void mEv_sp_debug_print4f(gfxprint_t* gfxprint) {
|
|
gfxprint_color(gfxprint, 245, 200, 170, 255);
|
|
gfxprint_locate8x8(gfxprint, 3, 11);
|
|
gfxprint_printf(
|
|
gfxprint,
|
|
"%3d %02d-%02d-%02d",
|
|
Save_Get(event_save_common).special_event.type,
|
|
Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL0] & 0xFF, // event rtc (current) day
|
|
Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL1] & 0xFF, // event begin day
|
|
Save_Get(event_save_common).dates[mEv_SAVE_DATE_SPECIAL2] & 0xFF // event end day
|
|
);
|
|
|
|
gfxprint_locate8x8(gfxprint, 30, 11);
|
|
gfxprint_printf(
|
|
gfxprint,
|
|
"%c%c%c%c%c%c%c%c",
|
|
mEv_CheckTitleDemo() ? 'T' : '.',
|
|
mEv_CheckFirstIntro() ? 'F' : '.',
|
|
mEv_CheckGateway() ? 'G' : '.',
|
|
mEv_CheckRealArbeit() ? 'R' : '.',
|
|
mEv_CheckArbeit() ? 'A' : '.',
|
|
mDemo_CheckDemo() ? 'D' : '.',
|
|
!mEv_PlayerOK() ? 'P' : '.',
|
|
!mEv_LivePlayer(Common_Get(player_no)) ? 'L' : '.'
|
|
);
|
|
}
|
|
|
|
extern int mEv_change(Event_c* event) {
|
|
return event->changed_num;
|
|
}
|
|
|
|
extern int mEv_get_special_event_state() {
|
|
int special_events[] = {
|
|
mEv_EVENT_SHOP_SALE,
|
|
mEv_EVENT_DESIGNER,
|
|
mEv_EVENT_BROKER_SALE,
|
|
mEv_EVENT_ARTIST,
|
|
mEv_EVENT_CARPET_PEDDLER,
|
|
mEv_EVENT_GYPSY
|
|
};
|
|
|
|
int active = FALSE;
|
|
int res = mEv_SPECIAL_STATE_UNSCHEDULED;
|
|
mEv_ymdh_u event_date_start;
|
|
mEv_ymdh_u today_date;
|
|
mEv_ymdh_u event_date;
|
|
mEv_ymdh_u today_date_start;
|
|
int event_type;
|
|
|
|
if (Save_Get(event_save_data).special.type <= mEv_SPNPC_END) {
|
|
event_type = special_events[Save_Get(event_save_data).special.type];
|
|
}
|
|
else {
|
|
return FALSE;
|
|
}
|
|
|
|
today_date.year = 0;
|
|
today_date.month = Common_Get(time.rtc_time.month);
|
|
today_date.day = Common_Get(time.rtc_time.day);
|
|
today_date.hour = Common_Get(time.rtc_time.hour);
|
|
|
|
event_date.year = 0;
|
|
event_date.month = Save_Get(event_save_data).special.scheduled.month;
|
|
event_date.day = Save_Get(event_save_data).special.scheduled.day;
|
|
event_date.hour = Save_Get(event_save_data).special.scheduled.hour;
|
|
|
|
event_date_start.raw = event_date.raw;
|
|
today_date_start.raw = today_date.raw;
|
|
|
|
today_date_start.hour = 0;
|
|
event_date_start.hour = 0;
|
|
|
|
if (event_type == mEv_EVENT_SHOP_SALE) {
|
|
if (event_date.raw == today_date.raw) {
|
|
active = TRUE;
|
|
}
|
|
}
|
|
else if (mEv_check_status(event_type, mEv_STATUS_ACTIVE)) {
|
|
active = TRUE;
|
|
}
|
|
|
|
if (active) {
|
|
res = mEv_SPECIAL_STATE_ACTIVE;
|
|
}
|
|
else if (check_ymdh_range(today_date.raw, event_date_start.raw, event_date.raw)) {
|
|
res = mEv_SPECIAL_STATE_SCHEDULED_TODAY;
|
|
}
|
|
else if (Save_Get(event_save_data).special.type != 0xFFFFFFFF && event_date_start.raw > today_date_start.raw) {
|
|
res = mEv_SPECIAL_STATE_SCHEDULED_LATER;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
extern int mEv_snowman_born_check() {
|
|
mEv_ymdh_u snowman_date;
|
|
mEv_ymdh_u today_date;
|
|
mEv_ymdh_u snowman_date_end;
|
|
|
|
today_date.year = Common_Get(time.rtc_time).year % 100;
|
|
today_date.month = Common_Get(time.rtc_time).month;
|
|
today_date.day = Common_Get(time.rtc_time).day;
|
|
today_date.hour = Common_Get(time.rtc_time).hour;
|
|
|
|
snowman_date.year = Save_Get(snowman_year);
|
|
snowman_date.month = Save_Get(snowman_month);
|
|
snowman_date.day = Save_Get(snowman_day);
|
|
snowman_date.hour = Save_Get(snowman_hour);
|
|
|
|
snowman_date_end.raw = snowman_date.raw;
|
|
snowman_date_end.hour = 5;
|
|
|
|
if (snowman_date.hour >= 6) {
|
|
mEv_MonthDay_u snowman_monthday;
|
|
mEv_MonthDay_u next_monthday;
|
|
|
|
snowman_monthday.month = snowman_date.month;
|
|
snowman_monthday.day = snowman_date.day;
|
|
next_monthday.raw = after_n_day(snowman_monthday.raw, 1);
|
|
|
|
if (next_monthday.raw == mEv_MonthDay(lbRTC_JANUARY, 1)) {
|
|
snowman_date_end.year = (snowman_date_end.year + 1) % 100;
|
|
}
|
|
|
|
snowman_date_end.month = next_monthday.month;
|
|
snowman_date_end.day = next_monthday.day;
|
|
}
|
|
|
|
if (check_ymdh_range(today_date.raw, snowman_date.raw, snowman_date_end.raw)) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
extern int mEv_someone_died() {
|
|
return dead;
|
|
}
|
|
|
|
extern void mEv_special_event_soldout(int type) {
|
|
GAME_PLAY* play = (GAME_PLAY*)gamePT;
|
|
mEv_event_today_c* ev_today;
|
|
int i;
|
|
|
|
for (i = 0; i < mEv_TODAY_EVENT_NUM; i++) {
|
|
ev_today = &event_today[i];
|
|
|
|
if (
|
|
ev_today->type != -1 &&
|
|
index_today[ev_today->type] != 0xFF &&
|
|
mEv_check_status(ev_today->type, mEv_STATUS_ERROR) == FALSE &&
|
|
ev_today->type == type
|
|
) {
|
|
if (clear_active(ev_today->type)) {
|
|
play->event.changed_num++;
|
|
}
|
|
|
|
ev_today->active_hours = mEv_EVENT_HOUR_CLEAR_EVENT;
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void mEv_toland_clear_common() {
|
|
int* keep_flags = Common_Get(event_keep_flags);
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(Common_Get(event_keep_flags)); i++) {
|
|
keep_flags[i] = 0;
|
|
}
|
|
|
|
mem_clear(Common_GetPointer(event_common), sizeof(Common_Get(event_common)), 0);
|
|
mem_clear(Common_GetPointer(special_event_common), sizeof(Common_Get(special_event_common)), 0);
|
|
}
|
|
|
|
extern void mGH_animal_return_init() {
|
|
mem_clear(Save_GetPointer(return_animal), sizeof(Save_Get(return_animal)), 0);
|
|
Save_Get(return_animal).npc_id = EMPTY_NO; // ??
|
|
}
|
|
|
|
extern int mGH_check_birth2() {
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
Anmret_c* return_animal = Save_GetPointer(return_animal);
|
|
lbRTC_time_c time;
|
|
|
|
if (return_animal->npc_id == EMPTY_NO) {
|
|
return FALSE;
|
|
}
|
|
|
|
/* Check that it's been less than 1 week since go home event was scheduled */
|
|
lbRTC_TimeCopy(&time, &return_animal->renew_time);
|
|
lbRTC_Add_DD(&time, lbRTC_WEEK);
|
|
|
|
if (
|
|
lbRTC_IsEqualDate(
|
|
time.year, time.month, time.day,
|
|
rtc_time->year, rtc_time->month, rtc_time->day
|
|
) == lbRTC_LESS
|
|
) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern int mGH_check_birth() {
|
|
if ((Save_Get(return_animal).talk_bit & (1 << Common_Get(player_no))) != 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
return mGH_check_birth2();
|
|
}
|
|
|
|
extern void mGH_check_delete() {
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
Anmret_c* return_animal = Save_GetPointer(return_animal);
|
|
Private_c* priv = Save_Get(private);
|
|
|
|
if (return_animal->npc_id != EMPTY_NO) {
|
|
if (Save_Get(npc_force_go_home) == TRUE) {
|
|
mGH_animal_return_init();
|
|
}
|
|
else {
|
|
lbRTC_time_c time;
|
|
|
|
lbRTC_TimeCopy(&time, &return_animal->renew_time);
|
|
/* Devs did this to fix a 'bug' with lbRTC_Add_DD which only allows going at most one month in the future */
|
|
lbRTC_Add_DD(&time, 20);
|
|
lbRTC_Add_DD(&time, 20);
|
|
lbRTC_Add_DD(&time, 20);
|
|
|
|
if (
|
|
lbRTC_IsEqualDate(
|
|
time.year, time.month, time.day,
|
|
rtc_time->year, rtc_time->month, rtc_time->day
|
|
) != lbRTC_OVER
|
|
) {
|
|
mGH_animal_return_init();
|
|
}
|
|
else {
|
|
int i;
|
|
|
|
if (mNpc_SearchAnimalinfo(Save_Get(animals), return_animal->npc_id, ANIMAL_NUM_MAX) != -1) {
|
|
mGH_animal_return_init(); // don't allow this animal to visit if a "version" of it lives in town
|
|
}
|
|
|
|
for (i = 0; i < PLAYER_NUM; i++) {
|
|
if (mPr_NullCheckPersonalID(&priv->player_ID) == FALSE && (return_animal->talk_bit & (1 << i)) == 0) {
|
|
return;
|
|
}
|
|
|
|
priv++;
|
|
}
|
|
|
|
mGH_animal_return_init();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void mMC_mask_cat_init() {
|
|
MaskCat_c* mask_cat = Save_GetPointer(mask_cat);
|
|
u8 cloth_no = mask_cat->cloth_no;
|
|
|
|
mem_clear(mask_cat, sizeof(Save_Get(mask_cat)), 0);
|
|
mPr_ClearPersonalID(&mask_cat->design.creator_pid);
|
|
Save_Get(mask_cat).cloth_no = cloth_no;
|
|
}
|
|
|
|
extern int mMC_check_birth() {
|
|
if (Save_Get(mask_cat).design.creator_pid.player_id == 0xFFFF) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (Save_Get(mask_cat).talk_idx >= mMC_TALK_IDX_MAX) {
|
|
/* Talked more than the maximum amount of times allowed */
|
|
mMC_mask_cat_init();
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern int mMC_check_birth_day() {
|
|
switch (Common_Get(time.rtc_time.weekday)) {
|
|
case lbRTC_SUNDAY:
|
|
case lbRTC_MONDAY:
|
|
case lbRTC_WEDNESDAY:
|
|
case lbRTC_FRIDAY:
|
|
return FALSE;
|
|
|
|
default:
|
|
return mMC_check_birth();
|
|
}
|
|
}
|
|
|
|
extern void mMC_check_delete() {
|
|
MaskCat_c* mask_cat = Save_GetPointer(mask_cat);
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
|
|
if (mask_cat->design.creator_pid.player_id != 0xFFFF) {
|
|
lbRTC_time_c max_time;
|
|
lbRTC_time_c min_time;
|
|
|
|
lbRTC_TimeCopy(&max_time, &mask_cat->time);
|
|
lbRTC_TimeCopy(&min_time, &mask_cat->time);
|
|
|
|
lbRTC_Add_DD(&max_time, lbRTC_WEEK);
|
|
lbRTC_Sub_DD(&min_time, lbRTC_WEEK);
|
|
|
|
if (
|
|
mask_cat->talk_idx >= mMC_TALK_IDX_MAX ||
|
|
lbRTC_IsEqualDate(
|
|
max_time.year, max_time.month, max_time.day,
|
|
rtc_time->year, rtc_time->month, rtc_time->day
|
|
) != lbRTC_OVER ||
|
|
lbRTC_IsEqualDate(
|
|
min_time.year, min_time.month, min_time.day,
|
|
rtc_time->year, rtc_time->month, rtc_time->day
|
|
) != lbRTC_LESS
|
|
) {
|
|
mMC_mask_cat_init();
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void mMC_set_time() {
|
|
MaskCat_c* mask_cat = Save_GetPointer(mask_cat);
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
|
|
lbRTC_TimeCopy(&mask_cat->time, rtc_time);
|
|
}
|