[Introduction]
Hi!
I’m working on a little prototype of a tower-tycoon based game. [I apologize in advance, this is a long post lol]
If you’re unfamiliar with this type of game:
- the game revolves around the idea of purchasing some sort of ‘object’ (unicorns, noobs, monkeys, etc), that drops a collectable item.
- Once you’ve purchased 3 of these objects you can merge them together, which removes the three objects and inserts a new object of a higher ‘rarity’.
Here is an example game you can play: Unicorn Tycoon 🦄 - Roblox
It seemed like a fun challenge to create my own version of these games. So far everything is going smoothly!
I succesfully created:
- a base system [player is assigned a base upon joining]
- collectable drop system [objects drop collectables, can be picked up]
- buying objects + tower mechanic [able to buy a new base rarity object, once a floor is filled it creates a new floor to begin placing them on]
I’m currently missing 2 major mechanics. But today I’m focusing on completeing the Merging aspect of the game. I’ve tried a series of different methods to try and complete it. But I just cannot wrap my brain around it.
[Problem]
[I’ll be refering to the objects as ‘spawners’ from here on, to make it clearer what I’m referring to!]
Alright lets dissect my approach…
First off, I’ve already initialized a module script containing the dictionary of information relevant to the objects,
local spawnerInfo = {
-- all spawners are worth 3 of the previous type
[1] = {
["Name"] = "Basic",
["Worth"] = 1, -- how much 'money' u get for picking up
["Bonus"] = 1, -- drop size * bonus = final revenue
["Drop Size"] = Vector3.new(1,1,1), -- size of drop
["Drop Color"] = BrickColor.new("White") -- color of drop
},
[2] = {
["Name"] = "Red",
["Worth"] = 6,
["Bonus"] = 1,
["Drop Size"] = Vector3.new(1,1,1),
["Drop Color"] = BrickColor.new("Grey")
}
}
return spawnerInfo
So these contain important information about each rarity of spawners. I initialized these dictionaries to integer indexes. So the ‘rarities’ are sequential.
Proceeding…
I have a Server script that handles everything. With the module scripts contained inside of the scripts. [see image below]
Inside of the Server script I have a function connected to the event of a RemoteEvent being fired from the client once the player steps on the physical merge button located within their base.
Here is how that looks [nothing crazy]:
merge.OnServerEvent:Connect(function(player, base)
spawners.Merge(base)
end)
And here is how the hierarchy is setup inside of a base:
Everytime a spawner is purchased, they’re placed inside of the Spawners folder.
Alright, lastly here are the methods I tried, and why they didn’t work
First Method [Trying to use Recursion]
function spawners.Merge(base, index)
-- iterate through spawners (ipairs)
-- if 3 of the same type exist, remove them, add a new spawner of the next rarity
-- use recursion until there are no more spawners to merge
if index == 0 then
print("recursion complete!")
return -- we finished woohoo
else
local tSpawners= base:WaitForChild("Spawners")
local myTable = {}
local prev = nil
print("current recursion loop, index: " .. index)
for i,v in ipairs(tSpawners:GetChildren()) do
if #myTable == 3 then
local newSpawnerRarity, newSpawnerInfo = next(spawnerInfo, 1)
for i,v in pairs(myTable) do
spawners.DeleteSpawner(base, v)
end
--spawners.Rearrange(base)
spawners.CreateSpawner(base, newSpawnerRarity)
return spawners.Merge(base, index-3)
else
if prev == nil then -- did we just start iterating?
prev = v
table.insert(myTable, v)
elseif v.Name == prev.Name then -- make sure its the same type
table.insert(myTable, v)
else
return spawners.Merge(base, index-1)
end
end
end
end
end
This method was weird, in my head, since the spawners are displayed sequentially decreasing in rarity, I thought by using ipairs I could just transfer the objects into another dictionary → (myTable), to keep track of the amount of a certain rarity. In hind-sight this was kind of a stupid idea. The issue is, the spawners would merge properly and create a new spawner of the next rarity. But I couldn’t do it again.
I used another method called rearrange()
, which also isn’t working currently because it wouldn’t move the excess spawners closer to the open spot nearest to the start of the line (bottom left of the tower). But I’m not worrying about that right now. I’m more concerned with this merging aspect.
So that didn’t work, here is my second attempt…
Second Method
function spawners.Merge(base)
--[[
Merge spawners in base, for every 3 same type, it will remove them and insert a new spawner of the next rarity
@param base : the player's base
]]
local spawnerCounts = {}
local spawners = base.Spawners
if spawners then
for i, spawner in ipairs(spawners:GetChildren()) do
-- count spawners
if spawnerCounts[spawnerInfo[tonumber(spawner.Name)]] == nil then
spawnerCounts[spawnerInfo[tonumber(spawner.Name)]] = 1
else
spawnerCounts[spawnerInfo[tonumber(spawner.Name)]] += 1
end
print(unpack(spawnerCounts))
if spawnerCounts[spawnerInfo[tonumber(spawner.Name)]] == 3 then
-- lets check to see if there is another rarity next..
local nextSpawnerRarity = spawnerInfo[tonumber(spawner.Name) + 1]
local indexToRemove
if nextSpawnerRarity == nil then
-- there isn't another spawner, don't do anything
print("YOU REACHED MAX LEVEL WOOHOO!!!")
return
end
for j, obj in ipairs(spawners:GetChildren()) do
if obj.name == spawner.name then
if indexToRemove == nil then
indexToRemove = j
else
table.remove(spawners:GetChildren(), j)
spawnerCounts[tonumber(obj.name)] = spawnerCounts[tonumber(obj.name)] - 1
end
end
end
table.remove(spawners:GetChildren(), indexToRemove)
spawners.CreateSpawner(base, nextSpawnerRarity)
end
end
else
print("Spawners don't exist?")
end
end
Honestly not even sure what I was trying to do. But it didn’t work.