//Tiles used for resource icons. Each counter is separate constant.
const int TILE_CR_0 = 25226;
const int TILE_CR_1 = 25225;
const int TILE_CR_2 = 25228;
const int TILE_CR_3 = 25227;
const int TILE_CR_4 = 25229;
const int TILE_CR_5 = 25230;
const int TILE_CR_6 = 25227;
const int TILE_CR_7 = 27533;
const int TILE_CR_8 = 27533;
const int TILE_CR_9 = 27533;
const int TILE_CR_10 = 27533;
const int TILE_CR_11 = 0;
const int TILE_CR_12 = 0;
const int TILE_CR_13 = 0;
const int TILE_CR_14 = 0;
const int TILE_CR_15 = 0;
const int TILE_CR_16 = 0;
const int TILE_CR_17 = 0;
const int TILE_CR_18 = 0;
const int TILE_CR_19 = 0;
const int TILE_CR_20 = 0;
const int TILE_CR_21 = 0;
const int TILE_CR_22 = 0;
const int TILE_CR_23 = 0;
const int TILE_CR_24 = 0;
const int TILE_CR_25 = 0;
const int TILE_CR_26 = 0;
const int TILE_CR_27 = 0;
const int TILE_CR_28 = 0;
const int TILE_CR_29 = 0;
const int TILE_CR_30 = 0;
const int TILE_CR_31 = 0;
//Csets used to render resource icons. Each counter is separate constant.
const int CSET_CR_0 = 8;
const int CSET_CR_1 = 5;
const int CSET_CR_2 = 7;
const int CSET_CR_3 = 1;
const int CSET_CR_4 = 4;
const int CSET_CR_5 = 1;
const int CSET_CR_6 = 8;
const int CSET_CR_7 = 1;
const int CSET_CR_8 = 5;
const int CSET_CR_9 = 7;
const int CSET_CR_10 = 8;
const int CSET_CR_11 = 0;
const int CSET_CR_12 = 0;
const int CSET_CR_13 = 0;
const int CSET_CR_14 = 0;
const int CSET_CR_15 = 0;
const int CSET_CR_16 = 0;
const int CSET_CR_17 = 0;
const int CSET_CR_18 = 0;
const int CSET_CR_19 = 0;
const int CSET_CR_20 = 0;
const int CSET_CR_21 = 0;
const int CSET_CR_22 = 0;
const int CSET_CR_23 = 0;
const int CSET_CR_24 = 0;
const int CSET_CR_25 = 0;
const int CSET_CR_26 = 0;
const int CSET_CR_27 = 0;
const int CSET_CR_28 = 0;
const int CSET_CR_29 = 0;
const int CSET_CR_30 = 0;
const int CSET_CR_31 = 0;
const int SCREEN_D_SOLDOUT = 0;//Scree D register used to track one-time pusrchases for shops.
const int FONT_RESOURCE_SHOP = 0;//Font used to render strings in shop UI
const int C_RESOURCE_CAN_AFFORD = 0x52;//Color used to indicate cost, if Link can afford purchase.
const int C_RESOURCE_CANNOT_AFFORD = 0x81;//Color used to indicate cost, if Link cannot afford purchase.
const int C_RESOURCE_FONT_SHADOW = 0x71;//Shadow for HUD font drawing (Color).
const int TILE_RESOURCE_FRAME = 20052;//Id of top left corner for 3x3 frame used to render UI frame.
const int CSET_RESOURCE_FRAME = 11;//ICSet used to render UI frame.
const int CMB_SOLD_OUT_SIGN = 1011;//Combo used to render "Sold Out" sign after doing one-time purchase.
const int CSET_SOLD_OUT_SIGN = 11;//CSet used to render "Sold Out" sign after doing one-time purchase.
const int CMB_RESOURCE_SHOP_PROMPT = 911;//Combo ID used to render prompt, when Link steps on shop spot.
const int CSET_RESOURCE_SHOP_PROMPT = 11;//CSet used to render prompt, when Link steps on shop spot.
const int RESOURCE_DISPLAY_X_OFFSET = 0;//Coordinates of rendering item displayed in the screen, relative to FFC`s position.
const int RESOURCE_DISPLAY_Y_OFFSET = -16;
const int RESOURCE_DISPLAY_MENU_X_OFFSET = 64;//Coordinates of rendering item displayed in the menu, relative to FFC`s position.
const int RESOURCE_DISPLAY_MENU_Y_OFFSET = 0;
//Skyward Sword resource upgrade/resource shop.
//An NPC that offers specific service, either new item, item upgrade, or secret trigger, for cost that consist of multiple counters to be paid simultaneously.
//Stand on FFC and press Ex1 to render string and then cost (up to 6 different counters with separate cost for each). If you can afford, press Ex1 to confirm payment, or Ex2 to cancel. If HP is used as part of cost, minimum of 1 heart must be left to afford payment.
//1. Set up graphics:
// TILE_CR_* for rendering counter icons using CSET_CR_* for shop UI.
// 3x3 frame for TILE_RESOURCE_FRAME. Needed to render UI frame using CSET_RESOURCE_FRAME CSet.
// Combo for "Sold Out sign".
// Combo for prompt display, when Link tands on FFC.
//2. Set up constants in script file to match graphics you set up.
//3. Place FFC st shop position.
// D0-D5 - counter costs, for each counter:
// #####.____ - ID of counter used to pay. <0 - ID of required item (taken away as part of barter deal)
// _____.#### - counter amount to pay.
// D6 #####.____ - String to display as intro when standing on FFC and pressing EX1.
// D6 _____.#### - String to display on purchase.
// D7 #####.____ - Screen D bit to track "Sold Out" status. >12 - infinite stock in shop.
// D7 _____.#### - ID of item sold/upgraded into. If D7<0 - secrets trigger instead on purchase (cash gate, building construction).
ffc script ResourceUpgradeShop{
void run (int cost1, int cost2, int cost3, int cost4, int cost5, int cost6, int req, int award){
int CR_TILES[32] = {TILE_CR_0,TILE_CR_1,TILE_CR_2,TILE_CR_3, TILE_CR_4,TILE_CR_5,TILE_CR_6,TILE_CR_7,TILE_CR_8,TILE_CR_9,
TILE_CR_10,TILE_CR_11,TILE_CR_12,TILE_CR_13, TILE_CR_14,TILE_CR_15,TILE_CR_16,TILE_CR_17,TILE_CR_18,TILE_CR_19,
TILE_CR_20,TILE_CR_21,TILE_CR_22,TILE_CR_23, TILE_CR_24,TILE_CR_25,TILE_CR_26,TILE_CR_27,TILE_CR_28,TILE_CR_29,
TILE_CR_30,TILE_CR_31};
int CR_CSETS[32] = {CSET_CR_0,CSET_CR_1,CSET_CR_2,CSET_CR_3, CSET_CR_4,CSET_CR_5,CSET_CR_6,CSET_CR_7,CSET_CR_8,CSET_CR_9,
CSET_CR_10,CSET_CR_11,CSET_CR_12,CSET_CR_13, CSET_CR_14,CSET_CR_15,CSET_CR_16,CSET_CR_17,CSET_CR_18,CSET_CR_19,
CSET_CR_20,CSET_CR_21,CSET_CR_22,CSET_CR_23, CSET_CR_24,CSET_CR_25,CSET_CR_26,CSET_CR_27,CSET_CR_28,CSET_CR_29,
CSET_CR_30,CSET_CR_31};
int RawCosts[6] = {cost1, cost2, cost3, cost4, cost5, cost6};
int COSTS[6];
int REQS[6];
int ITEMTILE[6];
int ITEMCSET[6];
for (int i=0; i<SizeOfArray(COSTS);i++){
REQS[i] = GetHighFloat(RawCosts[i]);
COSTS[i] = GetLowFloat(RawCosts[i]);
if (RawCosts[i]<0){
item it = Screen->CreateItem(Abs(REQS[i]));
ITEMTILE[i] = it->OriginalTile;
ITEMCSET[i] = it->CSet;
Remove(it);
}
}
int itm = Abs(GetLowFloat(award));
int ScreenD = Abs(GetHighFloat(award));
int EndStr = Abs(GetLowFloat(req));
int InfoString = Abs(GetHighFloat(req));
if (ScreenD<13){
if (GetScreenDBit(SCREEN_D_SOLDOUT, ScreenD)){
this->Data = CMB_SOLD_OUT_SIGN;
this->CSet = CSET_SOLD_OUT_SIGN;
Quit();
}
}
int AwarditemTile = GetItemTile(itm);
int AwarditemCSet = GetItemCSet(itm);
int cmb = 0;
int origcmb = ComboAt(CenterX(this), CenterY(this));
int state = 0;
int counter = 0;
int cost = 0;
int hpused = 0;
bool canafford = true;
int str1[] = "/";
int str2[] = "Not enough";
int str3[] = "Ex1-Confirm";
int str4[] = "OK";
int str5[] = "resources";
int str6[] = "Missing";
int str7[] = "Ex2-Cancel";
int str8[] = "1 heart";
int str9[] = "must left";
while(true){
if (state==0){
if ( award>0)Screen->FastTile(3,this->X+RESOURCE_DISPLAY_X_OFFSET, this->Y+RESOURCE_DISPLAY_Y_OFFSET,AwarditemTile, AwarditemCSet, OP_OPAQUE);
cmb = ComboAt(CenterLinkX(), CenterLinkY()-2);
if (cmb==origcmb){
Screen->FastCombo(6, Link->X,Link->Y-15,CMB_RESOURCE_SHOP_PROMPT, CSET_RESOURCE_SHOP_PROMPT,OP_OPAQUE);
if (Link->PressEx1){
Screen->Message(InfoString);
state=1;
}
}
}
else if (state==1){
hpused=0;
if ( award>0){
Screen->FastTile(3,this->X+RESOURCE_DISPLAY_X_OFFSET, this->Y+RESOURCE_DISPLAY_Y_OFFSET,AwarditemTile, AwarditemCSet, OP_OPAQUE);
}
DrawFrame(6,TILE_RESOURCE_FRAME,64,16,8,9,CSET_RESOURCE_FRAME,OP_OPAQUE);
if ( award>0){
DrawFrame(6,TILE_RESOURCE_FRAME,112+RESOURCE_DISPLAY_MENU_X_OFFSET,0+RESOURCE_DISPLAY_MENU_Y_OFFSET,2,2,CSET_RESOURCE_FRAME,OP_OPAQUE);
Screen->FastTile(6,120+RESOURCE_DISPLAY_MENU_X_OFFSET, 8+RESOURCE_DISPLAY_MENU_Y_OFFSET,AwarditemTile, AwarditemCSet, OP_OPAQUE);
}
for (int i=0;i<SizeOfArray(REQS);i++){
counter = REQS[i];
cost = COSTS[i];
if (REQS[i]<0){
Screen->FastTile(6, 80,28+17*i, ITEMTILE[i], ITEMCSET[i], OP_OPAQUE);
int itm = Abs(REQS[i]);
if (C_RESOURCE_FONT_SHADOW>0){
if (Link->Item[itm]) Screen->DrawString(6,105, 33+17*i,FONT_RESOURCE_SHOP, C_RESOURCE_FONT_SHADOW, -1, 0, str4, OP_OPAQUE);
else Screen->DrawString(6,105, 33+17*i,FONT_RESOURCE_SHOP, C_RESOURCE_FONT_SHADOW, -1, 0, str6, OP_OPAQUE);
}
if (Link->Item[itm]) Screen->DrawString(6,104, 32+17*i,FONT_RESOURCE_SHOP, C_RESOURCE_CAN_AFFORD, -1, 0, str4, OP_OPAQUE);
else Screen->DrawString(6,104, 32+17*i,FONT_RESOURCE_SHOP, C_RESOURCE_CANNOT_AFFORD, -1, 0, str6, OP_OPAQUE);
continue;
}
if (cost==0)continue;
if (counter==CR_LIFE && cost>0)hpused=cost;
if (C_RESOURCE_FONT_SHADOW>0){
Screen->DrawInteger(6,99, 33+17*i,FONT_RESOURCE_SHOP, C_RESOURCE_FONT_SHADOW, -1, 0,0, Game->Counter[counter],0, OP_OPAQUE);
Screen->DrawString(6,131, 33+17*i,FONT_RESOURCE_SHOP, C_RESOURCE_FONT_SHADOW, -1, 0, str1, OP_OPAQUE);
Screen->DrawInteger(6,139, 33+17*i,FONT_RESOURCE_SHOP, C_RESOURCE_FONT_SHADOW, -1, 0,0, cost,0, OP_OPAQUE);
}
Screen->FastTile(6, 80,28+17*i, CR_TILES[counter], CR_CSETS[counter], OP_OPAQUE);
Screen->DrawInteger(6,98, 32+17*i,FONT_RESOURCE_SHOP, Cond(Game->Counter[counter]>=cost,C_RESOURCE_CAN_AFFORD,C_RESOURCE_CANNOT_AFFORD), -1, 0,0, Game->Counter[counter],0, OP_OPAQUE);
Screen->DrawString(6,130, 32+17*i,FONT_RESOURCE_SHOP, 1, -1, 0, str1, OP_OPAQUE);
Screen->DrawInteger(6,138, 32+17*i,FONT_RESOURCE_SHOP, 1, -1, 0,0, cost,0, OP_OPAQUE);
}
if (hpused>0 && Link->HP < hpused+16){
if (C_RESOURCE_FONT_SHADOW>0){
Screen->DrawString(6,85, 135, FONT_RESOURCE_SHOP, C_RESOURCE_FONT_SHADOW, -1, 0, str8, OP_OPAQUE);
Screen->DrawString(6,85, 143, FONT_RESOURCE_SHOP, C_RESOURCE_FONT_SHADOW, -1, 0, str9, OP_OPAQUE);
}
Screen->DrawString(6,84, 134, FONT_RESOURCE_SHOP, 1, -1, 0, str8, OP_OPAQUE);
Screen->DrawString(6,84, 142, FONT_RESOURCE_SHOP, 1, -1, 0, str9, OP_OPAQUE);
}
else if (!CanAfford(COSTS, REQS)){
if (C_RESOURCE_FONT_SHADOW>0){
Screen->DrawString(6,89, 135, FONT_RESOURCE_SHOP, C_RESOURCE_FONT_SHADOW, -1, 0, str2, OP_OPAQUE);
Screen->DrawString(6,89, 143, FONT_RESOURCE_SHOP, C_RESOURCE_FONT_SHADOW, -1, 0, str5, OP_OPAQUE);
}
Screen->DrawString(6,88, 134, FONT_RESOURCE_SHOP, 1, -1, 0, str2, OP_OPAQUE);
Screen->DrawString(6,88, 142, FONT_RESOURCE_SHOP, 1, -1, 0, str5, OP_OPAQUE);
}
else{
if (C_RESOURCE_FONT_SHADOW>0){
Screen->DrawString(6,81, 135, FONT_RESOURCE_SHOP, C_RESOURCE_FONT_SHADOW, -1, 0, str3, OP_OPAQUE);
Screen->DrawString(6,81, 143, FONT_RESOURCE_SHOP, C_RESOURCE_FONT_SHADOW, -1, 0, str7, OP_OPAQUE);
}
Screen->DrawString(6,80, 134, FONT_RESOURCE_SHOP, 1, -1, 0, str3, OP_OPAQUE);
Screen->DrawString(6,80, 142, FONT_RESOURCE_SHOP, 1, -1, 0, str7, OP_OPAQUE);
}
if (Link->PressEx2) state=0;
if (Link->PressEx1){
if (CanAfford(COSTS,REQS)){
for (int i=0;i<SizeOfArray(REQS);i++){
if (REQS[i]<0){
int itm = Abs(REQS[i]);
Link->Item[itm]=false;
}
else{
counter = REQS[i];
cost = COSTS[i];
Game->DCounter[counter]-=cost;
}
}
Screen->Message(EndStr);
if (award<0){
Game->PlaySound(SFX_SECRET);
Screen->TriggerSecrets();
Screen->State[ST_SECRET]=true;
}
else{
item it = CreateItemAt(itm, Link->X, Link->Y);
it->Pickup +=IP_HOLDUP;
}
if (ScreenD<13){
SetScreenDBit(SCREEN_D_SOLDOUT, ScreenD, true);
this->Data = CMB_SOLD_OUT_SIGN;
this->CSet = CSET_SOLD_OUT_SIGN;
Quit();
}
else state=0;
}
else state=0;
}
NoAction();
}
Waitframe();
}
}
bool CanAfford(int costs, int reqs){
for (int i=0;i<SizeOfArray(reqs);i++){
int counter = reqs[i];
int cost = costs[i];
if (counter<0){
int itm = Abs(counter);
if (!Link->Item[itm])return false;
}
if (Game->Counter[counter]<cost) return false;
if (counter== CR_LIFE && Game->Counter[counter]<cost+16) return false;
}
return true;
}
void DrawFrame(int layer, int tile, int posx, int posy, int sizex, int sizey, int CSet, int opacity){
int drawx = posx;
int drawy = posy;
int xoffset=0;
int yoffset=0;
for (int w=0; w<sizex; w++){
drawx = posx+16*w;
xoffset=0;
if (w>0)xoffset=1;
if (w==sizex-1) xoffset=2;
for (int h=0; h<sizey; h++){
drawy = posy+16*h;
yoffset=0;
if (h>0)yoffset=1;
if (h==sizey-1) yoffset=2;
Screen->FastTile(layer, drawx, drawy, tile +xoffset+20*yoffset, CSet, opacity);
}
}
}
int GetItemTile(int itm){
item it =Screen->CreateItem(itm);
int ret = it->OriginalTile;
Remove(it);
return ret;
}
int GetItemCSet(int itm){
item it =Screen->CreateItem(itm);
int ret = it->CSet;
Remove(it);
return ret;
}
}
// Shop cleanout reward.
//Rewards player for doing all one-time purchases in shop using "ResourceUpgradeShop" script within current screen. Shops with infinite stock are ignored.
//Place invisible FFC anywhere in the screen.
//D0 - String to display on accomplishment.
//D1 - Reward. >0 - Item ID, <0 - permanent secrets.
ffc script ResourceShopCleanoutReward{
void run(int string, int reward){
if (reward>=0){
if (Screen->State[ST_SPECIALITEM])Quit();
}
else{
if (Screen->State[ST_SECRET])Quit();
}
while(!ResourceShopCleaned())Waitframe();
Waitframe();
Screen->Message(string);
Waitframe();
if (reward>=0){
item it = CreateItemAt(reward, Link->X, Link->Y);
it->Pickup +=0x802;
}
else{
Game->PlaySound(SFX_SECRET);
Screen->TriggerSecrets();
Screen->State[ST_SECRET]=true;
}
}
bool ResourceShopCleaned(){
int str[] = "ResourceUpgradeShop";
int scr = Game->GetFFCScript(str);
for (int i = 1; i<=32;i++){
ffc f = Screen->LoadFFC(i);
if (f->Script!=scr) continue;
int ScreenD = Abs(GetHighFloat(f->InitD[7]));
if (ScreenD>12) continue;
if (!GetScreenDBit(SCREEN_D_SOLDOUT, ScreenD)) return false;
}
return true;
}
}