PDA

View Full Version : Advanced Shop Script



ShadowMancer
08-17-2007, 12:57 PM
By popular demand; Presenting the Advanced Shop Script :D



import "std.zh"
int is_spending = 0;
int hold_time = 0;

ffc script shop_item {
void run(int item_is, int cost_is, int hands, int ctr_ref, int ctr_amt, int ffc_num, int msg) {
//The folling line is the combo ID where the '0' tile is, if your tile is in a different place simply change this number
int cmb_zero = 6656;
int tmp_cost;
ffc dig_10000;
ffc dig_1000;
ffc dig_100;
ffc dig_10;
ffc dig_1;
//Cost display routine
//Load needed digit ffcs
dig_10000 = Screen->LoadFFC(ffc_num+1);
dig_1000 = Screen->LoadFFC(ffc_num+2);
dig_100 = Screen->LoadFFC(ffc_num+3);
dig_10 = Screen->LoadFFC(ffc_num+4);
dig_1 = Screen->LoadFFC(ffc_num+5);
//put them in location
dig_10000->X = this->X-12;
dig_10000->Y = this->Y+18;
dig_1000->X = this->X-4;
dig_1000->Y = this->Y+18;
dig_100->X = this->X+4;
dig_100->Y = this->Y+18;
dig_10->X = this->X+12;
dig_10->Y = this->Y+18;
dig_1->X = this->X+20;
dig_1->Y = this->Y+18;
//display the digits
tmp_cost = cost_is;
dig_10000->Data = cmb_zero + Floor(tmp_cost*0.0001);
if(Floor(tmp_cost*0.0001) > 0) {tmp_cost -= (Floor(tmp_cost*0.0001)*10000);}
if (dig_10000->Data == cmb_zero) {
dig_10000->Data = 0;
dig_1000->X -=4;
dig_100->X -=4;
dig_10->X -=4;
dig_1->X -=4;
}
dig_1000->Data = cmb_zero + Floor(tmp_cost*0.001);
if(Floor(tmp_cost*0.001) > 0) {tmp_cost -= (Floor(tmp_cost*0.001)*1000);}
if(dig_1000->Data == cmb_zero && dig_10000->Data == 0) {
dig_1000->Data = 0;
dig_100->X -=4;
dig_10->X -=4;
dig_1->X -=4;
}
dig_100->Data = cmb_zero + Floor(tmp_cost*0.01);
if(Floor(tmp_cost*0.01) > 0) {tmp_cost -= (Floor(tmp_cost*0.01)*100);}
if (dig_100->Data == cmb_zero && dig_1000->Data == 0) {
dig_100->Data = 0;
dig_10->X -=4;
dig_1->X -=4;
}
dig_10->Data = cmb_zero + Floor(tmp_cost*0.1);
if(Floor(tmp_cost*0.1) > 0) {tmp_cost -= (Floor(tmp_cost*0.1)*10);}
if (dig_10->Data == cmb_zero && dig_100->Data == 0) {
dig_10->Data = 0;
dig_1->X -=4;
}
dig_1->Data = cmb_zero + Floor(tmp_cost/1);
//Main Loop
while(true) {
Waitframe();
if(this->Data != 0 && Link->X >= this->X-8 && Link->X <= this->X +24 && Link->Y >= this->Y-8 && Link->Y <= this->Y+24 && Game->Counter[1] >= cost_is && is_spending == 0)
{
this->Data = 0;
dig_10000->Data = 0;
dig_1000->Data = 0;
dig_100->Data = 0;
dig_10->Data = 0;
dig_1->Data = 0;
if (ctr_ref == -1) {Link->Item[item_is]=true;} else {Game->Counter[ctr_ref] += ctr_amt;}
if (hands == 2) {Link->Action = 5;}
if (hands == 1) {Link->Action = 4;}
Link->HeldItem = item_is;
if (msg != 0) {Screen->Message(msg);}
hold_time = 30;
Game->PlaySound(20)
is_spending = cost_is;

}
}
}
}

void rupie_taker()
{
Game->Counter[1] -= 1;
is_spending -= 1;
hold_time -= 1;
if (hold_time == 0) {Link->Action = 0;}
return;
}
global script main_script {
void run() {
while(true) {
//Put other global scripts here

if(is_spending > 0) {rupie_taker();}
Waitframe();
}
}
}


Features:

-> Make shops with 1-5 items
-> Use prices from 1-99999
-> Automatically displays prices
-> Takes rupies one by one just like LoZ
-> Optional message display when Link buys item


