How to design a "Dynamic inventory system" for a point and click game? - lua

I have done lots of research on invetory system for point and click game in Lua and corona.
I have come across this example,I am doing something similar to this,but I need a dynamic inventory system.
I mean if I have 4 slots,and all them are full the fifth object go to next slot,so there will be an arrow to the right so I can click on ;and go to the next page.
And imagine there are 5 items,and I have 4 slots,the fifth slot would be on the next page.
I use the third item,and third slot would then be empty,so I want the fourth and fifth item automatically move back to third and fourth slot.
I have hard time figuring this out.
Thanks for advance.
local myInventoryBag={}
local maxItems = 10 -- change this to how many you want
myInventoryBag[5]=3 -- Hammer for instance
myInventoryBag[4]=7 -- A metal Pipe for instance
local function getImageForItem(thisItem)
local itemNumber = tonumber(thisItem)
local theImage=""
if itemNumber==3 then
theImage="hammer.png"
elseif itemNumber == 7 then
theImage="metalpipe.png"
elseif ... -- for other options
...
else
return nil
end
local image = display.newImage(theImage)
return image
end
local function displayItems()
local i
for i=1,#myInventoryBag do
local x = 0 -- calculate based on the i
local y = 0 -- calculate based on the i
local image = getImageForItem(myInventoryBag[i])
if image==nil then return end
image.setReferencePoint(display.TopLeftReferencePoint)
image.x = x
image.y = y
end
end

local itemImages =
{
[0] = display.newImage('MISSING_ITEM_IMAGE.PNG'),
[3] = display.newImage('hammer.png'),
[7] = display.newImage('metalpipe.png'),
}
function getImageForItem(itemId)
return itemImages[itemId] or itemImages[0]
end
local myInventoryBag={}
local maxItems = 10 -- change this to how many you want
local visibleItems = 4 -- show this many items at a time (with arrows to scroll to others)
-- show inventory items at index [first,last]
local function displayInventoryItems(first,last)
local x = 0 -- first item goes here
local y = 0 -- top of inventory row
for i=first,last do
image = getImageForItem(myInventoryBag[i])
image.x = x
image.y = y
x = x + image.width
end
end
-- show inventory items on a given "page"
local function displayInventoryPage(page)
page = page or 1 -- default to showing the first page
if page > maxItems then
-- error! handle me!
end
local first = (page - 1) * visibleItems + 1
local last = first + visibleItems - 1
displayInventoryItems(first, last)
end
myInventoryBag[5] = 3 -- Hammer for instance
myInventoryBag[4] = 7 -- A metal Pipe for instance
displayInventoryPage(1)
displayInventoryPage(2)

