XR001's Shop Creator Script

xr001

New member
Jun 8, 2019
2
0
0
Heya Folks!

So I have gone through various different plugins that use the functionality below, but I wanted something that provided me a bit more freedom and the ability to easily integrate shops into my other scripts!

Below is the script as well as an example shop script. It is very cut and paste friendly. I have also included a video on how to actually use the script in game to make shop menus!

Feel free to send me any suggestions or ideas on how to improve this system!

Video (Please note it does not contain instructions for a Sell Items shop, see P.S.)
https://www.youtube.com/watch?v=CswUR9UZvcs&t=197s

Current Version: 1.1 (It has been overhauled before posting, see P.S.)

Code:
##Core Script##

##Inventory for the shop creator menu##
ShopCreatorInv:
  type: inventory
  display name: Shop Editor
  size: 54
  slots:
  - "[] [] [] [] [] [] [] [] []"
  - "[] [] [] [] [] [] [] [] []"
  - "[] [] [] [] [] [] [] [] []"
  - "[] [] [] [] [] [] [] [] []"
  - "[] [] [] [] [] [] [] [] [i@SaveShopIt]"
  - "[i@ClearCostIt] [i@CostMinus1It] [i@CostMinus10It] [i@CostMinus100It] [i@CostMinus1000It] [i@CostPlus1It] [i@CostPlus10It] [i@CostPlus100It] [i@CostPlus1000It]"
  Procedural Items:
  - if <player.has_flag[EditShop]> && <player.has_flag[AdjustedCost].not>:
    - determine <yaml[<player.flag[EditShop].get[1]>].read[<player.flag[EditShop].get[2]>]>
    - queue clear
  - if <player.has_flag[AdjustedCost]>:
    - determine <player.flag[AdjustedCost]>

##World script to handle Shop Creator Inventory##
ShopCreatorHandler:
  type: world
  debug: true
  events:
    on player clicks in ShopCreatorInv:
##Prevent players from placing Shop Menu items in other slots of the menu##
    - if <context.cursor_item.has_nbt[ShopMenuItem]>:
      - determine passively cancelled
##Prevent players from placing Cost Adjustment items into their inventory##
    - if <context.cursor_item.has_nbt[Cost]> && <context.raw_slot.is[==].to[-998]>:
      - determine passively cancelled
      - queue clear
    - if <context.raw_slot> > 54:
      - if <context.cursor_item.has_nbt[ShopMenuItem]>:
        - determine passively cancelled
        - narrate "You can't use that there!"
        - queue clear
##Prevent a player from placing an adjusted item into their inventory##
      - if <context.cursor_item.has_nbt[Cost]>:
        - determine passively cancelled
        - narrate "Click on ClearCost to reset an item!."
        - queue clear
      - else:
        - queue clear
##Prevent replacing items with Shop Creator Items##
    - if <context.cursor_item.has_nbt[ShopMenuItem].not> && <context.cursor_item.contains[i@air].not>:
      - if <context.item.has_nbt[ShopMenuItem]>:
        - determine passively cancelled
        - queue clear
##Initial lore adjustment to add Cost: $0##
      - if <context.cursor_item.has_nbt[Cost].not>:
        - nbt <context.cursor_item> Cost:0 save:adjustedcost
        - if <context.cursor_item.lore.size||0> == 0:
          - if <player.has_flag[SellShop]>:
            - adjust <entry[adjustedcost].new_item> "lore:Click Here to Sell! Offer: $<entry[adjustedcost].new_item.nbt[Cost]>" save:adjustedcost
          - else:
            - adjust <entry[adjustedcost].new_item> "lore:Click Here to Buy! Cost: $<entry[adjustedcost].new_item.nbt[Cost]>" save:adjustedcost
        - else:
          - adjust <entry[adjustedcost].new_item> "lore:<entry[adjustedcost].new_item.lore.include[Click Here to Buy! Cost: $<entry[adjustedcost].new_item.nbt[Cost]>]>" save:adjustedcost
        - flag player AdjustedCost:<player.open_inventory.list_contents.set[<entry[adjustedcost].result>].at[<context.slot>]>
        - adjust <player> item_on_cursor:i@air
        - inventory open d:in@ShopCreatorInv
        - flag player AdjustedCost:!
        - queue clear
