Jump to content

Photo

One Time Shop Items?


  • Please log in to reply
12 replies to this topic

#1 Seraphin Eveles

Seraphin Eveles

    Insert Title Here

  • Members

Posted 13 June 2023 - 12:42 PM

I'm trying to figure out if there's a way to make certain shops, or certain items, only able to be bought once. I.e., the Blue Ring only needs to be bought once in the original quest, but reappears in the shop after purchasing, and can be repurchased for no reason.

 

Edit: Currently using 2.55a113


Edited by SeraphinEveles, 13 June 2023 - 02:30 PM.


#2 Twilight Knight

Twilight Knight

    Tell all with glee, Argon's on PureZC

  • Members
  • Real Name:Sven
  • Location:Rotterdam, NL

Posted 20 June 2023 - 04:21 AM

I'm trying to figure out if there's a way to make certain shops, or certain items, only able to be bought once. I.e., the Blue Ring only needs to be bought once in the original quest, but reappears in the shop after purchasing, and can be repurchased for no reason.

 

Edit: Currently using 2.55a113

This might be possible with scripting by changing the shopdata https://www.zeldacla...?jump=shopdata 

 

Are you familiar with scripting?

Also I should add there are already scripts available that can do this, but you'd have to drop the classical Zelda shop thing. Here are 2 scripts:
https://www.purezc.n...scripts&id=386 
https://www.purezc.n...=scripts&id=360


Edited by Twilight Knight, 20 June 2023 - 04:24 AM.


#3 Seraphin Eveles

Seraphin Eveles

    Insert Title Here

  • Members

Posted 20 June 2023 - 10:33 AM

I'm not familiar, but I'd be willing to take a look at some things. Thanks!



#4 Seraphin Eveles

Seraphin Eveles

    Insert Title Here

  • Members

Posted 20 June 2023 - 02:29 PM

Ok, ya, not enough of that scripting (looking at the two posted ones as examples) makes sense to me.

 

If someone wants to take the time to make a script to make it work, I'd essentially just like to have the original looking shops, and some way to make items not show in the shop after buying them, in some configurable way. I'm sure there's a way it can be done, based on what I do understand from the scripts, but I don't understand enough to do it myself.


Edited by SeraphinEveles, 20 June 2023 - 02:30 PM.


#5 Twilight Knight

Twilight Knight

    Tell all with glee, Argon's on PureZC

  • Members
  • Real Name:Sven
  • Location:Rotterdam, NL

Posted 21 June 2023 - 04:27 AM

Sure I can help you with that tonight

Please feel free to remind me if I forget about it :-)



#6 Twilight Knight

Twilight Knight

    Tell all with glee, Argon's on PureZC

  • Members
  • Real Name:Sven
  • Location:Rotterdam, NL

Posted 21 June 2023 - 02:13 PM

// If you already have this imported you need to omit this line
import "std.zh"

// We need to keep track of the items because shopdata resets after saving the game
// And we can't just use Hero->Item[] for that as you probably don't want half potions to be removed for example
bool removeTheseItems[256];

/*
* Removes all items from shops that have the "removeItemFromShops" script
*/
void removeItemsFromShops() {
    // Loop over all potential shops to check if this item is sold
    for (int shopId = 0; shopId < 256; shopId++) {
        shopdata shop = Game->LoadShopData(shopId);

        // 1 == the regular shop type
        if (shop->Type == 1) {
            // Shop can have 3 items at most
            for (int i = 0; i < 3; i++) {
                // Remove the item from the shop if Link has it
                if (removeTheseItems[shop->Item[i]]) {
                    shop->HasItem[i] = false;
                }
            }
        }
    }
}

/*
* The shopdata resets after saving the game, so you need to remove the items again when continuing
* If you already have a onContinueGame script set, add removeItemsFromShops(); there
*/
global script continueGame
{
    void run()
    {
        removeItemsFromShops();
    }
}

/*
* Mark this item as one that should be removed from shops and then remove the item
* We need to keep track of the items because shopdata resets after saving the game
*/
item script removeItemFromShops
{
	void run() 
	{
        removeTheseItems[this->ID] = true;

        removeItemsFromShops();
	}
} 

 
Alright it was a little more challenging than expected, because the shop data resets after you save the game, but this should work for you.

If you're not familiar with setting up scripts: save this with notepad as a ".z" file (save as with double quotes to save as that type, f.e. "myquest_scripts.z"). Then compile it in ZQuest (press Y) and be sure to set the global and item scripts to the correct slot. All you need to do is add the global script to the "onContGame" slot and the item script to the first slot available.

Then in the item editor you can set the item passive script on whatever item you don't want resold in shops. Mind you this is permanent for now.

 

This way you have some control over what items are resold, which should work well for your use case and you could use it for other rings as well.



#7 Seraphin Eveles

Seraphin Eveles

    Insert Title Here

  • Members

Posted 21 June 2023 - 05:02 PM

Ok, so, it seems like I was able to get the script added, but I'm not seeing the "passive" script anywhere in the item editor.

 

EDIT:
I see what I did wrong! Gonna do some testing.


Edited by SeraphinEveles, 21 June 2023 - 05:11 PM.


#8 Seraphin Eveles