Some setup is required:
Make number tiles 0-9 (the script is curently setup to use tiles I made which are 8X8 numbers in the upper right coner of the tile)
Put these number tiles on the top of combo page 26 (you can change this if you want, see code for details)

To setup the FFC's:
I sugest useing FFC IDs 1,7,13,19,25
simply because the digits use the next 5 FFC's after the item FFC
set the combo of the FFC to look like the item you are selling
then just set a few arguments.

Arugements:
D0: ID of the item
D1: Cost of the item
D2: # of hands link uses when holding up item (use 0 to not hold up item)
D3: Counter Reference: if this item fills a counter (hearts, arrows, bombs etc) then put the counter ref. # here, use -1 if it is not a counter item.
D4: Counter Amount: Put amount counter is increased here
D5: FFC ID: (required) just put the ID # of the FFC this is
D6: Optional Message: if you want to display a message when Link buys the item put the message number here otherwise put 0.

I've tested this a few times and it seems to work fine, as always report any bugs here. The only odd thing is when rupies are bieng taken you cannot buy another item and, it will take a looooooong time to subtract the rupies for large priced items (i tested it with something like 6500 cost and it took forever) If this really botheres anyone let me know and I'll post a variation that will just take all the rupies at once, this was something that was sugested so I added it as an afterthought.

Hope this will hold everyone over until the 999 rupie limt thing is fixed :)

Almost forgot, the script 'main_script' is to be put in global slot #2 if you have any other scripts you need to run for every frame of the game put them in the main_scipt. I have not fully tested this but it should allow other things to happen while rupies are bieng taken (originally i had a while loop that took rupies but that prevented other things in my main_script from functioning until all the rupies were taken, this should fix it)

UPDATE: Here is the variation that takes rupies instantly I also added to sound FX to both scripts


import "std.zh"

int hold_time = 0;

ffc script shop_item {
void run(int item_is, int cost_is, int hands, int ctr_ref, int ctr_amt, int ffc_num, int msg) {
//The folling line is the combo ID where the '0' tile is, if your tile is in a different place simply change this number
int cmb_zero = 6656;
int tmp_cost;
ffc dig_10000;
ffc dig_1000;
ffc dig_100;
ffc dig_10;
ffc dig_1;
//Cost display routine
//Load needed digit ffcs
dig_10000 = Screen->LoadFFC(ffc_num+1);
dig_1000 = Screen->LoadFFC(ffc_num+2);
dig_100 = Screen->LoadFFC(ffc_num+3);
dig_10 = Screen->LoadFFC(ffc_num+4);
dig_1 = Screen->LoadFFC(ffc_num+5);
//put them in location
dig_10000->X = this->X-12;
dig_10000->Y = this->Y+18;
dig_1000->X = this->X-4;
dig_1000->Y = this->Y+18;
dig_100->X = this->X+4;
dig_100->Y = this->Y+18;
dig_10->X = this->X+12;
dig_10->Y = this->Y+18;
dig_1->X = this->X+20;
dig_1->Y = this->Y+18;
//display the digits
tmp_cost = cost_is;
dig_10000->Data = cmb_zero + Floor(tmp_cost*0.0001);
if(Floor(tmp_cost*0.0001) > 0) {tmp_cost -= (Floor(tmp_cost*0.0001)*10000);}
if (dig_10000->Data == cmb_zero) {
dig_10000->Data = 0;
dig_1000->X -=4;
dig_100->X -=4;
dig_10->X -=4;
dig_1->X -=4;
}
dig_1000->Data = cmb_zero + Floor(tmp_cost*0.001);
if(Floor(tmp_cost*0.001) > 0) {tmp_cost -= (Floor(tmp_cost*0.001)*1000);}
if(dig_1000->Data == cmb_zero && dig_10000->Data == 0) {
dig_1000->Data = 0;
dig_100->X -=4;
dig_10->X -=4;
dig_1->X -=4;
}
dig_100->Data = cmb_zero + Floor(tmp_cost*0.01);
if(Floor(tmp_cost*0.01) > 0) {tmp_cost -= (Floor(tmp_cost*0.01)*100);}
if (dig_100->Data == cmb_zero && dig_1000->Data == 0) {
dig_100->Data = 0;
dig_10->X -=4;
dig_1->X -=4;
}
dig_10->Data = cmb_zero + Floor(tmp_cost*0.1);
if(Floor(tmp_cost*0.1) > 0) {tmp_cost -= (Floor(tmp_cost*0.1)*10);}
if (dig_10->Data == cmb_zero && dig_100->Data == 0) {
dig_10->Data = 0;
dig_1->X -=4;
}
dig_1->Data = cmb_zero + Floor(tmp_cost/1);
//Main Loop
while(true) {
Waitframe();
if(this->Data != 0 && Link->X >= this->X-8 && Link->X <= this->X +24 && Link->Y >= this->Y-8 && Link->Y <= this->Y+24 && Game->Counter[1] >= cost_is && is_spending == 0)
{
this->Data = 0;
dig_10000->Data = 0;
dig_1000->Data = 0;
dig_100->Data = 0;
dig_10->Data = 0;
dig_1->Data = 0;
if (ctr_ref == -1) {Link->Item[item_is]=true;} else {Game->Counter[ctr_ref] += ctr_amt;}
if (hands == 2) {Link->Action = 5;}
if (hands == 1) {Link->Action = 4;}
Link->HeldItem = item_is;
if (msg != 0) {Screen->Message(msg);}
hold_time = 30;
Game->PlaySound(20)
Game->Counter[1] -= cost_is;

}
}
}
}

