Table index is nil

Im making a damage script which handles everything for me without me having to do all the ignores everytime I wanna damage a player… But It has an issue?

it’s the title of the post…

Code

local FunctionService = require(script.Parent:WaitForChild("Functions"))
local RagdollService = require(script.Parent:WaitForChild("RagdollService"))
local HttpService = game:GetService("HttpService")
local ManagerService = require(game:GetService("ServerScriptService").Combat.Main:WaitForChild("Manager"))


local DamageHandler = {}
DamageHandler.__index = {}

local Sets = {}

function DamageHandler.new() -- Return a Metatable with the stats.
	return setmetatable({
		IgnoreBlock = false,
		IgnoreParry = false,
		IgnoreRagdoll = false,
		IgnoreSpecial = false,
		IgnoreIFrames = false,
		
		HitCharacter = nil,
		Character = nil,
		
		RagdollData = {Can = false, Time = 0},
		StunData = {Can = false, Time = 0},
		Amount = 0,
		Multiplier = 1,
		
		Effects = {},
		
		MaxDistance = 4,
		Key = HttpService:GenerateGUID(false),
		Type = "Once",
		TypeData = {Time = 0, X = 0},
		Damage = DamageHandler
	}, DamageHandler)
end

function DamageHandler:Start() -- Begin the checks
	if Sets[self.Key] then warn("Damage with this key has already been done") return end
	
	Sets[self.Key] = self
	
	local HitRoot:BasePart = self.HitCharacter:FindFirstChild("HumanoidRootPart")
	local RootPart:BasePart = self.Character:FindFirstChild("HumanoidRootPart")
	local Humanoid: Humanoid = self.HitCharacter:FindFirstChildOfClass("Humanoid")
	local CharData = ManagerService:Retrieve(self.Character)
	local HitData = ManagerService:Retrieve(self.HitCharacter)
	local Status = CharData.Status	
	local ObjectSpace = HitRoot.CFrame:Inverse() * RootPart.CFrame
	local IsBehind = false
	
	task.spawn(function()
	if ObjectSpace.Z < 0 and (RootPart.CFrame.Position - HitRoot.CFrame.Position).Magnitude <= self.MaxDistance then
		IsBehind = true
	end
	end)
	
	
	task.spawn(function()
		if Status.InIFrames then
			if self.IgnoreIFrames then
				self:Deal()
				return "Connected"
			else
				return "Blocking"
			end
		elseif Status.IsBlocking and not IsBehind then
			if self.IgnoreBlock then
				self:Deal()
				return "Connected"
			else
				return "Blocking"
			end
		elseif Status.IsParrying and not IsBehind then
			if self.IgnoreParry then
				self:Deal()
				return "Connected"
			else
				return "Parried"
			end
		elseif Status.Special ~= "None" then
			if self.IgnoreSpecial then
				self:Deal()
				return "Connected"
			else
				return Status.Special
			end
		elseif Status.Ragdolled then
			if self.IgnoreRagdoll then
				self:Deal()
				return "Connected"
			else
				return "Ragdolled"
			end
		else
			self:Deal()
			return "Connected"
		end
	end)
	
end

function DamageHandler:Deal() -- Actually deal the damage based on the type.
	if not Sets[self.Key] then warn("Cant deal without key") return end;
	
	local Humanoid: Humanoid = self.HitCharacter:FindFirstChildOfClass("Humanoid")
	local CharData = ManagerService:Retrieve(self.HitCharacter)
	local Status = CharData.Status
	
	for I,V in ipairs(self.Effects) do
		print(V)
	end
	
	if self.Type == "Once" then
		Humanoid:TakeDamage(self.Amount * self.Multiplier)
		DamageHandler:_clear()
		return
	elseif self.Type == "Repeat" then
		repeat 
		Humanoid:TakeDamage(self.Amount * self.Multiplier)
		task.wait(self.TypeData.Time)
		until not Sets[self.Key]
		DamageHandler:_clear()
		return
	elseif self.Type == "Times" then
		for I =1,self.TypeData.X do
			Humanoid:TakeDamage(self.Amount * self.Multiplier)
			task.wait(self.TypeData.Time)
		end
		DamageHandler:_clear()
	return 
	end
end

function DamageHandler:_clear() -- Clear the key after the damage is done, or manually, doesn't matter.
	if Sets[self.Key] then
		Sets[self.Key] = nil
	end
end

return DamageHandler

the issue is at “Sets[self.Key] = self”; Line 41

To:

DamageHandler.__index = DamageHandler
1 Like

omg bruh no way… i missed that simple mistake

Problem solved?

abcdefg

nope… still an issue

qweqeweqew

I changed the code a little bit here it is.

local FunctionService = require(script.Parent:WaitForChild("Functions"))
local RagdollService = require(script.Parent:WaitForChild("RagdollService"))
local HttpService = game:GetService("HttpService")
local ManagerService = require(game:GetService("ServerScriptService").Combat.Main:WaitForChild("Manager"))


local DamageHandler = {}
DamageHandler.__index = DamageHandler
local Sets = {}

function DamageHandler.new() -- Return a Metatable with the stats.
	return setmetatable({
		IgnoreBlock = false,
		IgnoreParry = false,
		IgnoreRagdoll = false,
		IgnoreSpecial = false,
		IgnoreIFrames = false,
		
		HitCharacter = nil,
		Character = nil,
		
		RagdollData = {Can = false, Time = 0},
		StunData = {Can = false, Time = 0},
		Amount = 0,
		Multiplier = 1,
		
		Effects = {},
		
		MaxDistance = 4,
		Key = HttpService:GenerateGUID(false),
		Type = "Once",
		TypeData = {Time = 0, X = 0},
		Damage = DamageHandler
	}, DamageHandler)