Seraphin Eveles

    Insert Title Here

  • Members

Posted 21 June 2023 - 05:22 PM

Ok, so, after doing a bit of testing, it seems to remove some shop items that aren't owned. For example, I have a shop that has the Silver Arrow and the Long Bow in it, and buying the Arrow removed the Bow, making the shop empty.

 

EDIT:

Both items have the remove from shop flag. But it also happened with a shop that has a quiver (which has the script) and 2 items that do not, and all 3 were removed.

 

EDIT2:

Interestingly, for the bow & arrow shop, buying the arrow first (item 1) removes the bow from the shop. Buying the Bow first (item 2) does not remove the arrow, but purchasing the arrow afterwards does not grant the player the arrow. Both items have the script.

 

EDIT3:

The other notable shop is the hidden one on 1:46. Buying the quiver I put there in slot 1 removes the Bait and recovery heart, neither of which have the script. (noted in EDIT1)

Same happens for the shop on 1:12, which is a duplicate shop.

 

EDIT4:

With doing a bit more testing, it appears to be an issue with buying an item in the first slot of a shop that has the script attached to it.

 

EDIT5:

Actually, it seems to be that buying an item with the script attached removes any subsequent items. i.e., buying item1 removes item2 and item3, but buying item2 only removes item3 and not item1.


Edited by SeraphinEveles, 21 June 2023 - 05:51 PM.


#9 Twilight Knight

Twilight Knight

    Tell all with glee, Argon's on PureZC

  • Members
  • Real Name:Sven
  • Location:Rotterdam, NL

Posted 22 June 2023 - 02:06 AM

That doesn't make sense, can you share your quest file with me?

 

All the script is removing are items with the exact same ID. Well theoretically, I tested it only a little bit



#10 Seraphin Eveles

Seraphin Eveles

    Insert Title Here

  • Members

Posted 22 June 2023 - 06:52 AM

Are you on discord?

#11 Twilight Knight

Twilight Knight

    Tell all with glee, Argon's on PureZC

  • Members
  • Real Name:Sven
  • Location:Rotterdam, NL

Posted 22 June 2023 - 09:05 AM

Are you on discord?

Yes, in the PureZC server



#12 Twilight Knight

Twilight Knight

    Tell all with glee, Argon's on PureZC

  • Members
  • Real Name:Sven
  • Location:Rotterdam, NL

Posted 27 June 2023 - 08:42 AM

Alright, we sorted this out on Discord but here's the updated script for those also needing this (even if it's years from now):

// If you already have this imported you need to omit this line
import "std.zh"

// We need to keep track of the items because shopdata resets after saving the game
// And we can't just use Hero->Item[] for that as you probably don't want half potions to be removed for example
bool removeTheseItems[256];

/*
* Removes all items from shops that have the "removeItemFromShops" script
*/
void removeItemsFromShops() {
    // Loop over all potential shops to check if this item is sold
    for (int shopId = 0; shopId < 256; shopId++) {
        shopdata shop = Game->LoadShopData(shopId);

        // 1 == the regular shop type
        if (shop->Type == 1) {
            bool shopItemsChanged = false;
            int shopItems[3] = {
                0,
                0,
                0
            };
            int shopPrices[3] = {
                0,
                0,
                0
            };
            int shopItemIndex = 0;

            // Loop over the current shop items to check if some items need to be removed
            for (int i = 0; i < 3; i++) {
                // This item should not be sold anymore
                if (removeTheseItems[shop->Item[i]]) {
                    shopItemsChanged = true;
                }
                // These items should still be sold
                else {
                    shopItems[shopItemIndex] = shop->Item[i];
                    shopPrices[shopItemIndex] = shop->Price[i];
                    shopItemIndex++;
                }
            }

            // Items have changed, adjust the shop items
            if (shopItemsChanged) {
                for (int i = 0; i < 3; i++) {
                    if (shopItems[i] != 0) {
                        shop->Item[i] = shopItems[i];
                        shop->Price[i] = shopPrices[i];
                    } else {
                        shop->Item[i] = -1;
                        shop->Price[i] = 0;
                        shop->HasItem[i] = false;
                    }
                }
            }
        }
    }
}

/*
* The shopdata resets after saving the game, so you need to remove the items again when continuing
* If you already have a onContinueGame script set, add removeItemsFromShops(); there
*/
global script continueGame
{
    void run()
    {
        removeItemsFromShops();
    }
}

/*
* Mark this item as one that should be removed from shops and then remove the item
* We need to keep track of the items because shopdata resets after saving the game
*/
item script removeItemFromShops
{
	void run()
	{
        removeTheseItems[this->ID] = true;

        removeItemsFromShops();
	}
}

Note that there is an engine bug with setting shopdata->Price[] right now, but it's been reported and this will surely be fixed in some near-future build



#13 Jamian

Jamian

    ZC enthusiast

  • Members

Posted 04 July 2023 - 01:57 PM

Unless you insist on using the built-in Z1 caves (which I stopped using around the time of Promised Lands... it doesn't take that much effort to create custom caves, and it allows for so much more customization), I think it would be much simpler to just use an FFC script on the shop screen itself, that would change the shop type if the player already owns an item.


  • Twilight Knight likes this


1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users