##Add Cost Item To Cursor##
    - if <context.item.nbt[ShopMenuItem]||0> > 0 || <context.item.nbt[ShopMenuItem]||0> < 0:
      - determine passively cancelled
      - if <context.cursor_item.simple> == <context.item.simple>:
        - if <player.item_on_cursor.quantity> == 64:
          - queue clear
        - else:
          - adjust <context.cursor_item> quantity:<context.cursor_item.quantity.add[1]> save:AdjustCost
          - adjust <player> item_on_cursor:<entry[AdjustCost].result>
          - queue clear
      - else:
        - if <context.item.nbt[ShopMenuItem]> != Save && <context.item.nbt[ShopMenuItem]> != Clear:
          - adjust <player> item_on_cursor:<context.item>
##Add/Subtract Cost##
    - if <context.raw_slot> > 54 && <context.cursor_item.has_nbt[ShopMenuItem]>:
      - determine passively cancelled
      - adjust <player> item_on_cursor:i@air
      - queue clear
    - if <context.item.has_nbt[Cost]> && <context.cursor_item.has_nbt[ShopMenuItem]>:
      - if <context.cursor_item.nbt[ShopMenuItem]> == Clear:
        - queue clear
      - if <context.item.nbt[Cost].add[<context.cursor_item.nbt[ShopMenuItem].mul[<context.cursor_item.quantity>]>]> < 0:
        - determine passively cancelled
        - narrate "You cannot have a cost go below 0!"
        - queue clear
      - adjust <context.item> nbt:Cost/<context.item.nbt[Cost].add[<context.cursor_item.nbt[ShopMenuItem].mul[<context.cursor_item.quantity>]>]> save:adjustedcost
      - adjust <entry[adjustedcost].result> "lore:<entry[adjustedcost].result.lore.set[Click Here to Buy! Cost: $<entry[adjustedcost].result.nbt[Cost]>].at[<entry[adjustedcost].result.lore.size>]>" save:adjustedcost
      - flag player AdjustedCost:<player.open_inventory.list_contents.set[<entry[adjustedcost].result>].at[<context.slot>]>
      - define CursorStack <player.item_on_cursor>
      - adjust <player> item_on_cursor:i@air
      - inventory open d:in@ShopCreatorInv
      - adjust <player> item_on_cursor:<def[CursorStack]>
      - flag player AdjustedCost:!
##Clear Cost##
    on player left clicks ClearCostIt in ShopCreatorInv:
    - determine passively cancelled
    - if <context.cursor_item.has_nbt[cost]>:
      - adjust <context.cursor_item> "Lore:<context.cursor_item.lore.remove[<context.cursor_item.lore.size>]>" save:ClearCost
      - nbt <entry[ClearCost].result> Cost:! save:ClearCost
      - adjust <player> item_on_cursor:<entry[ClearCost].new_item>
      - narrate "Cost removed from Item."
      - flag AdjustedCost:<player.open_inventory.list_contents>
      - queue clear
    - adjust <player> item_on_cursor:i@air
    on player right clicks ClearCostIt in ShopCreatorInv:
    - determine passively cancelled
    - adjust <player> item_on_cursor:i@ClearCostIt
    on player clicks in ShopCreatorInv with ClearCostIt:
    - if <context.raw_slot> > 54 {
      - adjust <player> item_on_cursor:i@air
      - determine cancelled
      - queue clear
      }
    - if <context.item.has_nbt[ShopMenuItem]> || <context.item.contains[i@air]> {
      - determine passively cancelled
      - queue clear
      }
    - determine passively cancelled
    - adjust <context.item> nbt:Cost/0 save:adjustedcost
    - adjust <entry[adjustedcost].result> "lore:<entry[adjustedcost].result.lore.set[Click Here to Buy! Cost: $<entry[adjustedcost].result.nbt[Cost]>].at[<entry[adjustedcost].result.lore.size>]>" save:adjustedcost
    - flag player AdjustedCost:<player.open_inventory.list_contents.set[<entry[adjustedcost].result>].at[<context.slot>]>
    - define CursorStack <player.item_on_cursor>
    - adjust <player> item_on_cursor:i@air
    - inventory open d:in@ShopCreatorInv
    - adjust <player> item_on_cursor:<def[CursorStack]>
    - flag player AdjustedCost:!