global script main_script {
void run() {
while(true) {
//Put other global scripts here

if (hold_time == 0) {Link->Action = 0;} else {hold_time -= 1;}
Waitframe();
}
}
}



Uses drawing functions instead of FFC's to display numbers (instant rupie take version)
This version only takes one FFC per item so if you really wanted to you could make a shop with up to 32 items!
Okay, I don't know if anyone is that insane, but you could do it if you wanted to :D


ffc script shop_item {
void run(int item_is, int cost_is, int hands, int ctr_ref, int ctr_amt, int ffc_num, int msg) {
int cmb_zero = 6656;
int tmp_cost;
int dig_10000;
int dig_1000;
int dig_100;
int dig_10;
int dig_1;
int dig_10000x = this->X-12;
int dig_1000x = this->X-4;
int dig_100x = this->X+4;
int dig_10x = this->X+12;
int dig_1x = this->X+20;

//Cost display routine
//Load needed digit ffcs
//DrawTile(int layer, int x, int y, int tile, int blockw, int blockh, int cset, float scale, int rx, int ry, int rangle, int flip, bool transparency, int opacity)
//calculate stuff
tmp_cost = cost_is;
dig_10000 = cmb_zero + Floor(tmp_cost*0.0001);
if(Floor(tmp_cost*0.0001) > 0) {tmp_cost -= (Floor(tmp_cost*0.0001)*10000);}
if (dig_10000 <= cmb_zero) {
dig_10000x = -1;
dig_1000x -=4;
dig_100x -=4;
dig_10x -=4;
dig_1x -=4;
}
dig_1000 = cmb_zero + Floor(tmp_cost*0.001);
if(Floor(tmp_cost*0.001) > 0) {tmp_cost -= (Floor(tmp_cost*0.001)*1000);}
if(dig_1000 <= cmb_zero && dig_10000x == -1) {
dig_1000x = -1;
dig_100x -=4;
dig_10x -=4;
dig_1x -=4;
}
dig_100 = cmb_zero + Floor(tmp_cost*0.01);
if(Floor(tmp_cost*0.01) > 0) {tmp_cost -= (Floor(tmp_cost*0.01)*100);}
if (dig_100 <= cmb_zero && dig_1000x == -1 && dig_10000x == -1) {
dig_100x = -1;
dig_10x -=4;
dig_1x -=4;
}
dig_10 = cmb_zero + Floor(tmp_cost*0.1);
if(Floor(tmp_cost*0.1) > 0) {tmp_cost -= (Floor(tmp_cost*0.1)*10);}
if (dig_10 <= cmb_zero && dig_100x == -1 && dig_1000x == -1 && dig10000x == -1) {
dig_10x = -1;
dig_1x -=4;
}
dig_1 = cmb_zero + Floor(tmp_cost/1);
//Main Loop
while(true) {
Waitframe();
//display the digits
if (dig_10000x != -1) {Screen->DrawTile(3,dig_10000x,this->Y+18, dig_10000, 1,1,0,1,0,0,0,0,true,128);}
if (dig_1000x != -1) {Screen->DrawTile(3,dig_1000x,this->Y+18, dig_1000, 1,1,0,1,0,0,0,0,true,128);}
if (dig_100x != -1) {Screen->DrawTile(3,dig_100x,this->Y+18, dig_100, 1,1,0,1,0,0,0,0,true,128);}
if (dig_10x != -1) {Screen->DrawTile(3,dig_10x,this->Y+18, dig_10, 1,1,0,1,0,0,0,0,true,128);}
if (dig_1x != -1) {Screen->DrawTile(3,dig_1x,this->Y+18, dig_1, 1,1,0,1,0,0,0,0,true,128);}
if(this->Data != 0 && Link->X >= this->X-8 && Link->X <= this->X +24 && Link->Y >= this->Y-8 && Link->Y <= this->Y+24 && Game->Counter[1] >= cost_is && is_spending == 0)
{
this->Data = 0;
dig_10000x == -1;
dig_1000x == -1;
dig_100x == -1;
dig_10x == -1;
dig_1x == -1;
if (ctr_ref == -1) {Link->Item[item_is]=true;} else {Game->Counter[ctr_ref] += ctr_amt;}
if (hands == 2) {Link->Action = 5;}
if (hands == 1) {Link->Action = 4;}
Link->HeldItem = item_is;
if (msg != 0) {Screen->Message(msg);}
hold_time = 30;
Game->PlaySound(20)
Game->Counter[1] -= cost_is;
}
}
}
}