Basically what you would do is loop through all the inventory slots and check if the slot is empty. If it's empty, place the item in that slot and stop the loop. If it's not, go to the next one.
If you want to remove an item from the inventory, you can simply call table.delete(myInventoryBag, slotToEmpty).
For pages, you'd simply have a page variable. When drawing the inventory slots, just loop from slots (page-1) * 4 + 1 to page * 4.
(Edit: I'd highly recommend using proper indentation, as it will make the code much much more readable.)

Related

/Lua/ How to do this (idk how to call that lol)

I need to make a trolleybus number, which won't repeat for game. For example, there is a number "101" and there musn't be more "101". How to do that? I have a code, but I know, he won't work and I won't test it lol
function giveNumber()
local number = math.random(100, 199)
local takedNumbers = {}
local i = 0
local massiv = i+1
script.Parent.pered.SurfaceGui.TextLabel.Text = number
script.Parent.zad.SurfaceGui.TextLabel.Text = number
script.Parent.levo.SurfaceGui.TextLabel.Text = number
script.Parent.pravo.SurfaceGui.TextLabel.Text = number
takedNumbers[massiv] = {number}
end
script.Parent.Script:giveNumber() // what I wrote here? idk...
if number == takedNumbers[massiv] then
giveNumber()
end
i didn't test it, because I think it won't work because this code is something bad
I think this will serve your needs.
In the function generateUniqueNumber, the script loops until it found a number that is not yet in the array. (in other words, that it hasn't given out yet)
Once it found that number, it will insert it into the table to remember that it has given it out, and then it will return the number.
Then on the bottom of the script we just give the numbers to the buses :-)
--[[
Goal: Give all buses a unique number
]]
-- Variables
local takenNumbers = {};
-- This function returns a random number in the range [100, 199] that has not been taken yet
function generateUniqueNumber()
local foundNumber = false;
while not foundNumber do
randomNumber = math.random(100, 199);
if not table.find(takenNumbers, randomNumber) then
table.insert(takenNumbers, randomNumber);
return randomNumber;
end
end
end
-- This function sets the number of the bus
script.Parent.pered.SurfaceGui.TextLabel.Text = tostring(generateUniqueNumber());
script.Parent.zad.SurfaceGui.TextLabel.Text = tostring(generateUniqueNumber());
script.Parent.levo.SurfaceGui.TextLabel.Text = tostring(generateUniqueNumber());
script.Parent.pravo.SurfaceGui.TextLabel.Text = tostring(generateUniqueNumber());
2 things:
I didn't test this code as Roblox is not installed on the pc I'm currently on.
Please try formatting your code nicely next time. It greatly improves the readability! For example, you can use this website:
https://codebeautify.org/lua-beautifier
Simpler
Fill a table with free numbers...
local freenumbers = {}
for i = 1, 99 do freenumbers[i] = i + 100 end
...for every new takennumbers use table.remove() on freenumbers
local takennumbers = {}
if #freenumbers > 0 then
takennumbers[#takennumbers + 1] = table.remove(freenumbers, math.random(1, #freenumbers))
end

Lua spawnpoint random

my problem is that he uses all 3 spawn points instead of only 1 of the 3 that I put there to choose from
YY_Pos = {}
YY_Pos[1] = {m=3017299663, x=1700, y=13154, z=2450}
YY_Pos[2] = {m=3017299663, x=1775, y=12413, z=2436}
YY_Pos[3] = {m=3017299663, x=1775, y=12413, z=2500}
function YY_tmhz_1_OnCreatureDisappear(MapID, InstanceID, Creatur ID, x, y, z)
for i = 1,3 do
local Index_pos = math.random(1,3)
local CreatureID = map.MapCreateCreature(YY_Pos[i].m, InstanceID, 1534207, YY_Pos[i].x, YY_Pos[i].y, YY_Pos[i].z)
end
end
You create a random value Index_pos but you never use it.
Instead you use the loop counter variable i to index your coordinate table.
Also note that the code as is will not use 1 of three coordinates but 3 random coordinates.
You would have to move the math.random call out of the loop if you want to do something 3 times for the same random index.

Connecting a grid up with rope constraints

I'm trying to make a kind of "cloth simulation" by using ROBLOX's new rope constraints and a grid of parts.
Currently, I've made a 10x10 grid of .4x.4x.4 blocks and now I want to connect each one up with rope constraints.
I've named each part in the grid after their row and column (eg: first part in the grid being 1 1, last one being 10 10)
and then I get the parts around each individual grid part using their name and string manipulation.
I then insert 4 attachments into each part and 4 rope constraints.
Here's the code (ab stands for above, be stands for below, etc) :
for i2 = 1, #gParts do
local ab = tostring(tonumber(gParts[i2].Name:match("^(%S+)"))-5).." "..tostring(tonumber(string.sub(gParts[i2].Name,-1))-1)
local be = tostring(tonumber(gParts[i2].Name:match("^(%S+)"))+5).." "..tostring(tonumber(string.sub(gParts[i2].Name,-1))+1)
local le = tostring(tonumber(gParts[i2].Name:match("^(%S+)"))-1).." "..tostring(tonumber(string.sub(gParts[i2].Name,-1)))
local ri = tostring(tonumber(gParts[i2].Name:match("^(%S+)"))+1).." "..tostring(tonumber(string.sub(gParts[i2].Name,-1)))
for i3 = 1, 4 do
local atchm = Instance.new("Attachment",gParts[i2])
local ropeconst = Instance.new("RopeConstraint",gParts[i2])
end
end
Rope constraint has 2 main properties I need to use; attachment 1 and attachment 2.
I've never really messed with the new constraints, but I believe this should work.
Do keep in mind that the constraints are a new Instance in Roblox, and that they are likely still experimental.
X = 10;
Y = 10;
spread = 4;
--Spread is the Length of the Constraint. You may have to increase this, especially if it's stiff.
function createAttachments()
--This is under the assumption that gParts is a table filled with the Part Instances
for i,v in pairs(gParts) do
local atch = Instance.new("Attachment",v);
end;
end;
function connectConstraints(part,x,y)
if x ~= X then
connectRight = x+1.." "..y;
end;
if y ~= Y then
connectDown = x.." "..y+1;
end;
if connectRight ~= nil then
local ropeconst = Instance.new("RopeConstraint",part);
ropeconst.Length = spread;
ropeconst.Attachment0 = part.Attachment;
ropeconst.Attachment1 = connectRight.Attachment;
end;
if connectLeft ~= nil then
local ropeconst = Instance.new("RopeConstraint",part);
ropeconst.Length = spread;
ropeconst.Attachment0 = part.Attachment;
ropeconst.Attachment1 = connectLeft.Attachment;
end
end
createAttachments();
connectConstraints();
If this does not work for you, please let me know. I can contact you from the site itself if needed.

How to setup the correct logic for picking a random item from a list based on item's rarity i.e "rare" "normal"

I'm writing a game using Corona SDK in lua language. I'm having a hard time coming up with a logic for a system like this;
I have different items. I want some items to have 1/1000 chance of being chosen (a unique item), I want some to have 1/10, some 2/10 etc.
I was thinking of populating a table and picking a random item. For example I'd add 100 of "X" item to the table and than 1 "Y" item. So by choosing randomly from [0,101] I kind of achieve what I want but I was wondering if there were any other ways of doing it.
items = {
Cat = { probability = 100/1000 }, -- i.e. 1/10
Dog = { probability = 200/1000 }, -- i.e. 2/10
Ant = { probability = 699/1000 },
Unicorn = { probability = 1/1000 },
}
function getRandomItem()
local p = math.random()
local cumulativeProbability = 0
for name, item in pairs(items) do
cumulativeProbability = cumulativeProbability + item.probability
if p <= cumulativeProbability then
return name, item
end
end
end
You want the probabilities to add up to 1. So if you increase the probability of an item (or add an item), you'll want to subtract from other items. That's why I wrote 1/10 as 100/1000: it's easier to see how things are distributed and to update them when you have a common denominator.
You can confirm you're getting the distribution you expect like this:
local count = { }
local iterations = 1000000
for i=1,iterations do
local name = getRandomItem()
count[name] = (count[name] or 0) + 1
end
for name, count in pairs(count) do
print(name, count/iterations)
end
I believe this answer is a lot easier to work with - albeit slightly slower in execution.
local chancesTbl = {
-- You can fill these with any non-negative integer you want
-- No need to make sure they sum up to anything specific
["a"] = 2,
["b"] = 1,
["c"] = 3
}
local function GetWeightedRandomKey()
local sum = 0
for _, chance in pairs(chancesTbl) do
sum = sum + chance
end
local rand = math.random(sum)
local winningKey
for key, chance in pairs(chancesTbl) do
winningKey = key
rand = rand - chance
if rand <= 0 then break end
end
return winningKey
end

how to "page" through the data in a Lua table used as a dictionary?

How would I code a function to iterate through one "pages" worth of data? Sample code would be ideal...
So say we image the size of a page is 5 items. If we had a lua table with 18 items it would need to print out:
Page 1: 1 to 5
Page 2: 6 to 10
Page 3: 11 to 15
Page 4: 16 to 18
So assume the data is something like:
local data = {}
data["dog"] = {1,2,3}
data["cat"] = {1,2,3}
data["mouse"] = {1,2,3}
data["pig"] = {1,2,3}
.
.
.
How would one code the function that would do the equivalent of this:
function printPage (myTable, pageSize, pageNum)
-- find items in "myTable"
end
So in fact I'm not even sure if a Lua table used as a dictionary can even do this? There is no specific ordering is there in such a table, so how would you be sure the order would be the same when you come back to print page 2?
The next function allows you to go through a table in an order (albeit an unpredictable one). For example:
data = { dog = "Ralf", cat = "Tiddles", fish = "Joey", tortoise = "Fred" }
function printPage(t, size, start)
local i = 0
local nextKey, nextVal = start
while i < size and nextKey ~= nil do
nextKey, nextVal = next(t, nextKey)
print(nextKey .. " = " .. nextVal)
i = i + 1
end
return nextKey
end
local nextPage = printPage(data, 2) -- Print the first page
printPage(data, 2, nextPage) -- Print the second page
I know this isn't quite in the form you were after, but I'm sure it can be adapted quite easily.
The next function returns the key after the one provided in the table, along with its value. When the end of the table is reached, it returns nil. If you provide nil as the second parameter, it returns the first key and value in the table. It's also documented in Corona, although it appears to be identical.

Resources