Data from Modulescript keeps getting deleted despite trying to clone it

I made a modulescript containing custom wave layouts, which the zombie spawning script uses to know which Zombies to spawn for the current wave. As it spawns its zombies throughout the wave it removes them from its list so it can count down the amount remaining.

The issue is, no matter what I do it keeps deleting Zombies from the original table in the modulescript, meaning that in the next round all the waves have been deleted and the game no longer works. I want it to grab a copy of the table rather than doing this, but there doesn’t seem to be any way to do so.

I’ve tried:

  • Returning a variable of the table and not the table itself, it still deleted values from the original table during the spawning process
  • Using table.clone, it still deleted zombies from the list of waves (is it even a real clone??? I’m starting to doubt it at this point)
  • cloning the table from the server script, it STILL deleted zombies from the original modulescript for some reason
  • Requiring the modulescript again, values didn’t refresh

Modulescript:

local module = {}

local zombies = game.ServerStorage.Zombies

-- This isn't all of the waves, I shortened it since the full list isn't important
local waves = {
	{ -- wave 1
		{zombies["Basic Zombie"], 20}
	};
	
	{ -- wave 2
		{zombies["Basic Zombie"], 30},
		{zombies["Fast Zombie"], 10}
	};
	
	{ -- wave 3
		{zombies["Basic Zombie"], 20},
		{zombies["Fast Zombie"], 30}
	};
	
	{ -- wave 4
		{zombies["Basic Zombie"], 30},
		{zombies["Fast Zombie"], 10},
		{zombies["TurboMK2"], 10}
	};
}

module.GetWave = function(waveNumber)
	
	if #waves >= waveNumber then
		
		return table.clone(waves[waveNumber])
		
	else
		return nil
	end
	
	--return table.find(waves, "wave" .. waveNumber)
end

return module

Server script:

local runningID = 0
local gamevalues = game.ReplicatedStorage.GameValues
local waveLayouts = require(script.WaveLayouts)



script["Begin"].Event:Connect(function(startspawning)
	runningID += 1
	local currentRunningID = runningID
	if startspawning == true then
		
		local players = game.Players:GetChildren()
		local currentWave = game.ReplicatedStorage.GameValues.CurrentWave.Value
		
		local spawnedZombieCount = 0
		local maxZombies = gamevalues.MaxZombies.Value + ((gamevalues.CurrentWave.Value*4)*(#players * 0.5))
		local zombiesThisWave = 0 --math.round((gamevalues.CurrentWave.Value*8)*(#players * 0.8)) + 10
		
		
		-- Determining which zombies make it on to the list based on current wave ---------------------------------------
		local zombieList = waveLayouts.GetWave(currentWave)
		print(zombieList)
		print(waveLayouts.GetWave(currentWave))
		
		if zombieList == nil then
			
			
			for index, zombie in ipairs(game.ServerStorage.Zombies:GetChildren()) do
				if (currentWave >= zombie.Spawning.FirstWave.Value) and (currentWave <= zombie.Spawning.FinalWave.Value) then
					
					-- Current zombie spawning:
					-- base count + number of waves since first * scaling per wave
					
					local baseZombieCount = zombie.Spawning.Count.Value
					local zombiesPerWave = zombie.Spawning.Scaling.Value
					local wavesPassed = game.ReplicatedStorage.GameValues.CurrentWave.Value - zombie.Spawning.FirstWave.Value
					local zombieCount = math.floor(baseZombieCount + (zombiesPerWave * wavesPassed))
					
					
					table.insert(zombieList, {zombie, zombieCount})
					zombiesThisWave += zombieCount
					
					print("Added " .. zombieCount .. " " .. zombie.Name)
					--print(zombieList)
				end
			end
		else
			for index, zombieType in ipairs(zombieList) do
				zombiesThisWave += zombieType[2]
				print("Added " .. zombieType[2] .. " " .. zombieType[1].Name)
			end
		end
		if #zombieList == 0 then		warn("THERE'S NO ZOMBIES FOR THIS WAVE IT'S SO OVER")		end
		-----------------------------------------------------------------------------------------------------------------
		
		
		
		
		
		gamevalues.UnspawnedZombiecount.Value = zombiesThisWave
		
		print(zombiesThisWave .. " Zombies this wave")
		print(zombieList)
		repeat
			-- Selecting which zombie to spawn ----------------------------------------------------------
			local zombieNumber = math.random(1, #zombieList)
			local zombie = zombieList[zombieNumber] -- chooses a random zombie from the list
			local zombieModel = zombie[1] -- saves the zombie as a variable for spawning later
			
			zombieList[zombieNumber][2] = zombieList[zombieNumber][2] - 1 -- Removes one from that total zombie's count
			
			--print(zombie[2] .. " " .. zombie[1].Name .. " Left") -- say how much of this zombie is left
			
			if zombieList[zombieNumber][2] <= 0 then -- if this zombie hits 0, it removes it from the list
				table.remove(zombieList, zombieNumber)
				--print("removed " .. zombieModel.Name)
			end
			--------------------------------------------------------------------------------------------------------------------------------
			
			------ Picks a random spawn location from workspace.ImportantStuff.ZombieSpawns, and sets the variable Spawnpoint to it --------
			local spawnLocations = workspace.MapInfo.ZombieSpawns:GetChildren()
			local Spawnpoint = spawnLocations[math.random(1, #spawnLocations)]
			------------------------------------------------------------------------------------------------------------------------------------
			
			--local zombieSpawn = game.ServerStorage.Zombies["Basic Zombie"]:Clone()
			local zombieSpawn = zombieModel:Clone()
			zombieSpawn.Parent = workspace.AllZombies
			zombieSpawn.HumanoidRootPart.CFrame = Spawnpoint.CFrame
			--print("spawned a zombie")
			
			spawnedZombieCount+= 1
			gamevalues.UnspawnedZombiecount.Value -= 1
			--gamevalues.ZombiesLeft += 1
			
			script.ZombieSpawned:Fire()
			
			local livingZombieCount = workspace.AllZombies:GetChildren()
			local openZombieSlots = maxZombies - #livingZombieCount
			local spawnrateMultiplier = openZombieSlots / maxZombies-- + 0.1
			--wait(1 - (gamevalues.CurrentWave.Value / 10))
			
			task.wait(0.9 - spawnrateMultiplier)
			--print(spawnrateMultiplier)
			
			if #livingZombieCount >= maxZombies then
				--print("Zombies at max, of " .. maxZombies .. ", stalling...")
				repeat
					livingZombieCount = workspace.AllZombies:GetChildren()
					game.ReplicatedStorage.GameValues.ZombiesAlive.Value = #livingZombieCount
					wait(1)
				until #livingZombieCount < maxZombies or currentRunningID ~= runningID
			end
			
			
			game.ReplicatedStorage.GameValues.ZombiesAlive.Value = #livingZombieCount
			
			
		until spawnedZombieCount >= zombiesThisWave or currentRunningID ~= runningID
		if currentRunningID ~= runningID then 	warn("Something cut off the zombie spawning process early.")	else	print("Finished zombie spawning")	end
		
	end
end)

Is there a way I can call on this information without iterating on the original table? Cloning it somehow isn’t enough, so I’m at a loss for what to do.

table.clone creates a shallow copy of the table

this means that tables inside of the table are not cloned and they still point to the exact same table in memory

if you want to clone all nested tables then you need to deep clone

you can also (much less efficiently) require a clone of the module to refresh the contents like require(module:Clone()). The code inside the module that sets the data only runs the first time it’s required

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.