You will still need the main script.

Pheonix
08-17-2007, 02:24 PM
That is too awsome to be legal. I'll have to take you away.

Seriously, that is really cool. I'll start to use that... later...

Master_of_Power
08-22-2007, 07:35 AM
If, for some reason, I do use a extremely high price, I'd like to have the variation where the rupees are just instantly subtracted, as I stated before, I perfered it that way. would you post the variation?

Link seems to freeze when item is held up, plus it doesn't play the "Got Item" jingle.

ShadowMancer
08-22-2007, 02:37 PM
Link seems to freeze when item is held up, plus it doesn't play the "Got Item" jingle
Did you put the Main_Script in global slot 2? Link should hold the item for 30 frames, if that is too long for you just change the varible hold_time to a smaller number
Snippet:


Link->HeldItem = item_is;
if (msg != 0) {Screen->Message(msg);}
//Change this varible to change how many frames link holds up item
hold_time = 30;
is_spending = cost_is;

Yes I know it does not play the sound, I will ammend that in the next update.
I will post an 'instant rupie take' variation in a few minutes just have to write it up quick

Master_of_Power
08-24-2007, 10:12 AM
Did you put the Main_Script in global slot 2? Link should hold the item for 30 frames, if that is too long for you just change the varible hold_time to a smaller number


Yes I've put the main script in global slot 2 I'll test it again... and 30 frames is what? a half a second? Just so I don't get confused:rolleyes:

Sir_Johnamus
08-24-2007, 10:24 AM
30 tics is half a second, a frame might last a tic, but it has been awhile since I have gotten technical in ZC. Correct me if I'm wrong.

This is a great script, I will definately use it.

ShadowMancer
08-24-2007, 09:53 PM
I think because i used a counter and a waitframe inbetween each deincriment it goes by frames, which would depend on FPS which from what I understand varries depending on how much is 'happening' in the game at the time (remember the old NES games when alot of enemies etc, were on the screen and the game sloooowed down, the FPS would decrease because of increased processing demand) Don't quote me on any of this as I am trying to remeber technical stuff from way back in my data banks. I have no idea how 'tics' are measured so you may be right Sir_Johnamus .

I just thought also what may cause Link to get frozen in holding is if you did not put in the global varibles:
int is_spending = 0;
int hold_time = 0;
But I don't think the script would complie if those were left out, just a thought.

If a couple ppl would not mind testing out the script to see if they get the same 'frozen Link bug' it would be helpful. It worked perfectly in my tests.

ShadowMancer
10-12-2007, 07:04 PM
UPDATE: I edited the script to use drawing functions instead of useing all your FFC's for the screen, now you make the hyrule mega-mart with up to 32 items for sale if you want to. Script is in the first post, this post's only purpose is *BUMP*

AgentLym
06-01-2008, 08:25 PM
I hope I'm not 'grave-digging'... well, I probably am, but I hope 'grave-digging' isn't one of the rules here...:tongue:

Well, I'm having troubles. Link gets the item ok, but even if you don't intend to get the item, Link still grabs it! Could you post new script so that Link only buys the item if Link is right underneath the item, instead of the current 'if Link is 16 pixels to the right or 16 pixels beneath' buying settings...

What happens, is if Link is even one tile to the right of the item, he buys it. And if Link is one tile beneath it, like a whole combo away, he still buys it! So I can't put two items right next to each other, otherwise, you'll have to buy both of them....

Could someone help me?