##Save and Exit##
    on player clicks SaveShopIt in ShopCreatorInv:
    - determine passively cancelled
    - narrate "Shop Inventory:<player.flag[ShopCreator].get[2]> has been saved to File:<player.flag[ShopCreator].get[1]>.yml!"
    - if <player.has_flag[EditShop]>:
      - yaml id:<player.flag[ShopCreator].get[1]> set <player.flag[ShopCreator].get[2]>:!
    - foreach <player.open_inventory.list_contents.get[1].to[44]>:
      - yaml id:<player.flag[ShopCreator].get[1]> set <player.flag[ShopCreator].get[2]>:->:<def[value]>
    - yaml savefile:/Shops/<player.flag[ShopCreator].get[1]>.yml id:<player.flag[ShopCreator].get[1]>
    - yaml unload id:<player.flag[ShopCreator].get[1]>
    - flag player SellShop:!
    - flag player AdjustedCost:!
    - flag player EditShop:!
    - flag player ShopCreator:!
    - inventory close
    
ShopCreatorCmd:
  type: command
  name: createshop
  usage: /createshop
  description: "Use to create a list for a Denizen shop script. /createshop File:<&lc>FileName<&rc> Shop:<&lc>ShopName<&rc> | add Delete to delete a shop | add Edit to edit an existing shop."
  permission: denizen.shopcreator
  script:
    - if <player.has_flag[EditShop]> || <player.has_flag[ShopCreator]>:
      - flag player EditShop:!
      - flag player ShopCreator:!
      - flag player SellShop:!
##Delete Shop##
    - if <context.args.contains[Delete]>:
      - if <server.has_file[/Shops/<context.args.map_get[File].split_by[<&co>]>.yml].not>:
        - narrate "The File: <context.args.map_get[File].split_by[<&co>]>.yml does not exist! Did you type it in correctly?"
        - queue clear
      - yaml load:/Shops/<context.args.map_get[File].split_by[<&co>]>.yml id:<context.args.map_get[File].split_by[<&co>]>
      - if <yaml[<context.args.map_get[File].split_by[<&co>]>].contains[<context.args.map_get[Shop].split_by[<&co>]>].not>:
        - narrate "The Shop: <context.args.map_get[Shop].split_by[<&co>]> does not exist in File: <context.args.map_get[File].split_by[<&co>]>! Did you type it in correctly?"
        - queue clear
      - yaml id:<context.args.map_get[File].split_by[<&co>]> set <context.args.map_get[Shop].split_by[<&co>]>:!
      - yaml savefile:/Shops/<context.args.map_get[File].split_by[<&co>]>.yml id:<context.args.map_get[File].split_by[<&co>]>
      - narrate "The Shop: <context.args.map_get[Shop].split_by[<&co>]> in File: <context.args.map_get[File].split_by[<&co>]> has been deleted!"
      - queue clear
##Edit Shop##
    - if <context.args.contains[Edit]>:
      - if <player.has_flag[AdjustedCost]>:
        - flag player AdjustedCost:!
      - if <server.has_file[/Shops/<context.args.map_get[File].split_by[<&co>]>.yml].not>:
        - narrate "The File: <context.args.map_get[File].split_by[<&co>]>.yml does not exist! Did you type it in correctly?"
        - queue clear
      - yaml load:/Shops/<context.args.map_get[File].split_by[<&co>]>.yml id:<context.args.map_get[File].split_by[<&co>]>
      - if <yaml[<context.args.map_get[File].split_by[<&co>]>].contains[<context.args.map_get[Shop].split_by[<&co>]>].not>:
        - narrate "The Shop: <context.args.map_get[Shop].split_by[<&co>]> does not exist in File: <context.args.map_get[File].split_by[<&co>]>! Did you type it in correctly?"
        - queue clear
      - flag player EditShop:|:<context.args.map_get[File].split_by[<&co>]>|<context.args.map_get[Shop].split_by[<&co>]>
      - flag player ShopCreator:|:<context.args.map_get[File].split_by[<&co>]>|<context.args.map_get[Shop].split_by[<&co>]>
      - inventory open d:in@ShopCreatorInv
      - queue clear
