mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-06-09 03:59:38 -04:00
2762 lines
71 KiB
C
2762 lines
71 KiB
C
#include "m_shop.h"
|
|
|
|
#include "game.h"
|
|
#include "m_cockroach.h"
|
|
#include "m_collision_bg.h"
|
|
#include "m_common_data.h"
|
|
#include "m_event.h"
|
|
#include "m_handbill.h"
|
|
#include "m_house.h"
|
|
#include "m_item_name.h"
|
|
#include "m_name_table.h"
|
|
#include "m_room_type.h"
|
|
|
|
extern mActor_name_t* mSP_ftr_list[];
|
|
extern mActor_name_t* mSP_binsen_list[];
|
|
extern mActor_name_t* mSP_cloth_list[];
|
|
extern mActor_name_t* mSP_carpet_list[];
|
|
extern mActor_name_t* mSP_wall_list[];
|
|
|
|
static mActor_name_t diary_listA[6] = {
|
|
ITM_DIARY01, ITM_DIARY04, ITM_DIARY07, ITM_DIARY10, ITM_DIARY13, EMPTY_NO
|
|
};
|
|
|
|
static mActor_name_t diary_listB[6] = {
|
|
ITM_DIARY02, ITM_DIARY05, ITM_DIARY08, ITM_DIARY11, ITM_DIARY14, EMPTY_NO
|
|
};
|
|
|
|
static mActor_name_t diary_listC[7] = {
|
|
ITM_DIARY03, ITM_DIARY06, ITM_DIARY09, ITM_DIARY12, ITM_DIARY15, ITM_DIARY00, EMPTY_NO
|
|
};
|
|
|
|
static mActor_name_t* mSP_diary_list[mSP_LIST_NUM] = {
|
|
diary_listA,
|
|
diary_listB,
|
|
diary_listC,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
static mActor_name_t** mSP_goods_seg_inf[mSP_KIND_EXTENDED_MAX] = {
|
|
mSP_ftr_list,
|
|
mSP_binsen_list,
|
|
mSP_cloth_list,
|
|
mSP_carpet_list,
|
|
mSP_wall_list,
|
|
mSP_diary_list
|
|
};
|
|
|
|
static void mSP_InitItemTable(mActor_name_t* item_table, int count) {
|
|
int i;
|
|
|
|
if (item_table == NULL) {
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < count; i++) {
|
|
*item_table++ = EMPTY_NO;
|
|
}
|
|
}
|
|
|
|
static mActor_name_t* mSP_SelectListFromPriority(mActor_name_t** lists, u8* priorities, int list_type) {
|
|
mActor_name_t* list = NULL;
|
|
|
|
switch (list_type) {
|
|
case mSP_LISTTYPE_EVENT:
|
|
list = lists[mSP_LIST_EVENT];
|
|
break;
|
|
case mSP_LISTTYPE_TRAIN:
|
|
list = lists[mSP_LIST_TRAIN];
|
|
break;
|
|
case mSP_LISTTYPE_LOTTERY:
|
|
list = lists[mSP_LIST_LOTTERY];
|
|
break;
|
|
case mSP_LISTTYPE_HALLOWEEN:
|
|
list = lists[mSP_LIST_HALLOWEEN];
|
|
break;
|
|
case mSP_LISTTYPE_HALLOWEEN2:
|
|
list = lists[mSP_LIST_HALLOWEEN2];
|
|
break;
|
|
case mSP_LISTTYPE_PRESENT:
|
|
list = lists[mSP_LIST_PRESENT];
|
|
break;
|
|
case mSP_LISTTYPE_CHRISTMAS:
|
|
list = lists[mSP_LIST_CHRISTMAS];
|
|
break;
|
|
case mSP_LISTTYPE_SNOW:
|
|
list = lists[mSP_LIST_SNOW];
|
|
break;
|
|
case mSP_LISTTYPE_JONASON:
|
|
list = lists[mSP_LIST_JONASON];
|
|
break;
|
|
case mSP_LISTTYPE_POSTOFFICE:
|
|
list = lists[mSP_LIST_POSTOFFICE];
|
|
break;
|
|
case mSP_LISTTYPE_NINTENDO64:
|
|
list = lists[mSP_LIST_NINTENDO64];
|
|
break;
|
|
case mSP_LISTTYPE_SPECIALPRESENT:
|
|
list = lists[mSP_LIST_SPECIALPRESENT];
|
|
break;
|
|
case mSP_LISTTYPE_ISLAND:
|
|
list = lists[mSP_LIST_ISLAND];
|
|
break;
|
|
case mSP_LISTTYPE_ISLANDFAMICOM:
|
|
list = lists[mSP_LIST_ISLANDFAMICOM];
|
|
break;
|
|
case mSP_LISTTYPE_HOMEPAGE:
|
|
list = lists[mSP_LIST_HOMEPAGE];
|
|
break;
|
|
case mSP_LISTTYPE_EVENTPRESENTCHUMON:
|
|
list = lists[mSP_LIST_EVENTPRESENTCHUMON];
|
|
break;
|
|
case mSP_LISTTYPE_KAMAKURA:
|
|
list = lists[mSP_LIST_KAMAKURA];
|
|
break;
|
|
case mSP_LISTTYPE_HARVEST:
|
|
list = lists[mSP_LIST_HARVEST];
|
|
break;
|
|
case mSP_LISTTYPE_MARIO:
|
|
list = lists[mSP_LIST_MARIO];
|
|
break;
|
|
case mSP_LISTTYPE_TENT:
|
|
list = lists[mSP_LIST_TENT];
|
|
break;
|
|
|
|
case mSP_LISTTYPE_ABC:
|
|
default:
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 3; i++, priorities++) {
|
|
if (list_type == priorities[0]) {
|
|
switch (i) {
|
|
case mSP_LISTTYPE_COMMON:
|
|
list = lists[mSP_LIST_A];
|
|
break;
|
|
case mSP_LISTTYPE_UNCOMMON:
|
|
list = lists[mSP_LIST_B];
|
|
break;
|
|
case mSP_LISTTYPE_RARE:
|
|
list = lists[mSP_LIST_C];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (list == NULL) {
|
|
list = lists[mSP_LIST_A];
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
static void mSP_SetSeasonFTR_local_december(mActor_name_t* item_table, int count, mActor_name_t ftr0, mActor_name_t ftr1) {
|
|
if (count > 1) {
|
|
item_table[0] = ftr0;
|
|
item_table[1] = ftr1;
|
|
}
|
|
else if (fqrand() < 0.5f) {
|
|
item_table[0] = ftr0;
|
|
}
|
|
else {
|
|
item_table[0] = ftr1;
|
|
}
|
|
}
|
|
|
|
static void mSP_SetSeasonFTR(mActor_name_t* item_table, int count) {
|
|
lbRTC_time_c rtc_time = Common_Get(time.rtc_time);
|
|
lbRTC_month_t month = rtc_time.month;
|
|
lbRTC_day_t day = rtc_time.day;
|
|
|
|
if (count > 0 && month == lbRTC_DECEMBER) {
|
|
|
|
if (day <= 24) {
|
|
mSP_SetSeasonFTR_local_december(item_table, count, FTR_FESTIVE_TREE, FTR_BIG_FESTIVE_TREE);
|
|
}
|
|
else if (day >= 26) {
|
|
mSP_SetSeasonFTR_local_december(item_table, count, FTR_FESTIVE_CANDLE, FTR_FESTIVE_FLAG);
|
|
}
|
|
}
|
|
}
|
|
|
|
static mActor_name_t* mSP_GetItemList(mActor_name_t** lists, u8* priorities, int list_type) {
|
|
if (list_type == mSP_LISTTYPE_ABC) {
|
|
int abc_roll = RANDOM(100);
|
|
int goods_power = mPr_GetGoodsPower();
|
|
int rare_chance;
|
|
int uncommon_chance;
|
|
|
|
if (goods_power < 0) {
|
|
uncommon_chance = goods_power + 40; /* [10%, 39%] */
|
|
rare_chance = 5; /* always 5% chance */
|
|
/* common_chance = [85%, 66%] */
|
|
}
|
|
else {
|
|
rare_chance = goods_power + 5; /* [5%, 55%] */
|
|
uncommon_chance = rare_chance + 35; /* always 35% chance */
|
|
/* common_chance = [60%, 10%]*/
|
|
}
|
|
|
|
if (abc_roll < rare_chance) {
|
|
return mSP_SelectListFromPriority(lists, priorities, mSP_LISTTYPE_RARE);
|
|
}
|
|
else if (abc_roll < uncommon_chance) {
|
|
return mSP_SelectListFromPriority(lists, priorities, mSP_LISTTYPE_UNCOMMON);
|
|
}
|
|
else {
|
|
return mSP_SelectListFromPriority(lists, priorities, mSP_LISTTYPE_COMMON);
|
|
}
|
|
}
|
|
else {
|
|
return mSP_SelectListFromPriority(lists, priorities, list_type);
|
|
}
|
|
}
|
|
|
|
static int mSP_GoodsExistAlready(mActor_name_t* goods_table, int count, mActor_name_t item) {
|
|
int i;
|
|
|
|
if (goods_table != NULL) {
|
|
for (i = 0; i < count; i++) {
|
|
if (goods_table[i] == item) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern int mSP_CollectCheck(mActor_name_t item) {
|
|
mActor_name_t ftr_item = mRmTp_Item1ItemNo2FtrItemNo_AtPlayerRoom(item, FALSE);
|
|
u32* bitfield;
|
|
int idx;
|
|
|
|
bitfield = NULL;
|
|
|
|
switch (ITEM_NAME_GET_TYPE(ftr_item)) {
|
|
case NAME_TYPE_FTR0:
|
|
case NAME_TYPE_FTR1:
|
|
{
|
|
bitfield = Common_Get(now_private)->furniture_collected_bitfield;
|
|
idx = mRmTp_FtrItemNo2FtrIdx(ftr_item);
|
|
break;
|
|
}
|
|
|
|
case NAME_TYPE_ITEM1:
|
|
{
|
|
switch (ITEM_NAME_GET_CAT(ftr_item)) {
|
|
case ITEM1_CAT_PAPER:
|
|
{
|
|
bitfield = Common_Get(now_private)->paper_collected_bitfield;
|
|
idx = (ftr_item - ITM_PAPER_START) % PAPER_UNIQUE_NUM;
|
|
break;
|
|
}
|
|
|
|
case ITEM1_CAT_WALL:
|
|
{
|
|
bitfield = Common_Get(now_private)->wall_collected_bitfield;
|
|
idx = ftr_item - ITM_WALL_START;
|
|
break;
|
|
}
|
|
|
|
case ITEM1_CAT_CARPET:
|
|
{
|
|
bitfield = Common_Get(now_private)->carpet_collected_bitfield;
|
|
idx = ftr_item - ITM_CARPET_START;
|
|
break;
|
|
}
|
|
|
|
case ITEM1_CAT_MINIDISK:
|
|
{
|
|
bitfield = Common_Get(now_private)->music_collected_bitfield;
|
|
idx = (mActor_name_t)(ftr_item - ITM_MINIDISK_START);
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bitfield == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
return ((1 << (idx & 0x1F)) & bitfield[idx >> 5]) != 0;
|
|
}
|
|
|
|
static int mSP_CountElementInCommonList(mActor_name_t* list) {
|
|
int count = 0;
|
|
|
|
for (list; list[0] != EMPTY_NO; list++, count++) { }
|
|
|
|
return count;
|
|
}
|
|
|
|
static int mSP_CountElementInCommonList_collect(mActor_name_t* list, int* selected_idx, int uncollected_only) {
|
|
int count = 0;
|
|
int selected;
|
|
mActor_name_t* list_p;
|
|
|
|
if (uncollected_only == FALSE) {
|
|
count = mSP_CountElementInCommonList(list);
|
|
selected_idx[0] = RANDOM(count);
|
|
|
|
return count;
|
|
}
|
|
|
|
/* Count all uncollected items in the list */
|
|
for (list_p = list; list_p[0] != EMPTY_NO; list_p++) {
|
|
if (mSP_CollectCheck(list_p[0]) == FALSE) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
if (count == 0) {
|
|
selected_idx[0] = 0;
|
|
return 0;
|
|
}
|
|
|
|
selected = RANDOM(count);
|
|
selected_idx[0] = 0;
|
|
for (list_p = list; list_p[0] != EMPTY_NO && selected > 0; list_p++) {
|
|
if (mSP_CollectCheck(list_p[0]) == FALSE) {
|
|
selected--;
|
|
}
|
|
|
|
selected_idx[0]++;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
static int mSP_get_cloth_season() {
|
|
lbRTC_time_c rtc_time = Common_Get(time.rtc_time);
|
|
lbRTC_month_t month = rtc_time.month;
|
|
int res;
|
|
|
|
switch (month) {
|
|
case lbRTC_JANUARY:
|
|
res = mSP_CLOTH_SEASON_WINTER;
|
|
break;
|
|
|
|
case lbRTC_FEBRUARY:
|
|
{
|
|
if (rtc_time.day > 24) {
|
|
res = mSP_CLOTH_SEASON_SPRING;
|
|
}
|
|
else {
|
|
res = mSP_CLOTH_SEASON_WINTER;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case lbRTC_MARCH:
|
|
case lbRTC_APRIL:
|
|
res = mSP_CLOTH_SEASON_SPRING;
|
|
break;
|
|
|
|
case lbRTC_MAY:
|
|
{
|
|
if (rtc_time.day > 26) {
|
|
res = mSP_CLOTH_SEASON_SUMMER;
|
|
}
|
|
else {
|
|
res = mSP_CLOTH_SEASON_SPRING;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case lbRTC_JUNE:
|
|
case lbRTC_JULY:
|
|
res = mSP_CLOTH_SEASON_SUMMER;
|
|
break;
|
|
|
|
case lbRTC_AUGUST:
|
|
{
|
|
if (rtc_time.day > 26) {
|
|
res = mSP_CLOTH_SEASON_AUTUMN;
|
|
}
|
|
else {
|
|
res = mSP_CLOTH_SEASON_SUMMER;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case lbRTC_SEPTEMBER:
|
|
case lbRTC_OCTOBER:
|
|
res = mSP_CLOTH_SEASON_AUTUMN;
|
|
break;
|
|
|
|
case lbRTC_NOVEMBER:
|
|
{
|
|
if (rtc_time.day > 26) {
|
|
res = mSP_CLOTH_SEASON_WINTER;
|
|
}
|
|
else {
|
|
res = mSP_CLOTH_SEASON_AUTUMN;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case lbRTC_DECEMBER:
|
|
res = mSP_CLOTH_SEASON_WINTER;
|
|
break;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
extern u8 cloth_season_cnt[];
|
|
|
|
static int mSP_CountElementInClothList(int* selected) {
|
|
u8* count_p = cloth_season_cnt;
|
|
int cloth_season = mSP_get_cloth_season();
|
|
int cloth_count = count_p[mSP_CLOTH_SEASON_ANY] + count_p[cloth_season];
|
|
|
|
selected[0] = RANDOM(cloth_count); // random cloth selected
|
|
|
|
if (selected[0] >= cloth_season_cnt[mSP_CLOTH_SEASON_ANY]) {
|
|
int i;
|
|
|
|
/* seasonal cloths are sequential in the item lists, so add previous season counts to the selected index */
|
|
for (i = mSP_CLOTH_SEASON_SPRING; i < cloth_season; i++) {
|
|
selected[0] += count_p[i];
|
|
}
|
|
}
|
|
|
|
return cloth_count;
|
|
}
|
|
|
|
static int mSP_CountElementInClothList_collect(mActor_name_t* list, int* selected, int uncollected_only) {
|
|
u8* count_p = cloth_season_cnt;
|
|
|
|
if (uncollected_only == FALSE) {
|
|
return mSP_CountElementInClothList(selected);
|
|
}
|
|
else {
|
|
int cloth_season;
|
|
int count;
|
|
mActor_name_t* list_p;
|
|
mActor_name_t* list_p2;
|
|
int uncollected_num;
|
|
int n;
|
|
int s;
|
|
int i;
|
|
cloth_season = mSP_get_cloth_season();
|
|
uncollected_num = 0;
|
|
count = 0;
|
|
|
|
for (list_p = list; count < count_p[mSP_CLOTH_SEASON_ANY] && list_p != NULL; list_p++) {
|
|
if (mSP_CollectCheck(list_p[0]) == FALSE) {
|
|
uncollected_num++;
|
|
}
|
|
|
|
count++;
|
|
}
|
|
|
|
n = count_p[mSP_CLOTH_SEASON_ANY];
|
|
for (i = mSP_CLOTH_SEASON_SPRING; i < cloth_season; i++) {
|
|
n += count_p[i]; // add intermediate season counts
|
|
}
|
|
|
|
i = n;
|
|
s = n + count_p[cloth_season];
|
|
list_p2 = list + (int)n;
|
|
for (list_p = list_p2; i < s && list_p != NULL; list_p++) {
|
|
if (mSP_CollectCheck(list_p[0]) == FALSE) {
|
|
uncollected_num++;
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
if (uncollected_num == 0) {
|
|
selected[0] = 0;
|
|
return 0;
|
|
}
|
|
else {
|
|
int selected_idx = RANDOM(uncollected_num);
|
|
|
|
count = 0;
|
|
selected[0] = 0;
|
|
for (list; count < count_p[mSP_CLOTH_SEASON_ANY] && list != NULL && selected_idx > 0; list++) {
|
|
if (mSP_CollectCheck(list[0]) == FALSE) {
|
|
selected_idx--;
|
|
}
|
|
|
|
selected[0]++;
|
|
count++;
|
|
}
|
|
|
|
i = n;
|
|
for (list_p2; i < s && list_p2 != NULL && selected_idx > 0; list_p2++) {
|
|
if (mSP_CollectCheck(list_p2[0]) == FALSE) {
|
|
selected_idx--;
|
|
}
|
|
|
|
selected[0]++;
|
|
i++;
|
|
}
|
|
}
|
|
|
|
return uncollected_num;
|
|
}
|
|
}
|
|
|
|
static int mSP_NoList(mActor_name_t* items_table, int count, mActor_name_t* list) {
|
|
if (list == NULL) {
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
items_table[0] = EMPTY_NO;
|
|
items_table++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void mSP_SetDummyItem(mActor_name_t* items_table, int count, int kind) {
|
|
mActor_name_t dummy_table[mSP_KIND_EXTENDED_MAX] = {
|
|
FTR_CLASSIC_WARDROBE,
|
|
ITM_PAPER00,
|
|
ITM_CLOTH000,
|
|
ITM_CARPET00,
|
|
ITM_WALL00,
|
|
ITM_DIARY00
|
|
};
|
|
|
|
mActor_name_t dummy_item = dummy_table[kind];
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
items_table[i] = dummy_item;
|
|
}
|
|
}
|
|
|
|
extern void mSP_SelectRandomItem_New(
|
|
GAME* game,
|
|
mActor_name_t* goods_table,
|
|
int goods_count,
|
|
mActor_name_t* goods_exist_table,
|
|
int goods_exist_count,
|
|
int category,
|
|
int list_type,
|
|
int uncollected_only
|
|
) {
|
|
mSP_InitItemTable(goods_table, goods_count);
|
|
|
|
if (goods_count != 0 && goods_table != NULL) {
|
|
if (goods_table != NULL) {
|
|
u8 abc_priorities[3];
|
|
mActor_name_t** goods_seg_p = mSP_goods_seg_inf[category];
|
|
int i = 0;
|
|
|
|
mSP_GetGoodsPriority(abc_priorities, category);
|
|
|
|
while (i < goods_count) {
|
|
mActor_name_t* item_list_p = mSP_GetItemList(goods_seg_p, abc_priorities, list_type);
|
|
int list_item_count;
|
|
int selected_idx;
|
|
|
|
if (mSP_NoList(goods_table, goods_count, item_list_p) != FALSE) {
|
|
mSP_SetDummyItem(goods_table, goods_count, category);
|
|
return;
|
|
}
|
|
|
|
if (
|
|
category == mSP_KIND_CLOTH &&
|
|
(list_type == mSP_LISTTYPE_ABC || list_type == mSP_LIST_A || list_type == mSP_LIST_B || list_type == mSP_LIST_C)
|
|
) {
|
|
list_item_count = mSP_CountElementInClothList_collect(item_list_p, &selected_idx, uncollected_only);
|
|
}
|
|
else {
|
|
list_item_count = mSP_CountElementInCommonList_collect(item_list_p, &selected_idx, uncollected_only);
|
|
}
|
|
|
|
if (list_item_count == 0) {
|
|
mSP_InitItemTable(goods_table, goods_count);
|
|
return;
|
|
}
|
|
|
|
if (
|
|
mSP_GoodsExistAlready(goods_table, goods_count, item_list_p[selected_idx]) == FALSE &&
|
|
mSP_GoodsExistAlready(goods_exist_table, goods_exist_count, item_list_p[selected_idx]) == FALSE &&
|
|
Save_Get(shop).rare_item != item_list_p[selected_idx]
|
|
) {
|
|
goods_table[i] = item_list_p[selected_idx];
|
|
i++;
|
|
}
|
|
else if (list_item_count < goods_count + goods_exist_count) {
|
|
/* forcibly add duplicate items if the list size is less than total possible goods */
|
|
goods_table[i] = item_list_p[selected_idx];
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
mSP_SetDummyItem(goods_table, goods_count, category); // ?????
|
|
}
|
|
}
|
|
}
|
|
|
|
static int mSP_CountPriceTableElement(u16* price_table) {
|
|
int n = 0;
|
|
|
|
while (price_table[0] != 0xFFFF) {
|
|
price_table++;
|
|
n++;
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
extern int mSP_ShopSaleReport(mActor_name_t sold_item, mActor_name_t* goods_table, int goods_count, mActor_name_t rsv_item) {
|
|
int i;
|
|
|
|
if (sold_item == ITM_HUKUBUKURO_BAG) {
|
|
Save_Get(shop).flowers_candy_grab_bag_count--;
|
|
return FALSE;
|
|
}
|
|
|
|
if (sold_item == ITM_FOOD_CANDY) {
|
|
Save_Get(shop).flowers_candy_grab_bag_count--;
|
|
return FALSE;
|
|
}
|
|
|
|
for (i = 0; i < goods_count; i++) {
|
|
if (sold_item == goods_table[i]) {
|
|
goods_table[i] = rsv_item;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (sold_item == Save_Get(shop).rare_item) {
|
|
Save_Get(shop).rare_item = rsv_item;
|
|
return FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern u16 binsen_price_table[];
|
|
extern u16 cloth_price_table[];
|
|
extern u16 carpet_price_table[];
|
|
extern u16 wall_price_table[];
|
|
extern u16 tool_price_table[];
|
|
extern u16 plant_price_table[];
|
|
extern u16 food_price_table[];
|
|
extern u16 fish_price_table[];
|
|
extern u16 md_price_table[];
|
|
extern u16 diary_price_table[];
|
|
extern u16 insect_price_table[];
|
|
|
|
static u16* l_binsen_price_info = binsen_price_table;
|
|
static u16* l_cloth_price_info = cloth_price_table;
|
|
static u16* l_carpet_price_info = carpet_price_table;
|
|
static u16* l_wall_price_info = wall_price_table;
|
|
static u16* l_tool_price_info = tool_price_table;
|
|
static u16* l_plant_price_info = plant_price_table;
|
|
static u16* l_food_price_info = food_price_table;
|
|
static u16* l_fish_price_info = fish_price_table;
|
|
static u16* l_md_price_info = md_price_table;
|
|
static u16* l_diary_price_info = diary_price_table;
|
|
static u16* l_insect_price_info = insect_price_table;
|
|
|
|
static u16** l_price_info[ITEM1_CAT_NUM] = {
|
|
&l_binsen_price_info,
|
|
NULL,
|
|
&l_tool_price_info,
|
|
&l_fish_price_info,
|
|
&l_cloth_price_info,
|
|
NULL,
|
|
&l_carpet_price_info,
|
|
&l_wall_price_info,
|
|
&l_food_price_info,
|
|
&l_plant_price_info,
|
|
&l_md_price_info,
|
|
&l_diary_price_info,
|
|
NULL,
|
|
&l_insect_price_info,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
static mActor_name_t mSP_item1_start_idx_table[ITEM1_CAT_NUM] = {
|
|
ITM_PAPER_START,
|
|
ITM_MONEY_START,
|
|
ITM_TOOL_START,
|
|
ITM_FISH_START,
|
|
ITM_CLOTH_START,
|
|
ITM_ETC_START,
|
|
ITM_CARPET_START,
|
|
ITM_WALL_START,
|
|
ITM_FOOD_START,
|
|
ITM_ENV_START,
|
|
ITM_MINIDISK_START,
|
|
ITM_DIARY_START,
|
|
ITM_TICKET_START,
|
|
ITM_INSECT_START,
|
|
ITM_HUKUBUKURO_START,
|
|
ITM_KABU_START
|
|
};
|
|
|
|
extern u16 ftr_price_table[];
|
|
|
|
extern u32 mSP_ItemNo2ItemPrice(mActor_name_t item_no) {
|
|
static u32 shellfish_price_table[ITM_SHELL_END - ITM_SHELL_START] = {
|
|
160, 80, 600, 120, 240, 1800, 1400, 1000
|
|
};
|
|
|
|
lbRTC_time_c rtc_time = Common_Get(time.rtc_time);
|
|
lbRTC_year_t year = rtc_time.year;
|
|
u32 price = 0;
|
|
|
|
if (item_no == ITM_HUKUBUKURO_BAG) {
|
|
return year;
|
|
}
|
|
|
|
item_no = mRmTp_FtrItemNo2Item1ItemNo(item_no, FALSE);
|
|
if (item_no >= ITM_SHELL0 && item_no <= ITM_SHELL7) {
|
|
u32 idx = item_no - ITM_SHELL0;
|
|
|
|
return shellfish_price_table[idx % 8];
|
|
}
|
|
|
|
if (item_no == ITM_SIGNBOARD) {
|
|
return mSP_SIGNBOARD_PRICE;
|
|
}
|
|
|
|
switch (ITEM_NAME_GET_TYPE(item_no)) {
|
|
case NAME_TYPE_ITEM1:
|
|
{
|
|
u16** price_list_pp = l_price_info[ITEM_NAME_GET_CAT(item_no)];
|
|
|
|
if (price_list_pp != NULL && &price != NULL) {
|
|
u16* price_list_p = *price_list_pp;
|
|
int idx = item_no - mSP_item1_start_idx_table[ITEM_NAME_GET_CAT(item_no)];
|
|
|
|
if (item_no >= ITM_PAPER_START && item_no <= (ITM_PAPER_END - 1)) {
|
|
int paper_idx = (item_no - ITM_PAPER_START);
|
|
|
|
idx = (item_no - ITM_PAPER_START) % PAPER_UNIQUE_NUM;
|
|
if (idx < mSP_CountPriceTableElement(price_list_p)) {
|
|
price = price_list_p[idx];
|
|
price = price * ((paper_idx / 64) + 1);
|
|
return price;
|
|
}
|
|
}
|
|
|
|
if (idx < mSP_CountPriceTableElement(price_list_p)) {
|
|
switch (item_no) {
|
|
case ITM_FOOD_APPLE:
|
|
case ITM_FOOD_CHERRY:
|
|
case ITM_FOOD_PEAR:
|
|
case ITM_FOOD_PEACH:
|
|
case ITM_FOOD_ORANGE:
|
|
{
|
|
if (Save_Get(fruit) != item_no) {
|
|
return mSP_FOREIGN_FRUIT_PRICE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
price = price_list_p[idx];
|
|
return price;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case NAME_TYPE_FTR0:
|
|
case NAME_TYPE_FTR1:
|
|
{
|
|
if (&price != NULL) {
|
|
int ftr_idx = mRmTp_FtrItemNo2FtrIdx(item_no);
|
|
u16* price_list_p = ftr_price_table;
|
|
|
|
if (ftr_idx < mSP_CountPriceTableElement(price_list_p)) {
|
|
price = price_list_p[ftr_idx];
|
|
return price;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
extern int mSP_SearchItemCategoryPriority(mActor_name_t item_no, int category, int list_type, GAME* game) {
|
|
u8 abc_priorities[3];
|
|
mActor_name_t** lists_p = mSP_goods_seg_inf[category];
|
|
mActor_name_t* list_p;
|
|
int count;
|
|
int i;
|
|
|
|
mSP_GetGoodsPriority(abc_priorities, category);
|
|
list_p = mSP_GetItemList(lists_p, abc_priorities, list_type);
|
|
count = mSP_CountElementInCommonList(list_p);
|
|
|
|
if (list_p != NULL) {
|
|
for (i = 0; i < count; i++) {
|
|
if (item_no == list_p[i]) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static int mSP_ItemNo2GoodsListCategory(mActor_name_t item_no) {
|
|
if (ITEM_IS_FTR(item_no)) {
|
|
return mSP_KIND_FURNITURE;
|
|
}
|
|
else if (item_no >= ITM_PAPER_START && item_no < ITM_PAPER_END) {
|
|
return mSP_KIND_PAPER;
|
|
}
|
|
else if (item_no >= ITM_CLOTH_START && item_no < ITM_CLOTH_END) {
|
|
return mSP_KIND_CLOTH;
|
|
}
|
|
else if (item_no >= ITM_WALL_START && item_no < ITM_WALL_END) {
|
|
return mSP_KIND_WALLPAPER;
|
|
}
|
|
else if (item_no >= ITM_CARPET_START && item_no < ITM_CARPET_END) {
|
|
return mSP_KIND_CARPET;
|
|
}
|
|
else if (item_no >= ITM_DIARY_START && item_no <= (ITM_DIARY_END-1)) {
|
|
return mSP_KIND_DIARY;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static u8 l_zakka_goods[mSP_GOODS_TYPE_NUM] = {
|
|
1, // stationery
|
|
1, // clothing
|
|
1, // ABC ftr
|
|
0, // rare ftr
|
|
1, // carpet
|
|
1, // wallpaper
|
|
1, // ??
|
|
0, // ??
|
|
1, // saplings
|
|
2, // tools
|
|
2 // plants
|
|
};
|
|
|
|
static u8 l_conbini_goods[mSP_GOODS_TYPE_NUM] = {
|
|
2, // stationery
|
|
2, // clothing
|
|
2, // ABC ftr
|
|
0, // rare ftr
|
|
1, // carpet
|
|
1, // wallpaper
|
|
1, // ??
|
|
0, // ??
|
|
1, // saplings
|
|
3, // tools
|
|
3 // plants
|
|
};
|
|
|
|
static u8 l_super_goods[mSP_GOODS_TYPE_NUM] = {
|
|
2, // stationery
|
|
3, // clothing
|
|
3, // ABC ftr
|
|
1, // rare ftr
|
|
2, // carpet
|
|
2, // wallpaper
|
|
1, // ??
|
|
0, // ??
|
|
2, // saplings
|
|
2, // tools
|
|
4 // plants
|
|
};
|
|
|
|
static u8 l_dsuper_goods[mSP_GOODS_TYPE_NUM] = {
|
|
4, // stationery
|
|
5, // clothing
|
|
5, // ABC ftr
|
|
1, // rare ftr
|
|
3, // carpet
|
|
3, // wallpaper
|
|
1, // ??
|
|
0, // ??
|
|
3, // saplings
|
|
3, // tools
|
|
5 // plants
|
|
};
|
|
|
|
static u8* l_goods_count_table[mSP_SHOP_TYPE_NUM] = {
|
|
l_zakka_goods,
|
|
l_conbini_goods,
|
|
l_super_goods,
|
|
l_dsuper_goods
|
|
};
|
|
|
|
static void mSP_MakeRandomGoodsList(GAME* game, int* count, mActor_name_t* goods_list) {
|
|
int shop_level = mSP_GetShopLevel();
|
|
u8* goods_count = l_goods_count_table[shop_level];
|
|
Shop_c* shop = Save_GetPointer(shop);
|
|
mActor_name_t rare;
|
|
|
|
/* roll rare furniture if the shop has one */
|
|
if (goods_count[mSP_GOODS_TYPE_RARE_FTR] != 0) {
|
|
mSP_SelectRandomItem_New(game, &rare, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_RARE, FALSE);
|
|
}
|
|
else {
|
|
rare = EMPTY_NO;
|
|
}
|
|
|
|
Save_Get(shop).rare_item = rare;
|
|
|
|
/* roll ABC list furniture */
|
|
mSP_SelectRandomItem_New(game, goods_list + count[0], goods_count[mSP_GOODS_TYPE_FTR], NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_ABC, FALSE);
|
|
mSP_SetSeasonFTR(goods_list + count[0], goods_count[mSP_GOODS_TYPE_FTR]); // replace with seasonal furniture if necessary
|
|
count[0] += goods_count[mSP_GOODS_TYPE_FTR];
|
|
|
|
/* check for grab bag sale */
|
|
if (mSP_Chk_HukubukuroSail()) {
|
|
shop->flowers_candy_grab_bag_count += (s8)goods_count[mSP_GOODS_TYPE_PAPER];
|
|
if (shop_level >= mSP_SHOP_TYPE_SUPER) {
|
|
shop->flowers_candy_grab_bag_count += 1;
|
|
}
|
|
}
|
|
else {
|
|
/* no grab bag sale, so roll paper & diaries */
|
|
mSP_SelectRandomItem_New(game, goods_list + count[0], goods_count[mSP_GOODS_TYPE_PAPER], NULL, 0, mSP_KIND_PAPER, mSP_LISTTYPE_ABC, FALSE);
|
|
count[0] += goods_count[mSP_GOODS_TYPE_PAPER];
|
|
|
|
/* only roll diaries for Nookway or higher */
|
|
if (shop_level >= mSP_SHOP_TYPE_SUPER) {
|
|
mSP_SelectRandomItem_New(game, goods_list + count[0], 1, NULL, 0, mSP_KIND_DIARY, mSP_LISTTYPE_ABC, FALSE);
|
|
count[0] += 1;
|
|
}
|
|
}
|
|
|
|
/* roll clothing */
|
|
mSP_SelectRandomItem_New(game, goods_list + count[0], goods_count[mSP_GOODS_TYPE_CLOTH], NULL, 0, mSP_KIND_CLOTH, mSP_LISTTYPE_ABC, FALSE);
|
|
count[0] += goods_count[mSP_GOODS_TYPE_CLOTH];
|
|
|
|
/* roll carpets */
|
|
mSP_SelectRandomItem_New(game, goods_list + count[0], goods_count[mSP_GOODS_TYPE_CARPET], NULL, 0, mSP_KIND_CARPET, mSP_LISTTYPE_ABC, FALSE);
|
|
count[0] += goods_count[mSP_GOODS_TYPE_CARPET];
|
|
|
|
/* roll wallpaper */
|
|
mSP_SelectRandomItem_New(game, goods_list + count[0], goods_count[mSP_GOODS_TYPE_WALL], NULL, 0, mSP_KIND_WALLPAPER, mSP_LISTTYPE_ABC, FALSE);
|
|
count[0] += goods_count[mSP_GOODS_TYPE_WALL];
|
|
}
|
|
|
|
extern int mSP_CountElementInGoodsList() {
|
|
mActor_name_t* items = Save_Get(shop).items;
|
|
int goods_count = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < mSP_GOODS_COUNT; i++) {
|
|
if (items[i] != EMPTY_NO) {
|
|
goods_count++;
|
|
}
|
|
}
|
|
|
|
return goods_count;
|
|
}
|
|
|
|
static void mSP_SelectTool(mActor_name_t* goods_list, int* count, int tool_num, int shop_level) {
|
|
static int table[4] = { ITM_SHOVEL, ITM_NET, ITM_ROD, ITM_AXE };
|
|
|
|
int tools_added = 0;
|
|
u16 paint_idx = Save_Get(shop).shop_info.paint_color;
|
|
u32 sales_sum = Save_Get(shop).sales_sum;
|
|
f32 tool_max;
|
|
|
|
/* tool lockout based on sales sum is only applicable to Nook's Cranny */
|
|
if (shop_level > mSP_SHOP_TYPE_ZAKKA) {
|
|
tool_max = 4;/* shove, net, rod, axe */
|
|
}
|
|
else if (sales_sum < mSP_NET_SALES_SUM) {
|
|
tool_max = 1; /* shovel only */
|
|
}
|
|
else if (sales_sum < mSP_ROD_SALES_SUM) {
|
|
tool_max = 2; /* shovel, net */
|
|
}
|
|
else if (sales_sum < mSP_AXE_SALES_SUM) {
|
|
tool_max = 3; /* shovel, net, rod */
|
|
}
|
|
else {
|
|
tool_max = 4; /* shove, net, rod, axe */
|
|
}
|
|
|
|
if (tool_num > (int)tool_max) {
|
|
tool_num = (int)tool_max;
|
|
}
|
|
|
|
/*
|
|
This implementation kind of sucks.
|
|
At best case there's a (1/4)^4 (~0.4%) chance of
|
|
rolling all four unique tools in a single go.
|
|
*/
|
|
while (tools_added < tool_num) {
|
|
int idx = RANDOM_F(tool_max);
|
|
mActor_name_t tool = table[idx];
|
|
|
|
/* Don't allow duplicate tools */
|
|
if (mSP_GoodsExistAlready(goods_list, count[0], tool) == FALSE) {
|
|
goods_list[(int)count[0]] = tool;
|
|
tools_added++;
|
|
count[0]++;
|
|
}
|
|
}
|
|
|
|
/* Add paint & signboard if shop is Nookway or greater */
|
|
if (shop_level >= mSP_SHOP_TYPE_SUPER) {
|
|
if (paint_idx >= PAINT_NUM) {
|
|
paint_idx = 0; /* wrap over to beginning */
|
|
}
|
|
|
|
goods_list[count[0]] = ITM_RED_PAINT + paint_idx;
|
|
paint_idx++;
|
|
Save_Get(shop).shop_info.paint_color = paint_idx;
|
|
count[0]++;
|
|
goods_list[count[0]] = ITM_SIGNBOARD;
|
|
count[0]++;
|
|
}
|
|
|
|
/* Add umbrella */
|
|
mSP_RandomUmbSelect(goods_list + count[0], 1);
|
|
count[0]++;
|
|
}
|
|
|
|
static void mSP_SelectPlant(mActor_name_t* goods_list, int* count, int flower_count, int sapling_count, int shop_level) {
|
|
u8 flower_use[FLOWER_NUM];
|
|
int i;
|
|
|
|
if (mSP_CheckHallowinDay()) {
|
|
Save_Get(shop).flowers_candy_grab_bag_count = flower_count;
|
|
flower_count = sapling_count;
|
|
sapling_count = 0;
|
|
}
|
|
|
|
if (shop_level >= mSP_SHOP_TYPE_SUPER && sapling_count > 0) {
|
|
goods_list[count[0]] = ITM_CEDAR_SAPLING;
|
|
sapling_count--;
|
|
count[0] += 1;
|
|
}
|
|
|
|
for (i = 0; i < sapling_count; i++) {
|
|
goods_list[count[0]] = ITM_SAPLING;
|
|
count[0] += 1;
|
|
}
|
|
|
|
for (i = 0; i < FLOWER_NUM; i++) {
|
|
flower_use[i] = FALSE;
|
|
}
|
|
|
|
while (flower_count > 0) {
|
|
int idx = RANDOM(FLOWER_NUM);
|
|
|
|
if (flower_use[idx] == FALSE) {
|
|
goods_list[count[0]] = ITM_WHITE_PANSY_BAG + idx;
|
|
flower_use[idx] = TRUE;
|
|
flower_count--;
|
|
count[0] += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void mSP_MakeGoodsList(GAME* game) {
|
|
int count = 0;
|
|
mActor_name_t* shop_items = Save_Get(shop).items;
|
|
Shop_c* shop = Save_GetPointer(shop);
|
|
int shop_level = mSP_GetShopLevel();
|
|
u8* goods_count = l_goods_count_table[shop_level];
|
|
u8 tool_count = goods_count[mSP_GOODS_TYPE_TOOL];
|
|
u8 flower_count = goods_count[mSP_GOODS_TYPE_PLANT];
|
|
u8 sapling_count = goods_count[mSP_GOODS_TYPE_SAPLING];
|
|
|
|
if (mSP_CheckFukubikiDay() == FALSE) {
|
|
if (mSP_Chk_HukubukuroSail() != FALSE) {
|
|
shop->flowers_candy_grab_bag_count = 0;
|
|
}
|
|
|
|
mSP_MakeRandomGoodsList(game, &count, shop_items);
|
|
|
|
if (mSP_Chk_HukubukuroSail() != FALSE) {
|
|
shop->flowers_candy_grab_bag_count += (s8)tool_count;
|
|
shop->flowers_candy_grab_bag_count += (s8)flower_count;
|
|
shop->flowers_candy_grab_bag_count += (s8)sapling_count;
|
|
|
|
if (shop_level >= mSP_SHOP_TYPE_SUPER) {
|
|
shop->flowers_candy_grab_bag_count++; // add signboard & paint
|
|
shop->flowers_candy_grab_bag_count++;
|
|
}
|
|
}
|
|
else {
|
|
mSP_SelectTool(shop_items, &count, tool_count, shop_level & 3);
|
|
mSP_SelectPlant(shop_items, &count, flower_count, sapling_count, shop_level & 3);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void mSP_MakeLotteryList(GAME* game) {
|
|
mActor_name_t* lottery_items = Save_Get(shop).lottery_items;
|
|
mActor_name_t unobtained_lottery_item;
|
|
|
|
mSP_SelectRandomItem_New(
|
|
game,
|
|
&unobtained_lottery_item,
|
|
1,
|
|
NULL,
|
|
0,
|
|
mSP_KIND_FURNITURE,
|
|
mSP_LISTTYPE_LOTTERY,
|
|
TRUE
|
|
);
|
|
|
|
if (unobtained_lottery_item == EMPTY_NO) {
|
|
mSP_SelectRandomItem_New(
|
|
game,
|
|
lottery_items,
|
|
mSP_LOTTERY_ITEM_COUNT,
|
|
NULL,
|
|
0,
|
|
mSP_KIND_FURNITURE,
|
|
mSP_LISTTYPE_LOTTERY,
|
|
FALSE
|
|
);
|
|
}
|
|
else {
|
|
mSP_SelectRandomItem_New(
|
|
game,
|
|
lottery_items + 1,
|
|
mSP_LOTTERY_ITEM_COUNT - 1,
|
|
&unobtained_lottery_item,
|
|
1,
|
|
mSP_KIND_FURNITURE,
|
|
mSP_LISTTYPE_LOTTERY,
|
|
FALSE
|
|
);
|
|
|
|
lottery_items[0] = unobtained_lottery_item;
|
|
}
|
|
}
|
|
|
|
extern int mSP_CheckExchangeDay2() {
|
|
Shop_c* shop = Save_GetPointer(shop);
|
|
lbRTC_time_c rtc_time = Common_Get(time.rtc_time);
|
|
int res = lbRTC_IsEqualTime(
|
|
&rtc_time,
|
|
&shop->exchange_time,
|
|
lbRTC_CHECK_DAYS | lbRTC_CHECK_MONTHS | lbRTC_CHECK_YEARS
|
|
);
|
|
|
|
return res == lbRTC_EQUAL;
|
|
}
|
|
|
|
extern int mSP_CheckExchangeMonth() {
|
|
Shop_c* shop = Save_GetPointer(shop);
|
|
lbRTC_time_c rtc_time = Common_Get(time.rtc_time);
|
|
int res = lbRTC_IsEqualTime(
|
|
&rtc_time,
|
|
&shop->exchange_time,
|
|
lbRTC_CHECK_MONTHS | lbRTC_CHECK_YEARS
|
|
);
|
|
|
|
return res == lbRTC_EQUAL;
|
|
}
|
|
|
|
extern void mSP_NewExchangeDay() {
|
|
Save_Get(shop).exchange_time = Common_Get(time.rtc_time);
|
|
}
|
|
|
|
/* @unused size: 0x104 */
|
|
// ? mSP_SearchRareFurniture(...)
|
|
|
|
extern void mSP_ShopItsumoChirashi(int house_no, int shop_level, mActor_name_t item, int type, int send_proc) {
|
|
static int rare_chirashi_bunmen[mSP_SHOP_TYPE_NUM][2] = {
|
|
{ 18, 18 },
|
|
{ 19, 19 },
|
|
{ 21, 20 },
|
|
{ 23, 22 }
|
|
};
|
|
|
|
if (Save_Get(homes[house_no]).ownerID.land_id != 0xFFFF) {
|
|
int free_mail_idx = mMl_chk_mail_free_space(Save_Get(homes[house_no]).mailbox, HOME_MAILBOX_SIZE);
|
|
|
|
if (mEv_ArbeitPlayer(mHS_get_pl_no(house_no) & 3) != TRUE) {
|
|
u8 item_name_str[mIN_ITEM_NAME_LEN];
|
|
Mail_c leaflet;
|
|
int header_back_start;
|
|
|
|
mIN_copy_name_str(item_name_str, item);
|
|
mHandbill_Set_free_str(mHandbill_FREE_STR7, item_name_str, mIN_ITEM_NAME_LEN);
|
|
mMl_clear_mail(&leaflet);
|
|
mHandbill_Load_HandbillFromRom(
|
|
leaflet.content.header,
|
|
&header_back_start,
|
|
leaflet.content.footer,
|
|
leaflet.content.body,
|
|
rare_chirashi_bunmen[shop_level][type & 1]
|
|
);
|
|
leaflet.content.font = mMl_FONT_0;
|
|
leaflet.content.header_back_start = header_back_start;
|
|
leaflet.content.mail_type = mMl_TYPE_SHOP_SALE_LEAFLET;
|
|
leaflet.content.paper_type = ITM_PAPER55; // simple paper
|
|
|
|
switch (send_proc) {
|
|
case mPO_SENDTYPE_MAIL:
|
|
{
|
|
mPO_receipt_proc(&leaflet, mPO_SENDTYPE_LEAFLET);
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
if (free_mail_idx >= 0) {
|
|
mPr_CopyPersonalID(&leaflet.header.recipient.personalID, &Save_Get(private[mHS_get_pl_no(house_no) & 3]).player_ID);
|
|
leaflet.header.recipient.type = mMl_NAME_TYPE_PLAYER;
|
|
|
|
mMl_copy_mail(Save_Get(homes[house_no]).mailbox + free_mail_idx, &leaflet);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void mSP_SetShopRareFurnitureChirashi(int player_no, mActor_name_t* goods_list, int goods_count, GAME* game) {
|
|
const int p = player_no;
|
|
int shop_level = mSP_GetShopLevel();
|
|
int is_rare_item = FALSE;
|
|
mActor_name_t rare_item = EMPTY_NO;
|
|
int arrange_idx = mHS_get_arrange_idx(p);
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
|
|
if (player_no != mHS_get_pl_no_detail(arrange_idx)) {
|
|
mCkRh_SavePlayTime(player_no);
|
|
return;
|
|
}
|
|
|
|
/* Check if we're on the last day of the month */
|
|
if (Common_Get(time.rtc_time).day == lbRTC_GetDaysByMonth(Common_Get(time.rtc_time).year,
|
|
Common_Get(time.rtc_time).month)) {
|
|
mCkRh_SavePlayTime(player_no);
|
|
} else if (mEv_CheckEvent(mEv_SAVED_RENEWSHOP) == TRUE) {
|
|
mCkRh_SavePlayTime(player_no); // shop was already 'renewed' today
|
|
} else {
|
|
u16 bargain_day = mEv_get_bargain_day();
|
|
lbRTC_time_c goki_time;
|
|
mHm_hs_c* home;
|
|
|
|
if (bargain_day != 0) {
|
|
u32 month = mEv_TO_MONTH(bargain_day);
|
|
u32 day = mEv_TO_DAY(bargain_day);
|
|
if (Common_Get(time.rtc_time).month == month &&
|
|
Common_Get(time.rtc_time).day == day) {
|
|
mCkRh_SavePlayTime(player_no); // shop 'bargin' event is active
|
|
return;
|
|
}
|
|
}
|
|
|
|
goki_time = Save_Get(homes[arrange_idx]).goki.time;
|
|
lbRTC_Add_DD(&goki_time, 1);
|
|
home = Save_GetPointer(homes[arrange_idx]);
|
|
|
|
/* check if the current date & time is past the renew time */
|
|
if (home->goki.time.year == rtc_time->year &&
|
|
home->goki.time.month == rtc_time->month &&
|
|
home->goki.time.day == rtc_time->day) return;
|
|
|
|
if (goki_time.year == rtc_time->year &&
|
|
goki_time.month == rtc_time->month &&
|
|
goki_time.day == rtc_time->day &&
|
|
goki_time.hour < mTM_FIELD_RENEW_HOUR) return;
|
|
|
|
if (rtc_time->hour < mTM_FIELD_RENEW_HOUR ||
|
|
rtc_time->hour > mSP_GetShopCloseTime()) return;
|
|
|
|
if (mSP_SearchItemCategoryPriority(Save_Get(shop).rare_item,
|
|
mSP_KIND_FURNITURE,
|
|
mSP_LISTTYPE_RARE, game)) {
|
|
rare_item = Save_Get(shop).rare_item;
|
|
is_rare_item = TRUE;
|
|
} else {
|
|
int i;
|
|
|
|
/* spotlight item in shop wasn't the rare item, so check all
|
|
* the goods for one */
|
|
for (i = 0; i < goods_count; i++) {
|
|
if (mSP_ItemNo2GoodsListCategory(goods_list[i]) ==
|
|
mSP_KIND_FURNITURE) {
|
|
is_rare_item = mSP_SearchItemCategoryPriority(
|
|
goods_list[i], mSP_KIND_FURNITURE,
|
|
mSP_LISTTYPE_RARE, game);
|
|
|
|
if (is_rare_item != FALSE) {
|
|
rare_item = goods_list[i];
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* check if a rare item was found, and if so, send the notice
|
|
* leaflet to the player */
|
|
if (is_rare_item != FALSE) {
|
|
int arrange_idx = mHS_get_arrange_idx(p);
|
|
|
|
if (mHS_get_pl_no_detail(arrange_idx) != -1) {
|
|
mSP_ShopItsumoChirashi(arrange_idx, shop_level,
|
|
rare_item, is_rare_item,
|
|
mPO_SENDTYPE_LEAFLET);
|
|
mCkRh_SavePlayTime(player_no);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void mSP_SetRenewalChiraswhi_AppoDay() {
|
|
static int chirashi_idx_appoday[mSP_SHOP_TYPE_NUM] = { 0x1B, 0x1B, 0x1C, 0x1D };
|
|
Mail_c leaflet;
|
|
Mail_ct_c* content = &leaflet.content;
|
|
int header_back_start;
|
|
|
|
if (Save_Get(shop).shop_info.upgrading_today && mEv_CheckEvent(mEv_SAVED_RENEWSHOP) == FALSE) {
|
|
int shop_level = mSP_GetRealShopLevel();
|
|
int i;
|
|
|
|
for (i = 0; i < mHS_HOUSE_NUM; i++) {
|
|
int player_no = mHS_get_pl_no(i) & 3;
|
|
int free_mail_idx = mMl_chk_mail_free_space(Save_Get(homes[i]).mailbox, HOME_MAILBOX_SIZE);
|
|
|
|
if (free_mail_idx >= 0 && Save_Get(homes[i]).ownerID.land_id != 0xFFFF && mEv_ArbeitPlayer(player_no) == FALSE) {
|
|
|
|
mMl_clear_mail(&leaflet);
|
|
mHandbill_Load_HandbillFromRom(
|
|
content->header,
|
|
&header_back_start,
|
|
content->footer,
|
|
content->body,
|
|
chirashi_idx_appoday[shop_level]
|
|
);
|
|
leaflet.content.font = mMl_FONT_0;
|
|
leaflet.content.header_back_start = header_back_start;
|
|
leaflet.content.mail_type = mMl_TYPE_SHOP_SALE_LEAFLET;
|
|
leaflet.content.paper_type = ITM_PAPER55; // simple paper
|
|
|
|
mPr_CopyPersonalID(&leaflet.header.recipient.personalID, &Save_Get(private[mHS_get_pl_no(i) & 3]).player_ID);
|
|
leaflet.header.recipient.type = mMl_NAME_TYPE_PLAYER;
|
|
|
|
mMl_copy_mail(Save_Get(homes[i]).mailbox + free_mail_idx, &leaflet);
|
|
}
|
|
}
|
|
|
|
Save_Get(shop).shop_info.upgrading_today = FALSE;
|
|
}
|
|
}
|
|
|
|
extern void mSP_ExchangeLineUp_InGame(GAME* game) {
|
|
if (mSP_CheckExchangeDay2()) {
|
|
if (mSP_CheckExchangeMonth()) {
|
|
mSP_LotteryLineUp_GameAlloc(game);
|
|
}
|
|
|
|
mSP_NewExchangeDay();
|
|
mSP_ExchangeLineUp_GameAlloc(game);
|
|
Save_Get(shop).shop_info.not_loaded_before = TRUE;
|
|
mSP_SetShopRareFurnitureChirashi(Common_Get(player_no), Save_Get(shop).items, mSP_GOODS_COUNT, game);
|
|
}
|
|
}
|
|
|
|
extern void mSP_PlusSales(u32 sum) {
|
|
Save_Get(shop).sales_sum += sum;
|
|
|
|
if (mSP_GetShopLevel() == mSP_SHOP_TYPE_ZAKKA) {
|
|
if (Save_Get(shop).sales_sum > mSP_COMBINI_SUM) {
|
|
Save_Get(shop).sales_sum = mSP_COMBINI_SUM;
|
|
}
|
|
}
|
|
else if (mSP_GetShopLevel() == mSP_SHOP_TYPE_COMBINI) {
|
|
if (Save_Get(shop).sales_sum > mSP_SUPER_SUM) {
|
|
Save_Get(shop).sales_sum = mSP_SUPER_SUM;
|
|
}
|
|
}
|
|
else if (mSP_GetShopLevel() == mSP_SHOP_TYPE_SUPER) {
|
|
if (Save_Get(shop).sales_sum > mSP_DSUPER_SUM) {
|
|
Save_Get(shop).sales_sum = mSP_DSUPER_SUM;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* @unused size: 0x74 */
|
|
// extern int mSP_GetVisitorCount()
|
|
|
|
extern int mSP_SetNewVisitor() {
|
|
if (mLd_PlayerManKindCheck()) {
|
|
Save_Get(shop).visitor_flag = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern u32 mSP_GetSalesSum() {
|
|
return Save_Get(shop).sales_sum;
|
|
}
|
|
|
|
extern int mSP_GetShopLevel() {
|
|
return Save_Get(shop).shop_info.shop_level;
|
|
}
|
|
|
|
extern int mSP_RenewShopLevel() {
|
|
if (Save_Get(shop).shop_info.shop_level != (u8)mSP_GetRealShopLevel()) {
|
|
Save_Get(shop).shop_info.shop_level = mSP_GetRealShopLevel();
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern int mSP_GetRealShopLevel() {
|
|
u32 sales_sum = mSP_GetSalesSum();
|
|
|
|
if (sales_sum >= mSP_DSUPER_SUM && Save_Get(shop).visitor_flag != FALSE) {
|
|
return mSP_SHOP_TYPE_DSUPER;
|
|
}
|
|
else if (sales_sum >= mSP_SUPER_SUM) {
|
|
return mSP_SHOP_TYPE_SUPER;
|
|
}
|
|
|
|
return sales_sum >= mSP_COMBINI_SUM ? mSP_SHOP_TYPE_COMBINI : mSP_SHOP_TYPE_ZAKKA;
|
|
}
|
|
|
|
extern int mSP_GetGoodsPercent(int priority) {
|
|
int goods_power = mPr_GetGoodsPower();
|
|
|
|
if (priority >= 0 && priority <= mSP_PRIORITY_RARE) {
|
|
int rare;
|
|
int uncommon;
|
|
|
|
if (goods_power < 0) {
|
|
uncommon = goods_power + 35 + 5;
|
|
rare = 5;
|
|
}
|
|
else {
|
|
rare = goods_power + 5;
|
|
uncommon = rare + 35;
|
|
}
|
|
|
|
switch (priority) {
|
|
case mSP_PRIORITY_COMMON:
|
|
return 100 - uncommon;
|
|
case mSP_PRIORITY_UNCOMMON:
|
|
return uncommon - rare;
|
|
case mSP_PRIORITY_RARE:
|
|
return rare;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
extern void mSP_PrintNowShopSalesSum(gfxprint_t* gfxprint) {
|
|
if (mFI_CheckFieldData()) {
|
|
int shop_level = mSP_GetShopLevel();
|
|
int status = mSP_ShopOpen();
|
|
u32 sales_sum = mSP_GetSalesSum();
|
|
u32 working_sum;
|
|
|
|
switch (shop_level) {
|
|
case mSP_SHOP_TYPE_ZAKKA:
|
|
working_sum = sales_sum;
|
|
break;
|
|
case mSP_SHOP_TYPE_COMBINI:
|
|
working_sum = sales_sum - mSP_COMBINI_SUM;
|
|
break;
|
|
case mSP_SHOP_TYPE_SUPER:
|
|
working_sum = sales_sum - mSP_SUPER_SUM;
|
|
break;
|
|
default:
|
|
working_sum = sales_sum - mSP_DSUPER_SUM;
|
|
break;
|
|
}
|
|
|
|
gfxprint_color(gfxprint, 200, 200, 250, 255);
|
|
gfxprint_locate8x8(gfxprint, 3, 12);
|
|
|
|
if (mEv_CheckEvent(mEv_SAVED_RENEWSHOP) == FALSE) {
|
|
gfxprint_printf(gfxprint, "%d %d %s", shop_level, working_sum, mSP_ShopStatus2String(status));
|
|
|
|
gfxprint_color(gfxprint, 200, 200, 250, 255);
|
|
gfxprint_printf(
|
|
gfxprint,
|
|
"A%2d,%2d,%2d,%2d,%2d",
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_FURNITURE].a),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_WALLPAPER].a),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CARPET].a),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CLOTH].a),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_PAPER].a)
|
|
);
|
|
}
|
|
else {
|
|
gfxprint_color(gfxprint, 200, 100, 100, 255);
|
|
gfxprint_printf(
|
|
gfxprint,
|
|
"%d %d %s->%d.%d.%d",
|
|
shop_level,
|
|
working_sum,
|
|
mSP_ShopStatus2String(status),
|
|
Save_Get(shop).renewal_time.year,
|
|
Save_Get(shop).renewal_time.month,
|
|
Save_Get(shop).renewal_time.day
|
|
);
|
|
|
|
gfxprint_color(gfxprint, 200, 200, 250, 255);
|
|
gfxprint_printf(
|
|
gfxprint,
|
|
" A%2d,%2d,%2d,%2d,%2d",
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_FURNITURE].a),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_WALLPAPER].a),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CARPET].a),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CLOTH].a),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_PAPER].a)
|
|
);
|
|
}
|
|
|
|
gfxprint_color(gfxprint, 200, 200, 250, 255);
|
|
gfxprint_locate8x8(gfxprint, 3, 13);
|
|
gfxprint_printf(
|
|
gfxprint,
|
|
"B%2d,%2d,%2d,%2d,%2d",
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_FURNITURE].b),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_WALLPAPER].b),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CARPET].b),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CLOTH].b),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_PAPER].b)
|
|
);
|
|
gfxprint_printf(
|
|
gfxprint,
|
|
"C%2d,%2d,%2d,%2d,%2d",
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_FURNITURE].c),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_WALLPAPER].c),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CARPET].c),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_CLOTH].c),
|
|
mSP_GetGoodsPercent(Save_Get(shop).priority_lists[mSP_KIND_PAPER].c)
|
|
);
|
|
}
|
|
}
|
|
|
|
extern void mSP_GetGoodsPriority(u8* abc_priorities, int category) {
|
|
mSP_goods_priority_list_c* priorities = Save_Get(shop).priority_lists;
|
|
|
|
if (category == mSP_KIND_DIARY) {
|
|
category = mSP_KIND_FURNITURE;
|
|
}
|
|
|
|
abc_priorities[0] = priorities[category].a;
|
|
abc_priorities[1] = priorities[category].b;
|
|
abc_priorities[2] = priorities[category].c;
|
|
}
|
|
|
|
static void mSP_SetExchangeDay() {
|
|
Save_Get(shop).exchange_time = Common_Get(time.rtc_time);
|
|
}
|
|
|
|
static void mSP_InitGoods() {
|
|
Shop_c* shop = Save_GetPointer(shop);
|
|
mActor_name_t* items = shop->items;
|
|
int i;
|
|
|
|
for (i = 0; i < mSP_GOODS_COUNT; i++) {
|
|
*items++ = EMPTY_NO;
|
|
}
|
|
}
|
|
|
|
extern void mSP_ExchangeLineUp_ZeldaMalloc() {
|
|
mSP_InitGoods();
|
|
mSP_MakeGoodsList(NULL);
|
|
mSP_SetExchangeDay();
|
|
}
|
|
|
|
extern void mSP_LotteryLineUp_ZeldaMalloc() {
|
|
mSP_MakeLotteryList(NULL);
|
|
}
|
|
|
|
extern void mSP_ExchangeLineUp_GameAlloc(GAME* game) {
|
|
mSP_InitGoods();
|
|
mSP_MakeGoodsList(game);
|
|
mSP_SetExchangeDay();
|
|
}
|
|
|
|
extern void mSP_LotteryLineUp_GameAlloc(GAME* game) {
|
|
mSP_MakeLotteryList(game);
|
|
}
|
|
|
|
extern void mSP_InitShopSaveData() {
|
|
Shop_c* shop = Save_GetPointer(shop);
|
|
PersonalID_c* pid = shop->unused_ids;
|
|
mActor_name_t* lottery_items = shop->lottery_items;
|
|
int i = 0;
|
|
|
|
while (i < mSP_PERSONAL_ID_COUNT) {
|
|
mPr_ClearPersonalID(pid);
|
|
pid++;
|
|
i++;
|
|
}
|
|
|
|
mSP_InitGoods();
|
|
Save_Get(shop).rare_item = EMPTY_NO;
|
|
|
|
for (i = 0; i < mSP_LOTTERY_ITEM_COUNT; i++) {
|
|
lottery_items[0] = EMPTY_NO;
|
|
lottery_items++;
|
|
}
|
|
|
|
Save_Get(shop).flowers_candy_grab_bag_count = 0;
|
|
shop->sales_sum = 0;
|
|
shop->exchange_time = Common_Get(time.rtc_time);
|
|
shop->exchange_time.month--;
|
|
shop->shop_info.shop_level = mSP_SHOP_TYPE_ZAKKA;
|
|
shop->renewal_time = shop->exchange_time;
|
|
shop->shop_info.upgrading_today = FALSE;
|
|
Save_Get(shop).visitor_flag = FALSE;
|
|
}
|
|
|
|
static void mSP_DecideUniqueCommonList(mSP_goods_priority_list_c* priority_list) {
|
|
static mSP_goods_priority_list_c priority_candidate[6] = {
|
|
{ mSP_PRIORITY_COMMON, mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_RARE, 0 },
|
|
{ mSP_PRIORITY_COMMON, mSP_PRIORITY_RARE, mSP_PRIORITY_UNCOMMON, 0 },
|
|
{ mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_COMMON, mSP_PRIORITY_RARE, 0 },
|
|
{ mSP_PRIORITY_RARE, mSP_PRIORITY_COMMON, mSP_PRIORITY_UNCOMMON, 0 },
|
|
{ mSP_PRIORITY_RARE, mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_COMMON, 0 },
|
|
{ mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_RARE, mSP_PRIORITY_COMMON, 0 }
|
|
};
|
|
|
|
priority_list[0] = priority_candidate[RANDOM(6)];
|
|
}
|
|
|
|
static void mSP_DecideGoodsCommonList() {
|
|
mSP_goods_priority_list_c* priority_lists = Save_Get(shop).priority_lists;
|
|
|
|
mSP_DecideUniqueCommonList(&priority_lists[mSP_KIND_FURNITURE]);
|
|
mSP_DecideUniqueCommonList(&priority_lists[mSP_KIND_PAPER]);
|
|
mSP_DecideUniqueCommonList(&priority_lists[mSP_KIND_CLOTH]);
|
|
mSP_DecideUniqueCommonList(&priority_lists[mSP_KIND_CARPET]);
|
|
mSP_DecideUniqueCommonList(&priority_lists[mSP_KIND_WALLPAPER]);
|
|
}
|
|
|
|
extern void mSP_ShopGameStartCt(GAME* game) {
|
|
mSP_DecideGoodsCommonList();
|
|
mSP_InitShopSaveData();
|
|
mSP_ExchangeLineUp_InGame(game);
|
|
}
|
|
|
|
extern mActor_name_t mSP_GetNowShopBgNum() {
|
|
switch (Save_Get(scene_no)) {
|
|
case SCENE_SHOP0:
|
|
{
|
|
if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) {
|
|
return 0xFA;
|
|
}
|
|
|
|
return 0xF8;
|
|
}
|
|
|
|
case SCENE_CONVENI:
|
|
{
|
|
if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) {
|
|
return 0xFB;
|
|
}
|
|
|
|
return 0xFE;
|
|
}
|
|
|
|
case SCENE_SUPER:
|
|
{
|
|
if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) {
|
|
return 0xFC;
|
|
}
|
|
|
|
return 0x102;
|
|
}
|
|
|
|
case SCENE_DEPART:
|
|
{
|
|
if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) {
|
|
return 0xFD;
|
|
}
|
|
|
|
return 0x100;
|
|
}
|
|
|
|
case SCENE_DEPART_2:
|
|
return 0x101;
|
|
|
|
default:
|
|
return 0xFE;
|
|
}
|
|
}
|
|
|
|
static int mSP_what_special_sale;
|
|
|
|
extern int mSP_WhatSpecialSale() {
|
|
return mSP_what_special_sale;
|
|
}
|
|
|
|
extern mActor_name_t mSP_GetNowShopFgNum() {
|
|
int event_kind = Save_Get(event_save_data).special.event.bargin.kind;
|
|
|
|
switch (Save_Get(scene_no)) {
|
|
case SCENE_SHOP0:
|
|
{
|
|
if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_EVENT) {
|
|
if (event_kind == mSP_KIND_FURNITURE) {
|
|
mSP_what_special_sale = mSP_KIND_FURNITURE;
|
|
return 0x163;
|
|
}
|
|
|
|
if (event_kind == mSP_KIND_CLOTH) {
|
|
mSP_what_special_sale = mSP_KIND_CLOTH;
|
|
return 0x166;
|
|
}
|
|
|
|
if (event_kind == mSP_KIND_WALLPAPER) {
|
|
mSP_what_special_sale = mSP_KIND_WALLPAPER;
|
|
return 0x165;
|
|
}
|
|
|
|
mSP_what_special_sale = mSP_KIND_CARPET;
|
|
return 0x164;
|
|
}
|
|
|
|
if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) {
|
|
return 0x14D;
|
|
}
|
|
|
|
return 0x22;
|
|
}
|
|
|
|
case SCENE_CONVENI:
|
|
{
|
|
if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_EVENT) {
|
|
if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_FURNITURE) {
|
|
mSP_what_special_sale = mSP_KIND_FURNITURE;
|
|
return 0x167;
|
|
}
|
|
|
|
if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_CLOTH) {
|
|
mSP_what_special_sale = mSP_KIND_CLOTH;
|
|
return 0x16A;
|
|
}
|
|
|
|
if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_WALLPAPER) {
|
|
mSP_what_special_sale = mSP_KIND_WALLPAPER;
|
|
return 0x169;
|
|
}
|
|
|
|
mSP_what_special_sale = mSP_KIND_CARPET;
|
|
return 0x168;
|
|
}
|
|
|
|
if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) {
|
|
return 0x14E;
|
|
}
|
|
|
|
return 0x23;
|
|
}
|
|
|
|
case SCENE_SUPER:
|
|
{
|
|
if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_EVENT) {
|
|
if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_FURNITURE) {
|
|
mSP_what_special_sale = mSP_KIND_FURNITURE;
|
|
return 0x16B;
|
|
}
|
|
|
|
if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_CLOTH) {
|
|
mSP_what_special_sale = mSP_KIND_CLOTH;
|
|
return 0x16E;
|
|
}
|
|
|
|
if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_WALLPAPER) {
|
|
mSP_what_special_sale = mSP_KIND_WALLPAPER;
|
|
return 0x16D;
|
|
}
|
|
|
|
mSP_what_special_sale = mSP_KIND_CARPET;
|
|
return 0x16C;
|
|
}
|
|
|
|
if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) {
|
|
return 0x14F;
|
|
}
|
|
|
|
return 0x24;
|
|
}
|
|
|
|
case SCENE_DEPART:
|
|
{
|
|
if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_EVENT) {
|
|
return 0x16F;
|
|
}
|
|
|
|
if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_FUKUBIKI) {
|
|
return 0x150;
|
|
}
|
|
|
|
return 0x25;
|
|
}
|
|
|
|
case SCENE_DEPART_2:
|
|
{
|
|
if (Common_Get(tanuki_shop_status) == mSP_TANUKI_SHOP_STATUS_EVENT) {
|
|
if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_FURNITURE) {
|
|
mSP_what_special_sale = mSP_KIND_FURNITURE;
|
|
return 0x170;
|
|
}
|
|
|
|
if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_CLOTH) {
|
|
mSP_what_special_sale = mSP_KIND_CLOTH;
|
|
return 0x173;
|
|
}
|
|
|
|
if (Save_Get(event_save_data).special.event.bargin.kind == mSP_KIND_WALLPAPER) {
|
|
mSP_what_special_sale = mSP_KIND_WALLPAPER;
|
|
return 0x172;
|
|
}
|
|
|
|
mSP_what_special_sale = mSP_KIND_CARPET;
|
|
return 0x171;
|
|
}
|
|
|
|
return 0x26;
|
|
}
|
|
|
|
default:
|
|
return 0x25;
|
|
}
|
|
}
|
|
|
|
extern lbRTC_hour_t mSP_GetShopOpenTime() {
|
|
static lbRTC_hour_t shop_open_time_table[mSP_SHOP_TYPE_NUM] = {
|
|
9,
|
|
7,
|
|
9,
|
|
9
|
|
};
|
|
|
|
int shop_level = mSP_GetShopLevel();
|
|
|
|
if (Common_Get(time.rtc_time).day == lbRTC_GetDaysByMonth(Common_Get(time.rtc_time).year, Common_Get(time.rtc_time).month)) {
|
|
return 10; // lottery starts at 10AM
|
|
}
|
|
else {
|
|
return shop_open_time_table[shop_level];
|
|
}
|
|
}
|
|
|
|
extern lbRTC_hour_t mSP_GetShopCloseTime() {
|
|
static lbRTC_hour_t shop_close_time_table[mSP_SHOP_TYPE_NUM] = {
|
|
22,
|
|
23,
|
|
22,
|
|
22
|
|
};
|
|
|
|
return shop_close_time_table[mSP_GetShopLevel()];
|
|
}
|
|
|
|
extern lbRTC_hour_t mSP_GetShopCloseTime_Bgm() {
|
|
static lbRTC_hour_t shop_close_time_table[mSP_SHOP_TYPE_NUM] = {
|
|
22,
|
|
23,
|
|
22,
|
|
22
|
|
};
|
|
|
|
return shop_close_time_table[mSP_GetShopLevel()];
|
|
}
|
|
|
|
extern int mSP_InRenewal() {
|
|
if (mEv_CheckEvent(mEv_SAVED_RENEWSHOP) == TRUE) {
|
|
lbRTC_time_c renew_time = Save_Get(shop).renewal_time;
|
|
lbRTC_time_c* rtc_time = Common_GetPointer(time.rtc_time);
|
|
|
|
lbRTC_Sub_DD(&renew_time, 1);
|
|
|
|
if (
|
|
lbRTC_IsOverTime(&renew_time, rtc_time) == lbRTC_OVER ||
|
|
lbRTC_IsEqualTime(rtc_time, &renew_time, lbRTC_CHECK_YEARS | lbRTC_CHECK_MONTHS | lbRTC_CHECK_DAYS) != FALSE
|
|
) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/* @unused size: 0xF0 */
|
|
// int mSP_CheckSpecialSalesSoldOut(...)
|
|
|
|
extern int mSP_ShopOpen() {
|
|
lbRTC_time_c rtc_time = Common_Get(time.rtc_time);
|
|
lbRTC_hour_t now_hour;
|
|
|
|
if (mEv_CheckFirstJob()) {
|
|
return mSP_SHOP_STATUS_OPEN; // shop is forcefully open during chores
|
|
}
|
|
|
|
if (mEv_CheckEvent(mEv_SPNPC_SHOP) == TRUE) {
|
|
lbRTC_time_c bargin_time = Save_Get(event_save_data).special.event.bargin.start_time;
|
|
|
|
if (bargin_time.day == rtc_time.day) {
|
|
lbRTC_time_c end_time = Save_Get(event_save_data).special.event.bargin.end_time;
|
|
lbRTC_time_c start_time_pre = bargin_time;
|
|
lbRTC_time_c end_time_post = end_time;
|
|
now_hour = rtc_time.hour;
|
|
|
|
lbRTC_Sub_hh(&start_time_pre, 1);
|
|
lbRTC_Add_hh(&end_time_post, 1);
|
|
|
|
if (now_hour >= mTM_FIELD_RENEW_HOUR && now_hour < mSP_GetShopOpenTime()) {
|
|
return mSP_SHOP_STATUS_PRE;
|
|
}
|
|
|
|
if (now_hour < mTM_FIELD_RENEW_HOUR || now_hour >= mSP_GetShopCloseTime()) {
|
|
return mSP_SHOP_STATUS_END;
|
|
}
|
|
|
|
if (lbRTC_IsOverTime(&start_time_pre, &rtc_time) == lbRTC_LESS) {
|
|
return mSP_SHOP_STATUS_OPEN;
|
|
}
|
|
|
|
if (lbRTC_IsOverTime(&bargin_time, &rtc_time) == lbRTC_LESS) {
|
|
return mSP_SHOP_STATUS_PREEVENT;
|
|
}
|
|
|
|
if (lbRTC_IsOverTime(&end_time, &rtc_time) == lbRTC_LESS) {
|
|
return mSP_SHOP_STATUS_OPENEVENT;
|
|
}
|
|
|
|
if (lbRTC_IsOverTime(&end_time_post, &rtc_time) == lbRTC_LESS) {
|
|
return mSP_SHOP_STATUS_ENDEVENT;
|
|
}
|
|
|
|
return mSP_SHOP_STATUS_OPEN;
|
|
}
|
|
}
|
|
|
|
now_hour = rtc_time.hour;
|
|
|
|
if (mSP_InRenewal() != FALSE) {
|
|
return mSP_SHOP_STATUS_RENEW;
|
|
}
|
|
|
|
if (now_hour >= mSP_GetShopOpenTime() && now_hour < mSP_GetShopCloseTime()) {
|
|
return mSP_SHOP_STATUS_OPEN;
|
|
}
|
|
|
|
if (now_hour >= mTM_FIELD_RENEW_HOUR && now_hour < mSP_GetShopOpenTime()) {
|
|
return mSP_SHOP_STATUS_PRE;
|
|
}
|
|
|
|
return mSP_SHOP_STATUS_END;
|
|
}
|
|
|
|
extern void mSP_RandomHaniwaSelect(mActor_name_t* haniwa_list, int count) {
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
haniwa_list[i] = EMPTY_NO;
|
|
}
|
|
|
|
for (i = 0; i < count; i++) {
|
|
int set = FALSE;
|
|
|
|
while (!set) {
|
|
mActor_name_t haniwa = HANIWA_START + (mActor_name_t)FTR_NO_2_IDX(RANDOM(HANIWA_NUM));
|
|
|
|
if (mSP_GoodsExistAlready(haniwa_list, count, haniwa) == FALSE) {
|
|
haniwa_list[i] = haniwa;
|
|
set = TRUE;
|
|
}
|
|
else if (count > HANIWA_NUM) {
|
|
haniwa_list[i] = haniwa;
|
|
set = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void mSP_RandomMDSelect(mActor_name_t* md_list, int count) {
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
md_list[i] = EMPTY_NO;
|
|
}
|
|
|
|
for (i = 0; i < count; i++) {
|
|
int set = FALSE;
|
|
|
|
while (!set) {
|
|
mActor_name_t md = ITM_MINIDISK_START + RANDOM(NOT_SECRET_MD_NUM);
|
|
|
|
if (mSP_GoodsExistAlready(md_list, count, md) == FALSE) {
|
|
md_list[i] = md;
|
|
set = TRUE;
|
|
}
|
|
else if (count > NOT_SECRET_MD_NUM) {
|
|
md_list[i] = md;
|
|
set = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extern void mSP_RandomUmbSelect(mActor_name_t* umb_list, int count) {
|
|
int i;
|
|
|
|
for (i = 0; i < count; i++) {
|
|
umb_list[i] = EMPTY_NO;
|
|
}
|
|
|
|
for (i = 0; i < count; i++) {
|
|
int set = FALSE;
|
|
|
|
while (!set) {
|
|
mActor_name_t umb = ITM_UMBRELLA00 + RANDOM(UMBRELLA_NUM);
|
|
|
|
if (mSP_GoodsExistAlready(umb_list, count, umb) == FALSE) {
|
|
umb_list[i] = umb;
|
|
set = TRUE;
|
|
}
|
|
else if (count > UMBRELLA_NUM) {
|
|
umb_list[i] = umb;
|
|
set = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int mSP_CountBirth(u8 birth_type) {
|
|
int count = 0;
|
|
u8* birth_type_p = mRmTp_CheckFtrBirthInfoTop();
|
|
int i;
|
|
|
|
for (i = 0; i < FTR_NUM; i++) {
|
|
if (birth_type_p[0] == birth_type) {
|
|
count++;
|
|
}
|
|
|
|
birth_type_p++;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
static mActor_name_t mSP_FtrBirthIdx2ItemNo(u8 birth_type, int birth_idx) {
|
|
int count = 0;
|
|
u8* birth_type_p = mRmTp_CheckFtrBirthInfoTop();
|
|
int i;
|
|
|
|
for (i = 0; i < FTR_NUM; i++) {
|
|
if (birth_type_p[0] == birth_type) {
|
|
if (count == birth_idx) {
|
|
return mRmTp_FtrIdx2FtrItemNo(i, mRmTp_DIRECT_SOUTH);
|
|
}
|
|
|
|
count++;
|
|
}
|
|
|
|
birth_type_p++;
|
|
}
|
|
|
|
return FTR_DINO_TREX_SKULL;
|
|
}
|
|
|
|
extern mActor_name_t mSP_RandomOneFossilSelect(int multi_fossil) {
|
|
u8 birth_type = multi_fossil == FALSE ? mRmTp_BIRTH_TYPE_SINGLE_FOSSIL : mRmTp_BIRTH_TYPE_MULTI_FOSSIL;
|
|
int count = mSP_CountBirth(birth_type);
|
|
|
|
return mSP_FtrBirthIdx2ItemNo(birth_type, RANDOM(count));
|
|
}
|
|
|
|
extern int mSP_Chk_HukubukuroSail() {
|
|
lbRTC_time_c rtc_time = Common_Get(time.rtc_time);
|
|
lbRTC_year_t year = rtc_time.year;
|
|
lbRTC_month_t month = rtc_time.month;
|
|
lbRTC_day_t day = rtc_time.day;
|
|
|
|
if (month == lbRTC_NOVEMBER) {
|
|
int black_friday = lbRTC_Weekly_day(year, lbRTC_NOVEMBER, 4, lbRTC_THURSDAY) + 1;
|
|
|
|
if (black_friday == day) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern int mSP_CheckFukubikiDay() {
|
|
lbRTC_time_c rtc_time = Common_Get(time.rtc_time);
|
|
lbRTC_year_t year = rtc_time.year;
|
|
lbRTC_month_t month = rtc_time.month;
|
|
lbRTC_day_t day = rtc_time.day;
|
|
lbRTC_day_t days_in_month = lbRTC_GetDaysByMonth(year, month);
|
|
|
|
return days_in_month == day;
|
|
}
|
|
|
|
extern int mSP_SetGoods2ReservedPoint(mActor_name_t goods, mActor_name_t reserved_no) {
|
|
mActor_name_t* shop_fg = mFI_BkNumtoUtFGTop(0, 0);
|
|
int i;
|
|
|
|
for (i = 0; i < UT_TOTAL_NUM; i++) {
|
|
if (reserved_no == shop_fg[0]) {
|
|
mFI_UtNumtoFGSet_common(goods, i % UT_X_NUM, i / UT_X_NUM, FALSE);
|
|
return TRUE;
|
|
}
|
|
|
|
shop_fg++;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern int mSP_CheckHallowinDay() {
|
|
int res = FALSE;
|
|
lbRTC_time_c rtc_time = Common_Get(time.rtc_time);
|
|
lbRTC_month_t month = rtc_time.month;
|
|
lbRTC_day_t day = rtc_time.day;
|
|
|
|
if (
|
|
month == lbRTC_OCTOBER &&
|
|
day >= 16 &&
|
|
day <= 30
|
|
) {
|
|
res = TRUE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
extern void mSP_SetTanukiShopStatus() {
|
|
if (mSP_ShopOpen() == mSP_SHOP_STATUS_OPENEVENT) {
|
|
Common_Set(tanuki_shop_status, mSP_TANUKI_SHOP_STATUS_EVENT);
|
|
}
|
|
else if (mSP_CheckFukubikiDay()) {
|
|
Common_Set(tanuki_shop_status, mSP_TANUKI_SHOP_STATUS_FUKUBIKI);
|
|
}
|
|
else if (mSP_Chk_HukubukuroSail()) {
|
|
Common_Set(tanuki_shop_status, mSP_TANUKI_SHOP_STATUS_HUKUBUKURO_SALE);
|
|
}
|
|
else if (mSP_CheckHallowinDay()) {
|
|
Common_Set(tanuki_shop_status, mSP_TANUKI_SHOP_STATUS_HALLOWEEN);
|
|
}
|
|
else {
|
|
Common_Set(tanuki_shop_status, mSP_TANUKI_SHOP_STATUS_NORMAL);
|
|
}
|
|
}
|
|
|
|
static u32 mSP_sack_amount[MONEY_NUM] = {
|
|
100,
|
|
1000,
|
|
10000,
|
|
30000
|
|
};
|
|
|
|
static mActor_name_t mSP_itemNo[MONEY_NUM] = {
|
|
ITM_MONEY_100,
|
|
ITM_MONEY_1000,
|
|
ITM_MONEY_10000,
|
|
ITM_MONEY_30000
|
|
};
|
|
|
|
extern int mSP_money_check(u32 amount) {
|
|
u32 money = Common_Get(now_private)->inventory.wallet;
|
|
int res = FALSE;
|
|
|
|
if (money < amount) {
|
|
int i;
|
|
|
|
for (i = 0; i < MONEY_NUM; i++) {
|
|
int sack_num = mPr_GetPossessionItemSumWithCond(Common_Get(now_private), mSP_itemNo[i], mPr_ITEM_COND_NORMAL);
|
|
|
|
money += sack_num * mSP_sack_amount[i];
|
|
if (money >= amount) {
|
|
res = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
res = TRUE;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static u32 mSP_get_sell_price_sub(u32 money, u32 amount) {
|
|
u32 sack_num;
|
|
int i;
|
|
|
|
for (i = 0; i < MONEY_NUM; i++) {
|
|
for (sack_num = mPr_GetPossessionItemSumWithCond(Common_Get(now_private), mSP_itemNo[i], mPr_ITEM_COND_NORMAL); sack_num != 0; sack_num--) {
|
|
int sack_idx = mPr_GetPossessionItemIdxWithCond(Common_Get(now_private), mSP_itemNo[i], mPr_ITEM_COND_NORMAL);
|
|
|
|
mPr_SetPossessionItem(Common_Get(now_private), sack_idx, EMPTY_NO, mPr_ITEM_COND_NORMAL);
|
|
money += mSP_sack_amount[i];
|
|
|
|
if (money >= amount) {
|
|
return money - amount;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
extern void mSP_get_sell_price(u32 amount) {
|
|
u32 money = Common_Get(now_private)->inventory.wallet;
|
|
|
|
if (money < amount) {
|
|
money = mSP_get_sell_price_sub(money, amount);
|
|
}
|
|
else {
|
|
money -= amount;
|
|
}
|
|
|
|
Common_Get(now_private)->inventory.wallet = money;
|
|
}
|
|
|
|
static int mSP_GetNonePossessionItemCount_InList(mActor_name_t* list, int category, u32* collect_bitfield) {
|
|
mActor_name_t* list_p;
|
|
|
|
if (list != NULL) {
|
|
int count = 0;
|
|
|
|
for (list_p = list; list_p[0] != EMPTY_NO; list_p++) {
|
|
int collect_idx;
|
|
|
|
if (category == mSP_KIND_FURNITURE) {
|
|
collect_idx = mRmTp_FtrItemNo2FtrIdx(list_p[0]);
|
|
}
|
|
else if (category == mSP_KIND_CARPET) {
|
|
collect_idx = list_p[0] - ITM_CARPET_START;
|
|
}
|
|
else {
|
|
collect_idx = list_p[0] - ITM_WALL_START;
|
|
}
|
|
|
|
if (((collect_bitfield[collect_idx >> 5] >> (collect_idx & 0x1F)) & 1) == 0) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static mActor_name_t mSP_GetNonePossessionItem_InList(mActor_name_t* list, int category, u32* collect_bitfield) {
|
|
int none_count = mSP_GetNonePossessionItemCount_InList(list, category, collect_bitfield);
|
|
|
|
if (none_count != 0 && list != NULL) {
|
|
int selected_idx = RANDOM(none_count);
|
|
mActor_name_t* list_p;
|
|
int count = 0;
|
|
|
|
for (list_p = list; list_p[0] != EMPTY_NO; list_p++) {
|
|
int collect_idx;
|
|
|
|
if (category == mSP_KIND_FURNITURE) {
|
|
collect_idx = mRmTp_FtrItemNo2FtrIdx(list_p[0]);
|
|
}
|
|
else if (category == mSP_KIND_CARPET) {
|
|
collect_idx = list_p[0] - ITM_CARPET_START;
|
|
}
|
|
else {
|
|
collect_idx = list_p[0] - ITM_WALL_START;
|
|
}
|
|
|
|
if (((collect_bitfield[collect_idx >> 5] >> (collect_idx & 0x1F)) & 1) == 0) {
|
|
if (selected_idx == count) {
|
|
return list_p[0];
|
|
}
|
|
else {
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return EMPTY_NO;
|
|
}
|
|
|
|
static mActor_name_t mSP_GetNonePossessionItem_InLotteryFurniture(int player_no) {
|
|
return mSP_GetNonePossessionItem_InList(
|
|
mSP_ftr_list[mSP_LIST_LOTTERY],
|
|
mSP_KIND_FURNITURE,
|
|
(player_no >= 0 && player_no < PLAYER_NUM) ?
|
|
Save_Get(private[player_no]).furniture_collected_bitfield :
|
|
Common_Get(now_private)->furniture_collected_bitfield
|
|
);
|
|
}
|
|
|
|
static mActor_name_t mSP_GetNonePossessionItem_InEventFurniture(int player_no) {
|
|
return mSP_GetNonePossessionItem_InList(
|
|
mSP_ftr_list[mSP_LIST_EVENT],
|
|
mSP_KIND_FURNITURE,
|
|
(player_no >= 0 && player_no < PLAYER_NUM) ?
|
|
Save_Get(private[player_no]).furniture_collected_bitfield :
|
|
Common_Get(now_private)->furniture_collected_bitfield
|
|
);
|
|
}
|
|
|
|
/* @fabricated @unused */
|
|
static mActor_name_t mSP_GetNonePossessionItem_InEventWall(int player_no) {
|
|
return mSP_GetNonePossessionItem_InList(
|
|
mSP_ftr_list[mSP_LIST_EVENT],
|
|
mSP_KIND_WALLPAPER,
|
|
(player_no >= 0 && player_no < PLAYER_NUM) ?
|
|
Save_Get(private[player_no]).wall_collected_bitfield :
|
|
Common_Get(now_private)->wall_collected_bitfield
|
|
);
|
|
}
|
|
|
|
/* @fabricated @unused */
|
|
static mActor_name_t mSP_GetNonePossessionItem_InEventCarpet(int player_no) {
|
|
return mSP_GetNonePossessionItem_InList(
|
|
mSP_ftr_list[mSP_LIST_EVENT],
|
|
mSP_KIND_CARPET,
|
|
(player_no >= 0 && player_no < PLAYER_NUM) ?
|
|
Save_Get(private[player_no]).carpet_collected_bitfield :
|
|
Common_Get(now_private)->carpet_collected_bitfield
|
|
);
|
|
}
|
|
|
|
/* @fabricated @unused */
|
|
static mActor_name_t mSP_GetNonePossessionItem_InABCFurniture(int player_no) {
|
|
// TODO: check this impl is right using func size -- they probably did the list calc in this func itself
|
|
u8 abc_priorities[3];
|
|
|
|
mSP_GetGoodsPriority(abc_priorities, mSP_KIND_FURNITURE);
|
|
|
|
return mSP_GetNonePossessionItem_InList(
|
|
mSP_GetItemList(mSP_ftr_list, abc_priorities, mSP_LISTTYPE_ABC),
|
|
mSP_KIND_FURNITURE,
|
|
(player_no >= 0 && player_no < PLAYER_NUM) ?
|
|
Save_Get(private[player_no]).furniture_collected_bitfield :
|
|
Common_Get(now_private)->furniture_collected_bitfield
|
|
);
|
|
}
|
|
|
|
typedef mActor_name_t (*mSP_GET_NONE_POSSESSION_ITEM_PROC)(int);
|
|
|
|
static mActor_name_t mSP_CarryOutAlternativeRandomSelect(mSP_GET_NONE_POSSESSION_ITEM_PROC proc0, mSP_GET_NONE_POSSESSION_ITEM_PROC proc1, int player_no) {
|
|
int rng = RANDOM(100);
|
|
|
|
if ((rng & 1)) {
|
|
mActor_name_t item = (*proc0)(player_no);
|
|
|
|
if (item == EMPTY_NO) {
|
|
item = (*proc1)(player_no);
|
|
|
|
if (item != EMPTY_NO) {
|
|
return item;
|
|
}
|
|
}
|
|
else {
|
|
return item;
|
|
}
|
|
}
|
|
else {
|
|
mActor_name_t item = (*proc1)(player_no);
|
|
|
|
if (item == EMPTY_NO) {
|
|
item = (*proc0)(player_no);
|
|
|
|
if (item != EMPTY_NO) {
|
|
return item;
|
|
}
|
|
}
|
|
else {
|
|
return item;
|
|
}
|
|
}
|
|
|
|
return EMPTY_NO;
|
|
}
|
|
|
|
static mActor_name_t mSP_CarryOutAlternativeRandomSelect_NoneNULL(int category0, int list0, int category1, int list1) {
|
|
int rng = RANDOM(100);
|
|
mActor_name_t item;
|
|
|
|
if ((rng & 1)) {
|
|
mSP_SelectRandomItem_New(NULL, &item, 1, NULL, 0, category0, list0, FALSE);
|
|
return item;
|
|
}
|
|
else {
|
|
mSP_SelectRandomItem_New(NULL, &item, 1, NULL, 0, category1, list1, FALSE);
|
|
return item;
|
|
}
|
|
}
|
|
|
|
/* @unused size: 0xB8 */
|
|
// extern mActor_name_t mSP_SelectNpcBirthdayPresent(...)
|
|
static void mSP_SelectNpcBirthdayPresent() {
|
|
// necessary to include for data
|
|
static int priority[6][3] = {
|
|
{ mSP_PRIORITY_COMMON, mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_RARE },
|
|
{ mSP_PRIORITY_COMMON, mSP_PRIORITY_RARE, mSP_PRIORITY_RARE }, // lol based on this, I think it should've been common, rare, uncommon
|
|
{ mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_COMMON, mSP_PRIORITY_RARE },
|
|
{ mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_RARE, mSP_PRIORITY_COMMON },
|
|
{ mSP_PRIORITY_RARE, mSP_PRIORITY_COMMON, mSP_PRIORITY_UNCOMMON },
|
|
{ mSP_PRIORITY_RARE, mSP_PRIORITY_UNCOMMON, mSP_PRIORITY_COMMON }
|
|
};
|
|
}
|
|
|
|
extern mActor_name_t mSP_SelectFishginPresent(int player_no) {
|
|
mActor_name_t item = mSP_CarryOutAlternativeRandomSelect(&mSP_GetNonePossessionItem_InLotteryFurniture, &mSP_GetNonePossessionItem_InEventFurniture, player_no);
|
|
|
|
if (item != EMPTY_NO) {
|
|
return item;
|
|
}
|
|
|
|
return mSP_CarryOutAlternativeRandomSelect_NoneNULL(mSP_KIND_FURNITURE, mSP_LISTTYPE_LOTTERY, mSP_KIND_FURNITURE, mSP_LISTTYPE_EVENT);
|
|
}
|
|
|
|
mActor_name_t mSP_gc_famicom_table[8] = {
|
|
FTR_FAMICOM_CLU_CLU_LAND,
|
|
FTR_FAMICOM_BALLOON_FIGHT,
|
|
FTR_FAMICOM_DONKEY_KONG,
|
|
FTR_FAMICOM_DK_JR_MATCH,
|
|
FTR_FAMICOM_PINBALL,
|
|
FTR_FAMICOM_TENNIS,
|
|
FTR_FAMICOM_GOLF,
|
|
FTR_FAMICOM_EXCITEBIKE
|
|
};
|
|
|
|
/* @unused size: 0xDC */
|
|
// static mActor_name_t mSP_RandomOneFamicomSelect(...)
|
|
|
|
static mActor_name_t mSP_AGBRandomFamicomSelect() {
|
|
mActor_name_t item = EMPTY_NO;
|
|
|
|
mSP_SelectRandomItem_New(NULL, &item, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_ISLANDFAMICOM, FALSE);
|
|
return item;
|
|
}
|
|
|
|
static mActor_name_t mSP_GetRandomTrash() {
|
|
static mActor_name_t trash_table[3] = { ITM_DUST0_EMPTY_CAN, ITM_DUST1_BOOT, ITM_DUST2_OLD_TIRE };
|
|
|
|
return trash_table[RANDOM(3)];
|
|
}
|
|
|
|
static void mSP_SelectRandomItemToAGB_Unit(mActor_name_t* item, xyz_t* wpos, int ut_x, int ut_z) {
|
|
switch (item[0]) {
|
|
case 0xFEB2:
|
|
{
|
|
item[0] = mSP_GetRandomTrash();
|
|
break;
|
|
}
|
|
|
|
case 0xFEA1:
|
|
{
|
|
mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_COMMON, FALSE);
|
|
break;
|
|
}
|
|
|
|
case 0xFEA2:
|
|
{
|
|
mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_RARE, FALSE);
|
|
break;
|
|
}
|
|
|
|
case 0xFEA3:
|
|
{
|
|
if ((RANDOM(10) & 1)) {
|
|
mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_EVENT, FALSE);
|
|
}
|
|
else {
|
|
mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_LOTTERY, FALSE);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 0xFEA5:
|
|
{
|
|
mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_FURNITURE, mSP_LISTTYPE_ISLAND, FALSE);
|
|
break;
|
|
}
|
|
|
|
case 0xFEA4:
|
|
{
|
|
item[0] = mSP_AGBRandomFamicomSelect();
|
|
break;
|
|
}
|
|
|
|
case 0xFEA9:
|
|
{
|
|
mSP_RandomUmbSelect(item, 1);
|
|
break;
|
|
}
|
|
|
|
case 0xFEA6:
|
|
{
|
|
item[0] = mSP_RandomOneFossilSelect((RANDOM(4) & 1));
|
|
break;
|
|
}
|
|
|
|
case 0xFEA7:
|
|
{
|
|
mSP_RandomMDSelect(item, 1);
|
|
break;
|
|
}
|
|
|
|
case 0xFEA8:
|
|
{
|
|
mSP_RandomHaniwaSelect(item, 1);
|
|
break;
|
|
}
|
|
|
|
case 0xFEAA:
|
|
{
|
|
mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_CARPET, mSP_LISTTYPE_COMMON, FALSE);
|
|
break;
|
|
}
|
|
|
|
case 0xFEAB:
|
|
{
|
|
mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_CARPET, mSP_LISTTYPE_RARE, FALSE);
|
|
break;
|
|
}
|
|
|
|
case 0xFEAC:
|
|
{
|
|
mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_WALLPAPER, mSP_LISTTYPE_COMMON, FALSE);
|
|
break;
|
|
}
|
|
|
|
case 0xFEAD:
|
|
{
|
|
mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_WALLPAPER, mSP_LISTTYPE_RARE, FALSE);
|
|
break;
|
|
}
|
|
|
|
case 0xFEAE:
|
|
{
|
|
mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_CLOTH, mSP_LISTTYPE_COMMON, FALSE);
|
|
break;
|
|
}
|
|
|
|
case 0xFEAF:
|
|
{
|
|
mSP_SelectRandomItem_New(NULL, item, 1, NULL, 0, mSP_KIND_CLOTH, mSP_LISTTYPE_RARE, FALSE);
|
|
break;
|
|
}
|
|
|
|
case 0xFEB0:
|
|
{
|
|
int hole_no = mCoBG_GetHoleNumber(*wpos);
|
|
|
|
if (hole_no != -1) {
|
|
item[0] = HOLE_START + (mActor_name_t)hole_no;
|
|
}
|
|
else {
|
|
item[0] = EMPTY_NO;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 0xFEB1:
|
|
{
|
|
item[0] = ITM_WHITE_PANSY_BAG + RANDOM(FLOWER_NUM);
|
|
break;
|
|
}
|
|
|
|
case ITM_KABU_10:
|
|
case ITM_KABU_50:
|
|
case ITM_KABU_100:
|
|
{
|
|
item[0] = ITM_KABU_SPOILED; // spoil any turnips
|
|
break;
|
|
}
|
|
|
|
case 0xF11F:
|
|
{
|
|
item[0] = ACTOR_PROP_VILLAGER_SIGNBOARD;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef MUST_MATCH
|
|
/* @nonmatching - minor float load/store issue with xyz_t.z & weird scheduling issue */
|
|
extern void mSP_SelectRandomItemToAGB() {
|
|
int i;
|
|
int ut_x;
|
|
int ut_z;
|
|
xyz_t* wpos_p;
|
|
mActor_name_t* start_p;
|
|
mActor_name_t* item_p;
|
|
f32 x_pos;
|
|
|
|
xyz_t wpos = { 0.0f, 0.0f, 0.0f };
|
|
int bx = 0;
|
|
int bz = 0;
|
|
|
|
mFI_BlockKind2BkNum(&bx, &bz, mRF_BLOCKKIND_ISLAND_LEFT);
|
|
|
|
/* convert all unit island items to valid items */
|
|
for (i = 0; i < mISL_FG_BLOCK_X_NUM; i++) {
|
|
item_p = &Save_Get(island).fgblock[0][i].items[0][0];
|
|
|
|
mFI_BkNum2WposXZ(&wpos.x, &wpos.z, bx + i, bz);
|
|
wpos.x += mFI_UT_WORLDSIZE_HALF_X_F;
|
|
wpos.z += mFI_UT_WORLDSIZE_HALF_Z_F;
|
|
x_pos = wpos.x;
|
|
|
|
for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) {
|
|
wpos.x = x_pos;
|
|
|
|
for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) {
|
|
// this matches instructions but out of order and wrong registers
|
|
mSP_SelectRandomItemToAGB_Unit(item_p, &wpos, ut_x, ut_z);
|
|
wpos.x += mFI_UT_WORLDSIZE_X_F;
|
|
item_p++;
|
|
}
|
|
|
|
wpos.z += mFI_UT_WORLDSIZE_Z_F;
|
|
}
|
|
}
|
|
|
|
/* add correctly placed signboard actor */
|
|
for (i = 0; i < mISL_FG_BLOCK_X_NUM; i++) {
|
|
start_p = &Save_Get(island).fgblock[0][i].items[0][0];
|
|
item_p = &Save_Get(island).fgblock[0][i].items[0][0];
|
|
|
|
for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) {
|
|
for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) {
|
|
if (item_p[0] == COTTAGE_NPC) {
|
|
start_p[((ut_x - 1) & 15) + (((ut_z + 1) & 0xF) << 4)] = ACTOR_PROP_VILLAGER_SIGNBOARD;
|
|
}
|
|
|
|
item_p++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* remove incorrectly placed signboard actors */
|
|
for (i = 0; i < mISL_FG_BLOCK_X_NUM; i++) {
|
|
start_p = &Save_Get(island).fgblock[0][i].items[0][0];
|
|
item_p = &Save_Get(island).fgblock[0][i].items[0][0];
|
|
|
|
for (ut_z = 0; ut_z < UT_Z_NUM; ut_z++) {
|
|
for (ut_x = 0; ut_x < UT_X_NUM; ut_x++) {
|
|
if (item_p[0] == ACTOR_PROP_VILLAGER_SIGNBOARD && start_p[((ut_x + 1) & 15) + (((ut_z - 1) & 0xF) << 4)] != COTTAGE_NPC) {
|
|
item_p[0] = EMPTY_NO;
|
|
}
|
|
|
|
item_p++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
const xyz_t lbl_806432b4 = {0.0f, 0.0f, 0.0f};
|
|
REL_SYMBOL_AT(lbl_806432b4, 0x806432b4)
|
|
|
|
#include "orderfloats/806432c0_806432c8.inc"
|
|
|
|
extern asm void mSP_SelectRandomItemToAGB() {
|
|
#include "asm/803ebb44.s"
|
|
}
|
|
#endif
|
|
|
|
extern const char* mSP_ShopStatus2String(int status) {
|
|
static char dummy[] = "hahaha";
|
|
|
|
static char* str_table[mSP_SHOP_STATUS_NUM] = {
|
|
"Pre",
|
|
"End",
|
|
"Opn",
|
|
"Rnw",
|
|
"PreEv",
|
|
"EndEv",
|
|
"OpnEv"
|
|
};
|
|
|
|
if (status >= 0 && status < mSP_SHOP_STATUS_NUM) {
|
|
return str_table[status];
|
|
}
|
|
|
|
return dummy;
|
|
}
|
|
|
|
extern mActor_name_t mSP_GetRandomStationToyItemNo() {
|
|
/* TODO: where does this go? DnM+ indicates no unused functions after this, but data appears after str_table in mSP_ShopStatus2String */
|
|
static mActor_name_t train[2] = {
|
|
FTR_LOCOMOTIVE_MODEL, FTR_TRAIN_CAR_MODEL
|
|
};
|
|
|
|
/* TODO: furniture item index enum/defines */
|
|
return mRmTp_FtrIdx2FtrItemNo(0x42A + RANDOM(15), mRmTp_DIRECT_SOUTH);
|
|
}
|
|
|
|
#include "../src/m_item_debug.c"
|