papermario/src/world/script_api/shops.c

989 lines
37 KiB
C

#include "common.h"
#include "message_ids.h"
#include "hud_element.h"
#include "model.h"
#include "pause/pause_common.h"
#if !VERSION_JP
extern u8 MessagePlural[];
extern u8 MessageSingular[];
#endif
#if VERSION_PAL
extern u8 MessagePlural_de[];
#endif
extern HudScript HES_Item_Coin;
s32 shop_get_sell_price(s32 itemID);
API_CALLABLE(CanInteractWithShopItem);
API_CALLABLE(BeginShopItemInteraction);
API_CALLABLE(ShowShopPurchaseDialog);
API_CALLABLE(ShowShopOwnerDialog);
EvtScript EVS_ShopBeginSpeech = {
Call(SpeakToPlayer, LVar1, LVar2, LVar3, 0, LVar0)
Return
End
};
EvtScript EVS_ShopContinueSpeech = {
Call(ContinueSpeech, LVar1, LVar2, LVar3, 0, LVar0)
Return
End
};
EvtScript EVS_ShopResetSpeech = {
Call(EndSpeech, LVar1, LVar2, LVar3, 0)
Call(SpeakToPlayer, LVar1, LVar2, LVar3, 0, LVar0)
Return
End
};
EvtScript EVS_ShopEndSpeech = {
Call(EndSpeech, LVar0, LVar1, LVar2, 0)
Return
End
};
EvtScript EVS_ShopItemInteract = {
Call(GetPartnerInUse, LVar1)
IfEq(LVar1, PARTNER_NONE)
Goto(10)
EndIf
IfEq(LVar1, PARTNER_KOOPER)
Goto(10)
EndIf
IfEq(LVar1, PARTNER_BOMBETTE)
Goto(10)
EndIf
Return
Label(10)
Call(CanInteractWithShopItem)
IfFalse(LVar2)
Return
EndIf
Call(BeginShopItemInteraction, LVar0)
Return
End
};
EvtScript EVS_ShopPurchaseDialog = {
Call(ShowShopPurchaseDialog, LVar0)
Return
End
};
EvtScript EVS_ShopOwnerDialog = {
Call(ShowShopOwnerDialog)
Return
End
};
s32 shop_owner_begin_speech(s32 messageIndex) {
Shop* shop = gGameStatusPtr->mapShop;
s32 shopMsgID = shop->owner->shopMsgIDs[messageIndex];
Evt* script = start_script(&EVS_ShopBeginSpeech, EVT_PRIORITY_1, 0);
script->varTable[0] = shopMsgID;
script->varTable[1] = shop->owner->npcID;
script->varTable[2] = shop->owner->talkAnim;
script->varTable[3] = shop->owner->idleAnim;
return script->id;
}
s32 shop_owner_buy_dialog(s32 messageIndex, s32 itemName, s32 coinCost, s32 bpCost) {
Shop* shop = gGameStatusPtr->mapShop;
s32 shopMsgID = shop->owner->shopMsgIDs[messageIndex];
Evt* script;
u8* suffix;
set_message_text_var(itemName, 0);
set_message_int_var(coinCost, 1);
if (bpCost > 0) {
set_message_int_var(bpCost, 2);
#if !VERSION_JP
} else {
#if VERSION_PAL
if (gCurrentLanguage == 1) {
suffix = MessagePlural_de;
} else {
suffix = MessagePlural;
}
if (coinCost == 1) {
suffix = MessageSingular;
}
#else
if (coinCost == 1) {
suffix = MessageSingular;
} else {
suffix = MessagePlural;
}
#endif
set_message_text_var((s32) suffix, 2);
#endif
}
script = start_script(&EVS_ShopBeginSpeech, EVT_PRIORITY_1, 0);
script->varTable[0] = shopMsgID;
script->varTable[1] = shop->owner->npcID;
script->varTable[2] = shop->owner->talkAnim;
script->varTable[3] = shop->owner->idleAnim;
return script->id;
}
s32 shop_owner_continue_speech(s32 messageIndex) {
Shop* shop = gGameStatusPtr->mapShop;
s32 shopMsgID = shop->owner->shopMsgIDs[messageIndex];
Evt* script = start_script(&EVS_ShopContinueSpeech, EVT_PRIORITY_1, 0);
script->varTable[0] = shopMsgID;
script->varTable[1] = shop->owner->npcID;
script->varTable[2] = shop->owner->talkAnim;
script->functionTemp[3] = script->varTable[3] = shop->owner->idleAnim;
return script->id;
}
s32 shop_owner_continue_speech_with_quantity(s32 messageIndex, s32 amount) {
Shop* shop = gGameStatusPtr->mapShop;
s32 shopMsgID = shop->owner->shopMsgIDs[messageIndex];
u8* suffixMsg;
Evt* script;
set_message_int_var(amount, 0);
#if !VERSION_JP
if (amount == 1) {
suffixMsg = MessageSingular;
} else {
suffixMsg = MessagePlural;
}
set_message_text_var((s32) suffixMsg, 1);
#endif
script = start_script(&EVS_ShopContinueSpeech, EVT_PRIORITY_1, 0);
script->varTable[0] = shopMsgID;
script->varTable[1] = shop->owner->npcID;
script->varTable[2] = shop->owner->talkAnim;
script->functionTemp[3] = script->varTable[3] = shop->owner->idleAnim;
return script->id;
}
s32 shop_owner_reset_speech(s32 messageIndex) {
Shop* shop = gGameStatusPtr->mapShop;
s32 shopMsgID = shop->owner->shopMsgIDs[messageIndex];
Evt* script = start_script(&EVS_ShopResetSpeech, EVT_PRIORITY_1, 0);
script->varTable[0] = shopMsgID;
script->varTable[1] = shop->owner->npcID;
script->varTable[2] = shop->owner->talkAnim;
script->functionTemp[3] = script->varTable[3] = shop->owner->idleAnim;
return script->id;
}
s32 shop_owner_end_speech(void) {
Shop* shop = gGameStatusPtr->mapShop;
Evt* script = start_script(&EVS_ShopEndSpeech, EVT_PRIORITY_1, 0);
script->varTable[0] = shop->owner->npcID;
script->varTable[1] = shop->owner->talkAnim;
script->functionTemp[3] = script->varTable[2] = shop->owner->idleAnim;
return script->id;
}
API_CALLABLE(CanInteractWithShopItem) {
PlayerStatus* playerStatus = &gPlayerStatus;
script->varTable[2] = false;
if (playerStatus->actionState == ACTION_STATE_BOUNCE ||
playerStatus->actionState == ACTION_STATE_FALLING) {
return ApiStatus_DONE2;
}
if ((playerStatus->flags & PS_FLAG_PAUSE_DISABLED)) {
return ApiStatus_DONE2;
}
script->varTable[2] = true;
return ApiStatus_DONE2;
}
API_CALLABLE(BeginShopItemInteraction) {
static Evt* ShopInteractScript;
static s32 ShopInteractScriptID;
Shop* shop = gGameStatusPtr->mapShop;
s32 currentItemSlot = evt_get_variable(script, *script->ptrReadPos);
if (!(shop->flags & SHOP_FLAG_INTERACT_SCRIPT_RUNNING)) {
shop->curItemSlot = currentItemSlot;
shop->flags |= SHOP_FLAG_SHOWING_ITEM_INFO;
status_bar_always_show_on();
shop->unk_358 = 5;
if (gGameStatusPtr->pressedButtons[0] & BUTTON_A) {
Evt* childScript;
disable_player_input();
disable_player_static_collisions();
childScript = start_script(&EVS_ShopPurchaseDialog, EVT_PRIORITY_1, 0);
childScript->varTable[0] = currentItemSlot;
ShopInteractScript = childScript;
ShopInteractScriptID = childScript->id;
shop->flags |= SHOP_FLAG_INTERACT_SCRIPT_RUNNING;
return ApiStatus_BLOCK;
} else {
return ApiStatus_DONE2;
}
} else if (does_script_exist(ShopInteractScriptID)) {
return ApiStatus_BLOCK;
}
shop->flags &= ~SHOP_FLAG_INTERACT_SCRIPT_RUNNING;
enable_player_static_collisions();
enable_player_input();
return ApiStatus_DONE2;
}
enum PurchaseDialogState {
PURCHASE_DIALOG_STATE_INIT = 0,
PURCHASE_DIALOG_STATE_NOT_ENOUGH_COINS = 1,
PURCHASE_DIALOG_STATE_NOT_ENOUGH_ROOM = 4,
PURCHASE_DIALOG_STATE_ACCEPTED = 5,
PURCHASE_DIALOG_STATE_CANCEL = 6,
PURCHASE_DIALOG_STATE_EXEC_CALLBACK = 10,
PURCHASE_DIALOG_STATE_AWAIT_CALLBACK = 11,
PURCHASE_DIALOG_STATE_WAIT_FOR_SPEECH = 100,
};
API_CALLABLE(ShowShopPurchaseDialog) {
PlayerData* playerData = &gPlayerData;
s32 shopItemSlot = script->varTable[0];
Shop* shop = gGameStatusPtr->mapShop;
ShopItemData* shopInventory = &shop->staticInventory[shopItemSlot];
ItemData* shopItem = &gItemTable[shopInventory->itemID];
s32 bpCost;
static MessagePrintState* D_80286528;
static Evt* wShopBuyCallbackScript;
static s32 wShopSelectedItem;
static s32 wShopBuyResult;
// functionTemp[0] is PurchaseDialogState
// functionTemp[1] is speech script ID
// functionTempBool[2] is speech printer isClosed writeback
shop->flags &= ~SHOP_FLAG_SHOWING_ITEM_INFO;
status_bar_always_show_off();
if (isInitialCall) {
wShopSelectedItem = ITEM_NONE;
wShopBuyResult = SHOP_BUY_RESULT_NOT_ENOUGH_COINS;
bpCost = -1;
if (shopItem->typeFlags & ITEM_TYPE_FLAG_BADGE) {
bpCost = gMoveTable[shopItem->moveID].costBP;
}
script->functionTemp[1] = shop_owner_buy_dialog(SHOP_MSG_BUY_CONFIRM, shopItem->nameMsg, shopInventory->price, bpCost);
script->functionTemp[0] = PURCHASE_DIALOG_STATE_INIT;
increment_status_bar_disabled();
status_bar_always_show_off();
show_coin_counter();
}
switch (script->functionTemp[0]) {
case PURCHASE_DIALOG_STATE_INIT:
if (!does_script_exist(script->functionTemp[1])) {
script->functionTemp[0] = PURCHASE_DIALOG_STATE_WAIT_FOR_SPEECH;
script->functionTempBool[2] = false;
D_80286528 = msg_get_printer_for_msg(MSG_Choice_0001, &script->functionTempBool[2]);
}
break;
case PURCHASE_DIALOG_STATE_WAIT_FOR_SPEECH:
if (script->functionTempBool[2] == true) {
if (D_80286528->curOption == 0) {
if (playerData->coins < shopInventory->price) {
script->functionTemp[1] = shop_owner_continue_speech(SHOP_MSG_NOT_ENOUGH_COINS);
script->functionTemp[0] = PURCHASE_DIALOG_STATE_NOT_ENOUGH_COINS;
} else if (!IS_BADGE(shopInventory->itemID) && add_item(ITEM_NONE) == -1) {
script->functionTemp[1] = shop_owner_continue_speech(SHOP_MSG_NOT_ENOUGH_ROOM);
script->functionTemp[0] = PURCHASE_DIALOG_STATE_NOT_ENOUGH_ROOM;
} else {
playerData->coins -= shopInventory->price;
if (IS_BADGE(shopInventory->itemID)) {
add_badge(shopInventory->itemID);
evt_set_variable(NULL, GF_MAC01_BoughtBadgeFromRowf, true);
} else {
add_item(shopInventory->itemID);
}
script->functionTemp[1] = shop_owner_continue_speech(SHOP_MSG_BUY_THANK_YOU);
script->functionTemp[0] = PURCHASE_DIALOG_STATE_ACCEPTED;
}
} else {
script->functionTemp[1] = shop_owner_reset_speech(SHOP_MSG_FAREWELL);
script->functionTemp[0] = PURCHASE_DIALOG_STATE_CANCEL;
}
}
break;
case PURCHASE_DIALOG_STATE_NOT_ENOUGH_COINS:
if (!does_script_exist(script->functionTemp[1])) {
wShopBuyResult = SHOP_BUY_RESULT_NOT_ENOUGH_COINS;
wShopSelectedItem = shopInventory->itemID;
script->functionTemp[0] = PURCHASE_DIALOG_STATE_EXEC_CALLBACK;
}
break;
case PURCHASE_DIALOG_STATE_NOT_ENOUGH_ROOM:
if (!does_script_exist(script->functionTemp[1])) {
wShopBuyResult = SHOP_BUY_RESULT_NOT_ENOUGH_ROOM;
wShopSelectedItem = shopInventory->itemID;
script->functionTemp[0] = PURCHASE_DIALOG_STATE_EXEC_CALLBACK;
}
break;
case PURCHASE_DIALOG_STATE_ACCEPTED:
if (!does_script_exist(script->functionTemp[1])) {
wShopBuyResult = SHOP_BUY_RESULT_OK;
wShopSelectedItem = shopInventory->itemID;
script->functionTemp[0] = PURCHASE_DIALOG_STATE_EXEC_CALLBACK;
}
break;
case PURCHASE_DIALOG_STATE_CANCEL:
if (!does_script_exist(script->functionTemp[1])) {
wShopBuyResult = SHOP_BUY_RESULT_CANCEL;
wShopSelectedItem = shopInventory->itemID;
script->functionTemp[0] = PURCHASE_DIALOG_STATE_EXEC_CALLBACK;
}
break;
case PURCHASE_DIALOG_STATE_EXEC_CALLBACK:
wShopBuyCallbackScript = NULL;
if (shop->owner != NULL) {
if (shop->owner->onBuyEvt != NULL) {
wShopBuyCallbackScript = start_script(shop->owner->onBuyEvt, EVT_PRIORITY_1, 0);
wShopBuyCallbackScript->varTable[0] = wShopBuyResult;
wShopBuyCallbackScript->varTable[1] = wShopSelectedItem;
wShopBuyCallbackScript->varTable[2] = shopItemSlot;
}
}
script->functionTemp[0] = PURCHASE_DIALOG_STATE_AWAIT_CALLBACK;
break;
case PURCHASE_DIALOG_STATE_AWAIT_CALLBACK:
if (wShopBuyCallbackScript != NULL && does_script_exist(wShopBuyCallbackScript->id)) {
break;
}
decrement_status_bar_disabled();
hide_coin_counter_immediately();
return ApiStatus_DONE1;
}
return ApiStatus_BLOCK;
}
void create_shop_popup_menu(PopupMenu* popup);
void shop_open_item_select_popup(s32 mode) {
PopupMenu* menu = &gGameStatusPtr->mapShop->itemSelectMenu;
s32 numItemSlots;
s32 popupType;
s32 numEntries;
s32 itemID;
s32 i;
switch (mode) {
case 0:
popupType = POPUP_MENU_SELL_ITEM;
numItemSlots = ARRAY_COUNT(gPlayerData.invItems);
break;
case 1:
popupType = POPUP_MENU_CHECK_ITEM;
numItemSlots = ARRAY_COUNT(gPlayerData.invItems);
break;
default:
popupType = POPUP_MENU_CLAIM_ITEM;
numItemSlots = ARRAY_COUNT(gPlayerData.storedItems);
break;
}
numEntries = 0;
for (i = 0; i < numItemSlots; i++) {
ItemData* itemData;
switch (mode) {
case 0:
case 1:
itemID = gPlayerData.invItems[i];
if (itemID == ITEM_NONE) {
continue;
}
itemData = &gItemTable[itemID];
break;
default:
itemID = gPlayerData.storedItems[i];
if (itemID == ITEM_NONE) {
continue;
}
itemData = &gItemTable[itemID];
break;
}
menu->ptrIcon[numEntries] = gItemHudScripts[itemData->hudElemID].enabled;
menu->userIndex[numEntries] = i;
menu->enabled[numEntries] = true;
menu->nameMsg[numEntries] = itemData->nameMsg;
menu->descMsg[numEntries] = itemData->shortDescMsg;
menu->value[numEntries] = shop_get_sell_price(itemID);
numEntries++;
}
menu->popupType = popupType;
menu->numEntries = numEntries;
menu->initialPos = 0;
create_shop_popup_menu(menu);
status_bar_ignore_changes();
status_bar_always_show_on();
open_status_bar_quickly();
}
s32 shop_update_item_select_popup(s32* selectedIndex) {
Shop* shop = gGameStatusPtr->mapShop;
PopupMenu* menu = &shop->itemSelectMenu;
s16 menuResult = shop->itemSelectMenu.result;
if (menuResult == POPUP_RESULT_CHOOSING) {
return 0;
}
hide_popup_menu();
if (menuResult == POPUP_RESULT_CANCEL) {
*selectedIndex = -1;
} else {
*selectedIndex = menu->userIndex[menuResult - 1];
}
return 1;
}
void shop_close_item_select_popup(void) {
destroy_popup_menu();
status_bar_always_show_off();
status_bar_respond_to_changes();
close_status_bar();
}
s32 shop_get_sell_price(s32 itemID) {
Shop* shop = gGameStatusPtr->mapShop;
s32 numItems = shop->numSpecialPrices;
ShopSellPriceData* items = shop->staticPriceList;
s32 i;
if (shop != NULL) {
i = 0;
} // TODO fake match
for (i = 0; i < numItems; i++) {
if (items[i].itemID == itemID) {
return items[i].sellPrice;
}
}
return gItemTable[itemID].sellValue;
}
API_CALLABLE(ShowShopOwnerDialog) {
GameStatus* gameStatus = gGameStatusPtr;
PlayerData* playerData = &gPlayerData;
Shop* shop = gameStatus->mapShop;
static MessagePrintState* ShopOwnerPrintState;
enum {
DIALOG_STATE_DONE_INSTRUCTIONS = 0,
DIALOG_STATE_AWAIT_GREETING = 4,
DIALOG_STATE_AWAIT_MAIN_MENU = 41,
DIALOG_STATE_CLOSED_MAIN_MENU = 42,
DIALOG_STATE_CLOSED_SUBMENU = 9,
DIALOG_STATE_DONE = 10,
// selling
DIALOG_STATE_INIT_SELL_CHOICE = 201,
DIALOG_STATE_AWAIT_SELL_CHOICE = 2,
DIALOG_STATE_INIT_SELL_CONFIRM = 21,
DIALOG_STATE_AWAIT_SELL_CONFIRM = 3,
DIALOG_STATE_HANDLE_SELL_CHOICE = 31,
DIALOG_STATE_INIT_SELL_MORE_CHOICE = 32,
DIALOG_STATE_AWAIT_SELL_MORE_CHOICE = 12,
// checking
DIALOG_STATE_INIT_CHECK_CHOICE = 501,
DIALOG_STATE_AWAIT_CHECK_CHOICE = 5,
DIALOG_STATE_HANDLE_CHECK_CHOICE = 51,
DIALOG_STATE_INIT_CHECK_MORE_CHOICE = 52,
DIALOG_STATE_AWAIT_CHECK_MORE_CHOICE = 53,
// claiming
DIALOG_STATE_INIT_CLAIM_CHOICE = 701,
DIALOG_STATE_AWAIT_CLAIM_CHOICE = 7,
DIALOG_STATE_HANDLE_CLAIM_CHOICE = 71,
DIALOG_STATE_INIT_CLAIM_MORE_CHOICE = 72,
DIALOG_STATE_AWAIT_CLAIM_MORE_CHOICE = 73,
};
if (isInitialCall) {
script->functionTemp[1] = shop_owner_begin_speech(SHOP_MSG_GREETING);
script->functionTemp[0] = DIALOG_STATE_AWAIT_GREETING;
}
switch (script->functionTemp[0]) {
case DIALOG_STATE_AWAIT_GREETING:
if (!does_script_exist(script->functionTemp[1])) {
script->functionTemp[0] = DIALOG_STATE_AWAIT_MAIN_MENU;
script->functionTempBool[2] = false;
ShopOwnerPrintState = msg_get_printer_for_msg(MSG_Choice_0003, &script->functionTempBool[2]);
}
break;
case DIALOG_STATE_AWAIT_MAIN_MENU:
if (script->functionTempBool[2] == true) {
switch (ShopOwnerPrintState->curOption) {
case 0:
script->functionTemp[1] = shop_owner_continue_speech(SHOP_MSG_INSTRUCTIONS);
script->functionTemp[0] = DIALOG_STATE_DONE_INSTRUCTIONS;
break;
case 1:
if (get_item_count() == 0) {
script->functionTemp[1] = shop_owner_continue_speech(SHOP_MSG_NOTHING_TO_SELL);
script->functionTemp[0] = DIALOG_STATE_CLOSED_SUBMENU;
} else {
script->functionTemp[1] = shop_owner_continue_speech(SHOP_MSG_SELL_WHICH);
script->functionTemp[0] = DIALOG_STATE_INIT_SELL_CHOICE;
}
break;
case 2:
if (get_item_count() == 0) {
script->functionTemp[1] = shop_owner_continue_speech(SHOP_MSG_NOTHING_TO_CHECK);
script->functionTemp[0] = DIALOG_STATE_CLOSED_SUBMENU;
break;
}
if (get_stored_empty_count() == 0) {
script->functionTemp[1] = shop_owner_continue_speech(SHOP_MSG_NO_CHECK_ROOM);
script->functionTemp[0] = DIALOG_STATE_CLOSED_SUBMENU;
break;
}
script->functionTemp[1] = shop_owner_continue_speech_with_quantity(SHOP_MSG_CHECK_WHICH, get_stored_empty_count());
script->functionTemp[0] = DIALOG_STATE_INIT_CHECK_CHOICE;
break;
case 3:
if (get_stored_count() == 0) {
script->functionTemp[1] = shop_owner_continue_speech(SHOP_MSG_NOTHING_TO_CLAIM);
script->functionTemp[0] = DIALOG_STATE_CLOSED_SUBMENU;
break;
}
if (get_item_empty_count() == 0) {
script->functionTemp[1] = shop_owner_continue_speech(SHOP_MSG_NO_CLAIM_ROOM);
script->functionTemp[0] = DIALOG_STATE_CLOSED_SUBMENU;
break;
}
script->functionTemp[1] = shop_owner_continue_speech(SHOP_MSG_CLAIM_WHICH);
script->functionTemp[0] = DIALOG_STATE_INIT_CLAIM_CHOICE;
break;
default:
script->functionTemp[1] = shop_owner_end_speech();
script->functionTemp[0] = DIALOG_STATE_CLOSED_MAIN_MENU;
break;
}
}
break;
case DIALOG_STATE_INIT_SELL_CHOICE:
if (!does_script_exist(script->functionTemp[1])) {
shop_open_item_select_popup(0);
script->functionTemp[0] = DIALOG_STATE_AWAIT_SELL_CHOICE;
}
break;
case DIALOG_STATE_AWAIT_SELL_CHOICE:
if (shop_update_item_select_popup(&shop->selectedStoreItemSlot) == 1) {
script->functionTemp[0] = DIALOG_STATE_INIT_SELL_CONFIRM;
script->functionTemp[1] = 15;
}
break;
case DIALOG_STATE_INIT_SELL_CONFIRM:
if (script->functionTemp[1] > 0) {
script->functionTemp[1]--;
break;
}
shop_close_item_select_popup();
if (shop->selectedStoreItemSlot >= 0) {
ItemData* itemData = &gItemTable[playerData->invItems[shop->selectedStoreItemSlot]];
script->functionTemp[1] = shop_owner_buy_dialog(SHOP_MSG_SELL_CONFIRM, itemData->nameMsg, shop_get_sell_price(playerData->invItems[shop->selectedStoreItemSlot]), -1);
show_coin_counter();
script->functionTemp[0] = DIALOG_STATE_AWAIT_SELL_CONFIRM;
} else {
script->functionTemp[1] = shop_owner_begin_speech(SHOP_MSG_FAREWELL);
script->functionTemp[0] = DIALOG_STATE_CLOSED_SUBMENU;
}
break;
case DIALOG_STATE_AWAIT_SELL_CONFIRM:
if (!does_script_exist(script->functionTemp[1])) {
script->functionTemp[0] = DIALOG_STATE_HANDLE_SELL_CHOICE;
script->functionTempBool[2] = false;
ShopOwnerPrintState = msg_get_printer_for_msg(MSG_Choice_0002, &script->functionTempBool[2]);
}
break;
case DIALOG_STATE_HANDLE_SELL_CHOICE:
if (script->functionTempBool[2] == true) {
if (ShopOwnerPrintState->curOption == 0) {
add_coins(shop_get_sell_price(playerData->invItems[shop->selectedStoreItemSlot]));
playerData->invItems[shop->selectedStoreItemSlot] = ITEM_NONE;
if (get_item_count() == 0) {
script->functionTemp[1] = shop_owner_reset_speech(SHOP_MSG_SELL_THANKS);
script->functionTemp[0] = DIALOG_STATE_CLOSED_SUBMENU;
hide_coin_counter();
} else {
script->functionTemp[1] = shop_owner_reset_speech(SHOP_MSG_SELL_MORE);
script->functionTemp[0] = DIALOG_STATE_INIT_SELL_MORE_CHOICE;
}
} else {
script->functionTemp[1] = shop_owner_reset_speech(SHOP_MSG_SELL_CANCEL);
script->functionTemp[0] = DIALOG_STATE_INIT_SELL_MORE_CHOICE;
hide_coin_counter();
}
}
break;
case DIALOG_STATE_INIT_SELL_MORE_CHOICE:
if (!does_script_exist(script->functionTemp[1])) {
script->functionTemp[0] = DIALOG_STATE_AWAIT_SELL_MORE_CHOICE;
script->functionTempBool[2] = false;
ShopOwnerPrintState = msg_get_printer_for_msg(MSG_Choice_0004, &script->functionTempBool[2]);
}
break;
case DIALOG_STATE_AWAIT_SELL_MORE_CHOICE:
if (script->functionTempBool[2] == true) {
if (ShopOwnerPrintState->curOption == 0) {
script->functionTemp[1] = shop_owner_end_speech();
script->functionTemp[0] = DIALOG_STATE_INIT_SELL_CHOICE;
hide_coin_counter_immediately();
} else {
hide_coin_counter_immediately();
script->functionTemp[1] = shop_owner_reset_speech(22);
script->functionTemp[0] = DIALOG_STATE_CLOSED_SUBMENU;
}
}
break;
case DIALOG_STATE_INIT_CHECK_CHOICE:
if (does_script_exist(script->functionTemp[1]) == 0) {
shop_open_item_select_popup(1);
script->functionTemp[0] = DIALOG_STATE_AWAIT_CHECK_CHOICE;
}
break;
case DIALOG_STATE_AWAIT_CHECK_CHOICE:
if (shop_update_item_select_popup(&shop->selectedStoreItemSlot) == 1) {
script->functionTemp[0] = DIALOG_STATE_HANDLE_CHECK_CHOICE;
script->functionTemp[1] = 15;
}
break;
case DIALOG_STATE_HANDLE_CHECK_CHOICE:
if (script->functionTemp[1] > 0) {
script->functionTemp[1]--;
break;
}
shop_close_item_select_popup();
if (shop->selectedStoreItemSlot >= 0) {
if (store_item(playerData->invItems[shop->selectedStoreItemSlot]) >= 0) {
playerData->invItems[shop->selectedStoreItemSlot] = ITEM_NONE;
}
if ((get_item_count() == 0) || (get_stored_empty_count() == 0)) {
script->functionTemp[1] = shop_owner_begin_speech(SHOP_MSG_CHECK_ACCEPTED);
script->functionTemp[0] = DIALOG_STATE_CLOSED_SUBMENU;
} else {
script->functionTemp[1] = shop_owner_begin_speech(SHOP_MSG_CHECK_MORE);
script->functionTemp[0] = DIALOG_STATE_INIT_CHECK_MORE_CHOICE;
}
} else {
script->functionTemp[1] = shop_owner_begin_speech(SHOP_MSG_FAREWELL);
script->functionTemp[0] = DIALOG_STATE_CLOSED_SUBMENU;
}
break;
case DIALOG_STATE_INIT_CHECK_MORE_CHOICE:
if (!does_script_exist(script->functionTemp[1])) {
script->functionTemp[0] = DIALOG_STATE_AWAIT_CHECK_MORE_CHOICE;
script->functionTempBool[2] = false;
ShopOwnerPrintState = msg_get_printer_for_msg(MSG_Choice_0005, &script->functionTempBool[2]);
}
break;
case DIALOG_STATE_AWAIT_CHECK_MORE_CHOICE:
if (script->functionTempBool[2] == true) {
if (ShopOwnerPrintState->curOption == 0) {
script->functionTemp[1] = shop_owner_end_speech();
script->functionTemp[0] = DIALOG_STATE_INIT_CHECK_CHOICE;
} else {
script->functionTemp[1] = shop_owner_reset_speech(SHOP_MSG_FAREWELL);
script->functionTemp[0] = DIALOG_STATE_CLOSED_SUBMENU;
}
}
break;
case DIALOG_STATE_INIT_CLAIM_CHOICE:
if (!does_script_exist(script->functionTemp[1])) {
shop_open_item_select_popup(2);
script->functionTemp[0] = DIALOG_STATE_AWAIT_CLAIM_CHOICE;
}
break;
case DIALOG_STATE_AWAIT_CLAIM_CHOICE:
if (shop_update_item_select_popup(&shop->selectedStoreItemSlot) == 1) {
script->functionTemp[0] = DIALOG_STATE_HANDLE_CLAIM_CHOICE;
script->functionTemp[1] = 15;
}
break;
case DIALOG_STATE_HANDLE_CLAIM_CHOICE:
if (script->functionTemp[1] > 0) {
script->functionTemp[1]--;
break;
}
shop_close_item_select_popup();
if (shop->selectedStoreItemSlot >= 0) {
if (add_item(playerData->storedItems[shop->selectedStoreItemSlot]) >= 0) {
playerData->storedItems[shop->selectedStoreItemSlot] = 0;
}
if (get_item_empty_count() == 0 || get_stored_count() == 0) {
script->functionTemp[1] = shop_owner_begin_speech(SHOP_MSG_CLAIM_ACCEPTED);
script->functionTemp[0] = DIALOG_STATE_CLOSED_SUBMENU;
} else {
script->functionTemp[1] = shop_owner_begin_speech(SHOP_MSG_CLAIM_MORE);
script->functionTemp[0] = DIALOG_STATE_INIT_CLAIM_MORE_CHOICE;
}
} else {
script->functionTemp[1] = shop_owner_begin_speech(SHOP_MSG_FAREWELL);
script->functionTemp[0] = DIALOG_STATE_CLOSED_SUBMENU;
}
break;
case DIALOG_STATE_INIT_CLAIM_MORE_CHOICE:
if (!does_script_exist(script->functionTemp[1])) {
script->functionTemp[0] = DIALOG_STATE_AWAIT_CLAIM_MORE_CHOICE;
script->functionTempBool[2] = false;
ShopOwnerPrintState = msg_get_printer_for_msg(MSG_Choice_0005, &script->functionTempBool[2]);
}
break;
case DIALOG_STATE_AWAIT_CLAIM_MORE_CHOICE:
if (script->functionTempBool[2] == true) {
if (ShopOwnerPrintState->curOption == 0) {
script->functionTemp[1] = shop_owner_end_speech();
script->functionTemp[0] = DIALOG_STATE_INIT_CLAIM_CHOICE;
} else {
script->functionTemp[1] = shop_owner_reset_speech(SHOP_MSG_FAREWELL);
script->functionTemp[0] = DIALOG_STATE_CLOSED_SUBMENU;
}
}
break;
case DIALOG_STATE_DONE_INSTRUCTIONS:
case DIALOG_STATE_CLOSED_SUBMENU:
case DIALOG_STATE_CLOSED_MAIN_MENU:
if (!does_script_exist(script->functionTemp[1])) {
script->functionTemp[0] = DIALOG_STATE_DONE;
}
break;
case DIALOG_STATE_DONE:
if (shop->owner != NULL) {
if (shop->owner->onTalkEvt != 0) {
start_script(shop->owner->onTalkEvt, EVT_PRIORITY_1, 0);
}
}
open_status_bar_quickly();
return ApiStatus_DONE1;
}
return ApiStatus_BLOCK;
}
void shop_draw_item_name(s32 arg0, s32 posX, s32 posY) {
Shop* shop = gGameStatusPtr->mapShop;
ShopItemData* siItem = &shop->staticInventory[shop->curItemSlot];
ItemData* shopItem = &gItemTable[siItem->itemID];
draw_msg(shopItem->nameMsg, posX + 60 - (get_msg_width(shopItem->nameMsg, 0) >> 1), posY + 6, 255, MSG_PAL_WHITE, 0);
}
void shop_draw_item_desc(s32 arg0, s32 posX, s32 posY) {
Shop* shop = gGameStatusPtr->mapShop;
ShopItemData* shopItem = &shop->staticInventory[shop->curItemSlot];
draw_msg(shopItem->descMsg, posX + 8, posY, 255, MSG_PAL_STANDARD, 0);
}
void draw_shop_items(void) {
Shop* shop = gGameStatusPtr->mapShop;
ShopItemData* itemData;
Camera* camera;
s32 i;
s32 xTemp;
s32 yTemp;
s32 xOffset;
f32 x, y, z, s;
f32 inX, inY, inZ;
ShopItemEntity* shopItemEntities;
if (shop->flags & SHOP_FLAG_SHOWING_ITEM_INFO) {
set_window_update(WIN_SHOP_ITEM_NAME, (s32) basic_window_update);
set_window_update(WIN_SHOP_ITEM_DESC, (s32) basic_window_update);
} else {
set_window_update(WIN_SHOP_ITEM_NAME, (s32) basic_hidden_window_update);
set_window_update(WIN_SHOP_ITEM_DESC, (s32) basic_hidden_window_update);
}
if (shop->flags & SHOP_FLAG_SHOWING_ITEM_INFO) {
camera = &gCameras[gCurrentCameraID];
itemData = shop->staticInventory;
shopItemEntities = gGameStatusPtr->shopItemEntities;
for (i = 0; i < shop->numItems; i++, itemData++, shopItemEntities++) {
inX = shopItemEntities->pos.x;
inY = shopItemEntities->pos.y + 30.0f;
inZ = shopItemEntities->pos.z;
transform_point(camera->mtxPerspective, inX, inY, inZ, 1.0f, &x, &y, &z, &s);
s = 1.0f / s;
x *= s;
y *= -s;
z = (z * s + 1.0f) * 0.5;
if (z > 0.0f && z < 1.0f) {
xTemp = (((x * camera->viewportW) + camera->viewportW) * 0.5) + camera->viewportStartX;
yTemp = (((y * camera->viewportH) + camera->viewportH) * 0.5) + camera->viewportStartY;
if (itemData->price < 100) {
xOffset = -4;
} else {
xOffset = 0;
}
if (!(get_item_entity(shopItemEntities->index)->flags & ITEM_ENTITY_FLAG_HIDDEN)) {
draw_number(itemData->price, xTemp + xOffset, yTemp, DRAW_NUMBER_CHARSET_THIN, MSG_PAL_WHITE, 255, 0);
}
if (i == shop->curItemSlot) {
hud_element_set_render_pos(shop->costHID, (xTemp + xOffset) - 6, yTemp + 5);
hud_element_set_scale(shop->costHID, 0.7f);
hud_element_draw_clipped(shop->costHID);
}
}
}
}
if (shop->unk_358 > 0) {
shop->unk_358--;
} else {
shop->flags &= ~SHOP_FLAG_SHOWING_ITEM_INFO;
status_bar_always_show_off();
}
}
API_CALLABLE(MakeShop) {
Bytecode* args = script->ptrReadPos;
ShopItemLocation* itemDataPositions;
ShopItemData* inventory;
ShopSellPriceData* prices;
s32 inventoryItemFlags;
Shop* shop;
Model* model;
s32 numShopItems;
f32 centerX;
f32 centerY;
f32 centerZ;
s32 var1;
s32 var2;
s32 var3;
s32 var4;
f32 sizeX;
f32 sizeY;
f32 sizeZ;
var1 = evt_get_variable(script, *args++);
var2 = evt_get_variable(script, *args++);
var3 = evt_get_variable(script, *args++);
var4 = evt_get_variable(script, *args++);
itemDataPositions = (ShopItemLocation*) var1;
inventory = (ShopItemData*) var2;
prices = (ShopSellPriceData*) var3;
inventoryItemFlags = var4;
shop = heap_malloc(sizeof(*shop));
gGameStatusPtr->mapShop = shop;
shop->itemDataPositions = itemDataPositions;
shop->staticInventory = inventory;
shop->staticPriceList = prices;
shop->inventoryItemFlags = inventoryItemFlags;
numShopItems = 0;
while (inventory->itemID != ITEM_NONE) {
numShopItems++;
inventory++;
}
shop->numItems = numShopItems;
numShopItems = 0;
if (prices != NULL) {
while (prices->itemID != ITEM_NONE) {
numShopItems++;
prices++;
}
}
shop->numSpecialPrices = numShopItems;
if (shop->numItems > 0) {
gGameStatusPtr->shopItemEntities = heap_malloc(sizeof(ShopItemEntity) * shop->numItems);
}
inventory = shop->staticInventory;
itemDataPositions = shop->itemDataPositions;
numShopItems = 0;
while (inventory->itemID != ITEM_NONE) {
get_model_center_and_size(itemDataPositions->posModelID, &centerX, &centerY, &centerZ, &sizeX, &sizeY, &sizeZ);
centerY += 6;
gGameStatusPtr->shopItemEntities[numShopItems].pos.x = centerX;
gGameStatusPtr->shopItemEntities[numShopItems].pos.y = centerY;
gGameStatusPtr->shopItemEntities[numShopItems].pos.z = centerZ;
model = get_model_from_list_index(get_model_list_index_from_tree_index(itemDataPositions->posModelID));
model->flags |= MODEL_FLAG_INACTIVE;
gGameStatusPtr->shopItemEntities[numShopItems].index =
make_item_entity_nodelay(inventory->itemID | shop->inventoryItemFlags, centerX, centerY, centerZ, 1, 0);
set_item_entity_flags(gGameStatusPtr->shopItemEntities[numShopItems].index, ITEM_ENTITY_RESIZABLE);
bind_trigger_1(&EVS_ShopItemInteract, TRIGGER_FLOOR_TOUCH, itemDataPositions->triggerColliderID, numShopItems, 0, 3);
bind_trigger_1(&EVS_ShopItemInteract, TRIGGER_FLOOR_PRESS_A, itemDataPositions->triggerColliderID, numShopItems, 0, 3);
itemDataPositions++;
inventory++;
numShopItems++;
}
shop->costHID = hud_element_create(&HES_Item_Coin);
hud_element_set_flags(shop->costHID, HUD_ELEMENT_FLAG_80);
hud_element_clear_flags(shop->costHID, HUD_ELEMENT_FLAG_FILTER_TEX);
get_worker(create_worker_frontUI(NULL, draw_shop_items));
set_window_properties(WIN_SHOP_ITEM_NAME, 100, 66, 120, 28, WINDOW_PRIORITY_0, shop_draw_item_name, NULL, -1);
#if VERSION_JP
set_window_properties(WIN_SHOP_ITEM_DESC, 39, 184, 242, 32, WINDOW_PRIORITY_1, shop_draw_item_desc, NULL, -1);
#else
set_window_properties(WIN_SHOP_ITEM_DESC, 32, 184, 256, 32, WINDOW_PRIORITY_1, shop_draw_item_desc, NULL, -1);
#endif
gWindowStyles[10].defaultStyleID = WINDOW_STYLE_9;
gWindowStyles[11].defaultStyleID = WINDOW_STYLE_3;
shop->curItemSlot = 0;
shop->selectedStoreItemSlot = 0;
shop->flags = 0;
shop->owner = NULL;
return ApiStatus_DONE2;
}
API_CALLABLE(MakeShopOwner) {
Shop* mapShop = gGameStatusPtr->mapShop;
mapShop->owner = (ShopOwner*) evt_get_variable(script, *script->ptrReadPos);
return ApiStatus_DONE2;
}