##Create Shop##
    - if <server.has_file[/Shops/<context.args.map_get[File].split_by[<&co>]>.yml].not>:
      - yaml create id:<context.args.map_get[File].split_by[<&co>]>
      - yaml savefile:/Shops/<context.args.map_get[File].split_by[<&co>]>.yml id:<context.args.map_get[File].split_by[<&co>]>
      - yaml load:/Shops/<context.args.map_get[File].split_by[<&co>]>.yml id:<context.args.map_get[File].split_by[<&co>]>
    - else:
      - yaml load:/Shops/<context.args.map_get[File].split_by[<&co>]>.yml id:<context.args.map_get[File].split_by[<&co>]>
      - if <yaml[<context.args.map_get[File].split_by[<&co>]>].contains[<context.args.map_get[Shop].split_by[<&co>]>]>:
        - yaml unload id:<context.args.map_get[File].split_by[<&co>]>
        - narrate "That shop already exists! If you wish to Edit or Delete a Shop, add those arguments when using the /createshop command." 
        - queue clear 
    - flag player ShopCreator:|:<context.args.map_get[File].split_by[<&co>]>|<context.args.map_get[Shop].split_by[<&co>]>
    - inventory open d:in@ShopCreatorInv
    - if <context.args.contains[SellShop]>:
      - flag player SellShop

##Shop Creator Items##    
    
SaveShopIt:
  type: item
  display name: Save Shop
  material: i@writable_book[nbt=ShopMenuItem/Save]
  lore:
  - "Click here to save this shop inventory."

ClearCostIt:
  type: item
  display name: Clear Cursor
  material: i@barrier[nbt=ShopMenuItem/Clear]
  lore:
  - "Clicking here with a Cost Editting item"
  - "will clear it from your cursor."
  - "Right click to pick up this item."
  - "Click an item to adjust its cost to $0."
  - "With a cost adjusted item on your cursor"
  - "click here to reset the item entirely."  
  
CostPlus1It:
  type: item
  display name: Add $1
  material: i@stone[nbt=ShopMenuItem/1]
  lore:
  - "Click here to add $1 to the price"
  - "of an item. With this item in hand"
  - "click on an item. It will add $1"
  - "for each item in the held stack."

CostPlus10It:
  type: item
  display name: Add $10
  material: i@iron_block[nbt=ShopMenuItem/10]
  lore:
  - "Click here to add $10 to the price"
  - "of an item. With this item in hand"
  - "click on an item. It will add $10"
  - "for each item in the held stack."

CostPlus100It:
  type: item
  display name: Add $100
  material: i@gold_block[nbt=ShopMenuItem/100]
  lore:
  - "Click here to add $100 to the price"
  - "of an item. With this item in hand"
  - "click on an item. It will add $100"
  - "for each item in the held stack."
  
CostPlus1000It:
  type: item
  display name: Add $1000
  material: i@diamond_block[nbt=ShopMenuItem/1000]
  lore:
  - "Click here to add $1000 to the price"
  - "of an item. With this item in hand"
  - "click on an item. It will add $1000"
  - "for each item in the held stack."

CostMinus1It:
  type: item
  display name: Subtract $1
  material: i@coal_ore[nbt=ShopMenuItem/-1]
  lore:
  - "Click here to subtract $1 to the price"
  - "of an item. With this item in hand"
  - "click on an item. It will subtract $1"
  - "for each item in the held stack."

CostMinus10It:
  type: item
  display name: Subtract $10
  material: i@iron_ore[nbt=ShopMenuItem/-10]
  lore:
  - "Click here to subtract $10 to the price"
  - "of an item. With this item in hand"
  - "click on an item. It will subtract $10"
  - "for each item in the held stack."

CostMinus100It:
  type: item
  display name: Subtract $100
  material: i@gold_ore[nbt=ShopMenuItem/-100]
  lore:
  - "Click here to subtract $100 to the price"
  - "of an item. With this item in hand"
  - "click on an item. It will subtract $100"
  - "for each item in the held stack."
  
CostMinus1000It:
  type: item
  display name: Subtract $1000
  material: i@diamond_ore[nbt=ShopMenuItem/-1000]
  lore:
  - "Click here to subtract $1000 to the price"
  - "of an item. With this item in hand"
  - "click on an item. It will subtract $1000"
  - "for each item in the held stack."

