How do i fix "attempt nil with name"

How do i fix this script?

local cooldown = false
local attackAnimation = Instance.new("Animation")
local animationID = "rbxassetid://6505914323"
attackAnimation.Parent = game:GetService("ReplicatedStorage")
attackAnimation.AnimationId = animationID
local myNPC = workspace.Mobs.NPC
local npcHumanoid = myNPC:FindFirstChildOfClass("Humanoid")
local armorModule = require(game.ServerScriptService:WaitForChild("ArmorHandler"))

script.Parent.npchum.Touched:Connect(function(hit)
	local hum = hit.Parent:FindFirstChild("Humanoid")
	if hum then
		local animator = npcHumanoid:FindFirstChildOfClass("Animator") or Instance.new("Animator")
		animator.Parent = npcHumanoid
		if not cooldown then
			cooldown = true
			local animation = animator:LoadAnimation(attackAnimation)
			animation:Play()
			hum:TakeDamage(25)
			wait(1)
			cooldown = false
				
			end
		end
end)
myNPC.npchum.Died:Connect(function()
	myNPC:Destroy()
	
	local armor = armorModule.chooseRandom()
	
	print(armor.Name) --Error here
end)

Thank you (sorry for posting a lot)

armor is nil, so the problem isn’t actually this script. The problem is ArmorHandler.

Should i show you the armorhandler?

If you wouldn’t mind. I’ll see what I can do from there.

local armormodule = {}

armormodule.armors = {
	["Legendary"] = {
		game.ReplicatedStorage.Armors.LegendaryArmor
	};

	["Epic"] = {
		game.ReplicatedStorage.Armors.EpicArmor
	}

}

armormodule.rarities = {
	["Legendary"] = 0.0001; -- 0.001% chance

	["Epic"] = 10; --10% chance 

}



armormodule.chooseRandom = function()

	local randomNumber = math.random(1,100.1)

	local counter = 0

	for rarity, weight in pairs(armormodule.rarities) do
		counter = counter + weight
		if randomNumber <= counter then

			local rarityTable = armormodule.armors[rarity]
			local chosenArmor = rarityTable[math.random(1,#rarityTable)]
			return chosenArmor

		end
	end

end

return armormodule

I see. So what happens is that you don’t have a default rarity to fall back to. That’s not my favorite way to handle percentage-based odds, but I’m fairly certain that your problem will be resolved if all of the rarities in the armormodule.rarities table add up to at least 100%.

should i change the math.random to lower? or do i increase the chances?

Actually, that works too. Change math.random to equal the sum of all of the chances. Do it like this to include decimals.

local sum = 0
for i, v in pairs armormodule.rarities do
    sum += v
end

and then when you need to get a random number, use this instead of your current math.random.
math.random()*sum

ill keep the sum at 0 right?

1 Like

Also, I don’t know if it helps, but here are a couple of posts I have describing other methods to get a random loot chance.

and this one, skip to about halfway through
https://devforum.roblox.com/t/what-are-some-of-the-worst-lines-of-code-you-read-that-make-you-think-what-was-the-writer-thinking/760394/42?u=jarodoforbiter

It still says attempt nil with name

I tested this, and it works. This replaces the entirety of the module script you shared.

local armormodule = {}

armormodule.armors = {
	["Legendary"] = {
		game.ReplicatedStorage.Armors.LegendaryArmor
	};

	["Epic"] = {
		game.ReplicatedStorage.Armors.EpicArmor
	}

}

armormodule.rarities = {
	["Legendary"] = .001; -- 0.001% chance

	["Epic"] = 10; --10% chance 

}

local sum = 0
for i, v in pairs(armormodule.rarities) do
	sum += v
end


armormodule.chooseRandom = function()

	local randomNumber = math.random()*sum

	local counter = 0

	for rarity, weight in pairs(armormodule.rarities) do
		counter = counter + weight
		if randomNumber <= counter then

			local rarityTable = armormodule.armors[rarity]
			local chosenArmor = rarityTable[math.random(1,#rarityTable)]
			return chosenArmor

		end
	end

end

return armormodule

Thank you for your help!