chess123mate

Original answer to Scripting Helpers question

Sep 17th, 2017
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.89 KB | None | 0 0
  1. When creating a table in lua, both commas and semicolons mean the same thing. As it happens, you could reorganize your table creation like this and it would mean the same thing:
  2.  
  3. `local products = {50, 100, 250, 500, 1000, 1500, Gold50 = 0, Gold100 = 0, etc}`
  4.  
  5. (Note that `0` is the same as `000000` in lua.)
  6.  
  7. What you're wanting is to have a table within a table. You have a number of options available for organization:
  8.  
  9. 1. Use `{Gold50 = {0, 50}, etc}`
  10. 2. Use `{Gold50 = {ID=0, Price=50}, etc}`
  11. 3. Use `{0 = {Name = "Gold", Offers = {{Amount = 50, Price = 50}, {Amount = 100, Price = 100}, otherDealsHere}}, 1 = {Name = "Name of item ID1", etc}}`
  12. 4. Use `{Gold = {[50]=50, [100]=100, etc}, etc}`
  13.  
  14. Option 1 is the closest to what you're already trying to do, but it is the least descriptive -- when you're using it in your code you'll have cryptic `product[2]` phrases that will only make sense if you've looked at the `products` table relatively recently and remember that `product[2]` means `price`
  15.  
  16. Option 2 is an improvement over #1 because it uses keys to describe what each value is. With this one, you do things like `product.Price`. If you prefer, you can get a similar effect by using option 1 with constants (which I like to put in ALL-CAPS to indicate that it is a constant):
  17.  
  18. ~~~~~~~~~~~~~~~~~
  19. local products = {Gold50 = {0, 50}, etc}
  20. local ID = 1
  21. local PRICE = 2
  22.  
  23. --elsewhere:
  24. local product = products.Gold50
  25. local price = product[PRICE]
  26. ~~~~~~~~~~~~~~~~~
  27.  
  28. Option 3's key is the ID of the product; its value includes a listing of all the offers and their associated prices. I don't recommend using it, but I leave it there as an illustration of what you can do with nested tables.
  29.  
  30. Option 4 skips the ID and has a simpler format than option 3 -- I highly recommend considering this unless you really need the ID for something. Why use a number when you could use a string? Well, encoding it in the datastores would be one reason, and ensuring that you can change the name later would be a 2nd, but if you do need the ID, you can just do this: `{Gold = {ID=0, [50]=50, [100]=100, etc}, etc}` The "[50]" is the key, the "50" is the value - I suggest that the key is the amount of gold you're offering and the value is the price you're selling it for. Notably, that "50" is not a string (though you could make it so by putting it in quotes).
  31.  
  32.  
  33. Another option to consider is to use classes. This is really only needed if you want to attach functions to your tables. A simple way of setting them up in this case (using option 4):
  34.  
  35. ~~~~~~~~~~~~~~~~~
  36. function Product(id, name, offers)
  37. local self = {}
  38. -- Option 1: assign variables directly to self
  39. self.id = id
  40. self.name = name
  41. self.offers = offers
  42. -- Option 2: keep the variables private (so don't have the above 3 lines) and have functions for acessing them
  43. function self:GetID() return id end
  44. --same idea for the other 2
  45. --Now you put any other functions here, like:
  46. function self:GetPriceForOffer(amount)
  47. return offers[amount] -- or "self.offers[amount]" if using option 1
  48. end
  49. return self
  50. end
  51. --You can use inheritance to to make this more useful:
  52. function Gold()
  53. local self = Product(0, "Gold", {[50]=50, etc})
  54. function self:ApplyOffer(player, amount)
  55. _G.awardGold(player, amount)
  56. end
  57. return self
  58. end
  59. ~~~~~~~~~~~~~~~~~
  60. Even if you don't want to use classes, I recommend at least using a function:
  61. ~~~~~~~~~~~~~~~~~
  62. local products = {}
  63. function CreateProduct(id, name, offers)
  64. products[id] = {Name = name, Offers = offers}
  65. end
  66. CreateProduct(0, "Gold", {[50]=50, [100]=95, etc})
  67. ~~~~~~~~~~~~~~~~~
  68.  
  69. The value of this is that you can change how you store `products` by changing a single line rather than rewriting your entire `products` declaration (which may have 10s or 100s of lines!) You can even do this:
  70.  
  71. ~~~~~~~~~~~~~~~~~
  72. local products = {}
  73. function CreateProduct(id, name, offers)
  74. local product = {ID = id, Name = name, Offers = offers}
  75. products[id] = product
  76. products[name] = product
  77. end
  78. CreateProduct(0, "Gold", {[50]=50, [100]=95, etc})
  79. ~~~~~~~~~~~~~~~~~
  80. You can now access Gold with `products[0]` and `products.Gold` - whatever is needed!
  81.  
  82. As for the rest of your script, you have a few more problems:
  83.  
  84. - You should only assign to `ProcessReceipt` once (see [the API on it](http://wiki.roblox.com/index.php?title=API:Class/MarketplaceService/ProcessReceipt)), not every time a purchaseEvent occurs. It must handle all possible purchases. Possibly, each product should also have a function like `ApplyOffer` (which I demonstrated with the classes, but you can just add as a fourth argument to `CreateProduct` just as well). Then your ProcessReceipt function just needs to `product:ApplyOffer(player, amount)` -- much simpler than a whole series of if/elseif's! Also note that your structure is incorrect. Though it is true that ProcessReceipt will be called multiple times, you're supposed to return `Enum.ProductPurchaseDecision.PurchaseGranted` when you succeed (and you *should* only do this after saving what they purchased to a datastore *successfully*). Check the example in the link I provided at the beginning of this point for an example.
  85. - I recommend against using _G - ModuleScripts are meant to serve this purpose (and you can guarantee that the function has been declared since you first have to `require` it)
  86. - Minor note: You shouldn't need to make sure that `player` exists (at least based on the RemoteEvents tutorial); if somehow the information that the player left arrived to the server before the information that they requested a purchase, Roblox probably doesn't fire the OnServerEvent at all. Alternatively, if you'd like to be guaranteed error-free, you might also make sure that `player.Parent` exists also: `if player and player.Parent then`. You can save on an indent for the rest of your function by inverting it and returning: `if not player or not player.Parent then return end` - however, this is a stylistic choice.
Advertisement
Add Comment
Please, Sign In to add comment