##Player Shop Creation System##
PlayerShopHandler:
  type: world
  events:
    on player places PlayerShopIt:
    - flag player ShopOwner:<context.location>
    - flag player ShopCreator:|:PlayerShops|<player.uuid>|<context.location>
    - inventory open d:in@ShopCreatorInv
    on player closes ShopCreatorInv:
    - foreach <player.inventory.list_contents>:
      - if <def[value].contains[i@ClearCostIt]> || <def[value].contains[i@CostMinus1000It]> || <def[value].contains[i@CostMinus100It]> || <def[value].contains[i@CostMinus10It]>  || <def[value].contains[i@CostMinus1It]> || <def[value].contains[i@CostPlus1000It]> || <def[value].contains[i@CostPlus100It]> || <def[value].contains[i@CostPlus10It]> || <def[value].contains[i@CostPlus1It]>:
        - take <def[value]> quantity:<def[value].quantity>
##Player Shop Creation Item##
PlayerShopIt:
  type: item
  material: sign
  display name: Shop Post
  lore:
  - "Congratulations! You're the proud owner"
  - "of a Personal Shop Post. Simply place"
  - "this sign anywhere you're allowed to"
  - "setup your own Personal Shop! Others will"
  - "be able to purchase items you place there!"
  - "Should you need to restock, simply right"
  - "click this sign!"
##Example Shop##
GenericShopInv:
  type: inventory
  display name: Shop Name Here
  size: 45
  slots:
  - "[] [] [] [] [] [] [] [] []"
  - "[] [] [] [] [] [] [] [] []"
  - "[] [] [] [] [] [] [] [] []"
  - "[] [] [] [] [] [] [] [] []"
  - "[] [] [] [] [] [] [] [] []"
  Procedural Items:
  - determine <yaml[FileName].read[ShopName]>

NPCAssignment:
  type: assignment
  actions:
    on assignment:
      - trigger name:click state:true
    on click:
      - narrate "Greeting Here"
      - yaml load:/Shops/FileName.yml id:ShopName
      - wait 2
      - inventory open d:in@GenericShopInv
      - yaml unload id:ShopName
    
ShopMenuHandler:
  type: world
  events:
    on player drags in GenericShopInv:
    - determine cancelled
    on player clicks in GenericShopInv:
    - determine passively cancelled
    - if <context.item.has_nbt[Cost]>:
      - if <player.money.is[MORE].to[<context.item.nbt[Cost]>]>:
        - if <player.inventory.is_full>:
          - narrate "Your inventory is full!"
          - queue clear
        - take money quantity:<context.item.nbt[Cost]>
        - adjust <context.item> "Lore:<context.item.lore.remove[<context.item.lore.size>]>" save:Item
        - nbt <entry[Item].result> Cost:! save:Item
        - give <entry[Item].new_item>
        - narrate "$<context.item.nbt[Cost]> has been removed from your wallet."
        - flag player TotalSpent:+:<context.item.nbt[Cost]>
        - queue clear
      - else:
        - narrate "You don't have enough money! Cost: $<context.item.nbt[Cost]> Your Money: $<player.money>"
        - queue clear

P.S.

The ability to make a shop where players can sell items has been added but was not part of the original video!
When using the /createshop command add the argument SellShop at the end of the command and the system will create a shop for selling items too! Everything works exactly the same way accept when you make the script for the Sell Items menu make sure that it is checking if the player has the items in question and change the take money commands accordingly.
With the right knowledge this script allows for VERY customizable shops. Hit me up if you need ideas on different ways to utilize this system!
 

Klawdek

New member
Jul 13, 2019
1
0
0
I am going to check out your script it may help me with my problem. Thank you for posting it. What I need is to be able to set up a shop that sells items for 2nd tier currency items. Presently there are no plugins that are being updated that can do this. The plugin I was using is no longer being updated. https://www.spigotmc.org/resources/shop-conjurate-now-in-1-13-2.66651/

No other shop plugin allows using special items as currency, yet I see other servers that do it. THey must be using their own plugins :(

It would be neat if you added such a feature to this script.