Files
ac-decomp/src/m_shop.c
T
2024-01-17 13:18:25 -05:00

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"