end

function DamageHandler:Start() -- Begin the checks
	if Sets[self.Key] then warn("Damage with this key has already been done") return end
	
	Sets[self.Key] = self
	
	DamageHandler:Check()
end

function DamageHandler:Check()
	local HitRoot:BasePart = self.HitCharacter:FindFirstChild("HumanoidRootPart")
	local RootPart:BasePart = self.Character:FindFirstChild("HumanoidRootPart")
	local Humanoid: Humanoid = self.HitCharacter:FindFirstChildOfClass("Humanoid")
	local CharData = ManagerService:Retrieve(self.Character)
	local HitData = ManagerService:Retrieve(self.HitCharacter)
	local Status = CharData.Status	
	local ObjectSpace = HitRoot.CFrame:Inverse() * RootPart.CFrame
	local IsBehind = false

	task.spawn(function()
		if ObjectSpace.Z < 0 and (RootPart.CFrame.Position - HitRoot.CFrame.Position).Magnitude <= self.MaxDistance then
			IsBehind = true
		end
	end)


	task.spawn(function()
		if Status.InIFrames then
			if self.IgnoreIFrames then
				self:Deal()
				return "Connected"
			else
				return "Blocking"
			end
		elseif Status.IsBlocking and not IsBehind then
			if self.IgnoreBlock then
				self:Deal()
				return "Connected"
			else
				return "Blocking"
			end
		elseif Status.IsParrying and not IsBehind then
			if self.IgnoreParry then
				self:Deal()
				return "Connected"
			else
				return "Parried"
			end
		elseif Status.Special ~= "None" then
			if self.IgnoreSpecial then
				self:Deal()
				return "Connected"
			else
				return Status.Special
			end
		elseif Status.Ragdolled then
			if self.IgnoreRagdoll then
				self:Deal()
				return "Connected"
			else
				return "Ragdolled"
			end
		else
			self:Deal()
			return "Connected"
		end
	end)

end

function DamageHandler:Deal() -- Actually deal the damage based on the type.
	if not Sets[self.Key] then warn("Cant deal without key") return end;
	
	local Humanoid: Humanoid = self.HitCharacter:FindFirstChildOfClass("Humanoid")
	local CharData = ManagerService:Retrieve(self.HitCharacter)
	local Status = CharData.Status
	
	for I,V in ipairs(self.Effects) do
		print(V)
	end
	
	if self.Type == "Once" then
		Humanoid:TakeDamage(self.Amount * self.Multiplier)
		DamageHandler:_clear()
		return
	elseif self.Type == "Repeat" then
		repeat 
		Humanoid:TakeDamage(self.Amount * self.Multiplier)
		task.wait(self.TypeData.Time)
		until not Sets[self.Key]
		DamageHandler:_clear()
		return
	elseif self.Type == "Times" then
		for I =1,self.TypeData.X do
			Humanoid:TakeDamage(self.Amount * self.Multiplier)
			task.wait(self.TypeData.Time)
		end
		DamageHandler:_clear()
	return 
	end
end

function DamageHandler:_clear() -- Clear the key after the damage is done, or manually, doesn't matter.
	if Sets[self.Key] then
		Sets[self.Key] = nil
	end
end

return DamageHandler

Whats the issue now? Or is it the same issue?

1 Like

same issue same spot

…qew…weeqwe

Are you using the constructor (.new) before using any other methods?

yes

return {
	Use = function(Character:Model, Combo)
		local RootPart = Character:FindFirstChild("HumanoidRootPart")
		local Data = ManagerService:Retrieve(Character)
		
		print("Handling for" ..  tostring(Character))
		
		local CurrentTouching = {}
		local Hitbox = HitService.CreateHitbox()
		Hitbox.CFrame = Character
		Hitbox.Offset = WeaponData[Data.CharacterInfo.Weapon.Name].Hitbox.Offset
		Hitbox.Size = WeaponData[Data.CharacterInfo.Weapon.Name].Hitbox.Size
		Hitbox.Shape = Enum.PartType.Block
		Hitbox.OverlapParams = Paramaters.Normal(Character)
		
		task.spawn(function()
		Hitbox:Start()
		task.delay(0.1, function()
		Hitbox:Destroy()
		end)
		
		local DamageData = DamageService.new()
		DamageData.Character = Character
		DamageData.Amount = WeaponData[Data.CharacterInfo.Weapon.Name].Damage
		DamageData.StunData.Time = WeaponData[Data.CharacterInfo.Weapon.Name].StunTime
		DamageData.StunData.Can = true
		
		Hitbox.Touched:Connect(function(Hit: BasePart)
		local HitCharacter = Hit:FindFirstAncestorOfClass("Model")
		local HitHumanoid = HitCharacter:FindFirstChildOfClass("Humanoid")
		DamageData.HitCharacter = HitCharacter
		local Status = DamageData.Damage:Start()
		print(Status)
		
		end)
		end)
	end,
}
1 Like

I’m guessing this is the line with the issue? Why are you calling the method like this? Just do DamageData:Start()

2 Likes

damagedata.new() returns the meta table, i then put the handler functions inside of the metatable and it goes by the term damage

Methods pass self as the first parameter so because of the way you’re using the methods it’s passing nil in place of self. If you want to call the method you have to manually pass in data in place of self like this:

DamageData.Damage.Start(DamageData)
1 Like

idk what was happening earlier but I couldn’t just call :Start() on damage data but Ig it works now thanks!

That’s because you didn’t use the index metamethod correctly. But it’s good your problem is solved :smiley:

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