Attempt to index nil with character

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    Make my fists work lol…
  2. What is the issue? Include screenshots / videos if possible!
  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
wait()
local remoteevent = script.Parent:FindFirstChild('RemoteEvent')

local player = nil
local char = nil
local hum = nil

local punch_damage = math.random(2, 9)

local lefthand = nil
local righthand = nil
local blocked = nil

local fistenabled = nil

local selected = false
local punching = false 
local blocking = false
local abletoblock = true
local hit = false
local blockdelay = 0

local norm = false

local attackspeed = 0.45 -- time until next attack
local attacktouchtime = 0.75 -- time damage lasts on hand

local TwoHandAnim = 1
local Punch1 = 2
local Punch2 = 3
local BlockAnim = 4
local Punch3 = 5

local blocked = nil

function TagHumanoid(humanoid, player)
	local Creator_Tag = Instance.new("ObjectValue")
	Creator_Tag.Name = "creator"
	Creator_Tag.Value = player
	Creator_Tag.Parent = humanoid
	wait(2)
	Creator_Tag:Destroy()
end

function TagKO(humanoid,player)
	local Creator = Instance.new("ObjectValue")
	if not humanoid.Parent:FindFirstChild("KO") then
	Creator.Name = "KO"
	Creator.Value = player
	Creator.Parent = humanoid
	end
end
function UntagHumanoid(humanoid)
	for i, v in pairs(humanoid:GetChildren()) do
		if v:IsA("ObjectValue") and v.Name == "creator" then
			v:Destroy()
		end
	end
end

--onselected, save shoulders and get player
script.Parent.Equipped:connect(function()
	player = game.Players:GetPlayerFromCharacter(script.Parent.Parent)
	char = script.Parent.Parent
	fistenabled = player.Character:WaitForChild('Fist')
	hum = char:WaitForChild('Humanoid')
	lefthand = char:WaitForChild('Left Arm')
	righthand = char:WaitForChild('Right Arm')
	blocked = char:WaitForChild('Blocked')
	hum.Died:connect(function()
		if lefthand:FindFirstChild('TouchInterest') then
			lefthand:FindFirstChild('TouchInterest'):Destroy()
		end
		if righthand:FindFirstChild('TouchInterest') then
			righthand:FindFirstChild('TouchInterest'):Destroy()
		end
		script.Parent:Destroy()
	end)
	repeat
		wait()
	until TwoHandAnim ~= nil and Punch1 ~= nil and Punch2 ~= nil and BlockAnim ~= nil
	if selected then
		return
	end
	fistenabled.Value = true
	selected = true
	remoteevent:FireClient(player, 'PlayAnim', TwoHandAnim)
end)

script.Parent.Unequipped:connect(function()
	selected = false
	player = game.Players:GetPlayerFromCharacter(script.Parent.Parent)
	char = script.Parent.Parent
	fistenabled = player.Character:WaitForChild('Fist')
	fistenabled.Value = false
	blocked.Value = false
	if TwoHandAnim ~= nil then 
		remoteevent:FireClient(player, 'StopAnim', TwoHandAnim)
	end 
	if Punch1 ~= nil then 
		remoteevent:FireClient(player, 'StopAnim', Punch1)
	end 
	if Punch2 ~= nil then 
		remoteevent:FireClient(player, 'StopAnim', Punch2)
	end 
	if Punch3 ~= nil then
		remoteevent:FireClient(player, 'StopAnim', Punch3)
	end
	if BlockAnim ~= nil then
		remoteevent:FireClient(player, 'StopAnim', BlockAnim)
	end
end)

function Block()
	if not blocking and not punching and abletoblock and hum.Health > 0 then
		abletoblock = false
		blocking = true
		blocked.Value = true
		remoteevent:FireClient(player, 'PlayAnim', BlockAnim)
		wait(1)
		blocked.Value = false
		remoteevent:FireClient(player, 'StopAnim', BlockAnim)
		blocking = false
		wait(1.5)
		abletoblock = true
	end
end

function Punch()
	if punching == false and hit == false and blocking == false then
		punching = true
		norm = true
		local connection
		local fx = Instance.new("StringValue")
		fx.Name = "SwingSound"
		fx.Parent = script.Parent
		remoteevent:FireClient(player, 'StopAnim', TwoHandAnim)
		local punchrdm = math.random(1, 2)
		if punchrdm == 1 then
			remoteevent:FireClient(player, 'PlayAnim', Punch1)
			connection = lefthand.Touched:connect(function(p)
				local h
				if p.Parent:IsA('Accessory') or p.Parent:IsA('Hat') then
					h = p.Parent.Parent:FindFirstChild("Humanoid")
				else
					h = p.Parent:FindFirstChild("Humanoid")
				end
				if h then
					if hit == false and punching == true and h.Health > 0 then
						if h.Parent:FindFirstChild('Blocking') then
							local blocking = h.Parent:FindFirstChild('Blocking')
							if not blocking.Value then
								hit = true
								UntagHumanoid(h)
								TagKO(h.Parent, player)
								local fx = Instance.new("StringValue")
								fx.Name = "HitSound"
								fx.Parent = script.Parent
								h:TakeDamage(punch_damage)
								h:LoadAnimation(script.Parent.HitReaction):Play(0.2,nil,1)
								TagHumanoid(h, player)
							elseif blocking.Value then
								blockdelay = 2
								hit = true
								local fx = Instance.new("StringValue")
								fx.Name = "Hit_BlockSound"
								fx.Parent = script.Parent
							end
						end
					end 
				end
			end)
		elseif punchrdm == 2 then
			remoteevent:FireClient(player, 'PlayAnim', Punch2)
			connection = righthand.Touched:connect(function(p)
				local h
				if p.Parent:IsA('Accessory') or p.Parent:IsA('Hat') then
					h = p.Parent.Parent:FindFirstChild("Humanoid")
				else
					h = p.Parent:FindFirstChild("Humanoid")
				end
				if h then
					if hit == false and punching == true and h.Health > 0 then
						if h.Parent:FindFirstChild('Blocking') then
							local blocking = h.Parent:FindFirstChild('Blocking')
							if not blocking.Value then
								hit = true
								UntagHumanoid(h)
								TagKO(h.Parent, player)
								local fx = Instance.new("StringValue")
								fx.Name = "HitSound"
								fx.Parent = script.Parent
								h:TakeDamage(punch_damage)
								h:LoadAnimation(script.Parent.HitReaction2):Play(0.2,nil,1)
								TagHumanoid(h, player)
							elseif blocking.Value then
								blockdelay = 2
								hit = true
								local fx = Instance.new("StringValue")
								fx.Name = "Hit_BlockSound"
								fx.Parent = script.Parent
							end
						end
					end 
				end
			end)
		--[[elseif punchrdm == 5 then
			remoteevent:FireClient(player, 'PlayAnim', Punch3)
			connection = righthand.Touched:connect(function(p)
				local h
				if p.Parent:IsA('Accessory') or p.Parent:IsA('Hat') then
					h = p.Parent.Parent:FindFirstChild("Humanoid")
				else
					h = p.Parent:FindFirstChild("Humanoid")
				end
				if h then
					if hit == false and punching == true and h.Health > 0 then
						if h.Parent:FindFirstChild('Blocking') then
							local blocking = h.Parent:FindFirstChild('Blocking')
							if not blocking.Value then
								hit = true
								UntagHumanoid(h)
								local fx = Instance.new("StringValue")
								fx.Name = "HitSound"
								fx.Parent = script.Parent
								h:TakeDamage(punch_damage*2)
								h:LoadAnimation(script.Parent.UpperReaction):Play(0.1,nil,1)
								TagHumanoid(h, player)
								wait(0.2)
								h:TakeDamage(punch_damage)
							elseif blocking.Value then
								hit = true
								local fx = Instance.new("StringValue")
								fx.Name = "Hit_BlockSound"
								fx.Parent = script.Parent
							end
						end
					end 
				end
			end)]]
		end
		if selected == true then 
			remoteevent:FireClient(player, 'PlayAnim', TwoHandAnim)
		end
		spawn(function() -- seperate scope for touch time
			wait(attacktouchtime)
			hit = false
			connection:Disconnect()
		end)
		wait(attackspeed)
		wait(blockdelay)
		punching = false
		blockdelay = 0
	end
end

function Strong()
	if punching == false and hit == false and blocking == false then
		punching = true
		norm = true
		local connection
		local fx = Instance.new("StringValue")
		fx.Name = "SwingSound"
		fx.Parent = script.Parent
		remoteevent:FireClient(player, 'StopAnim', TwoHandAnim)
		local punchrdm = 5
		if punchrdm == 5 then
			remoteevent:FireClient(player, 'PlayAnim', Punch3)
			connection = righthand.Touched:connect(function(p)
				local h
				if p.Parent:IsA('Accessory') or p.Parent:IsA('Hat') then
					h = p.Parent.Parent:FindFirstChild("Humanoid")
				else
					h = p.Parent:FindFirstChild("Humanoid")
				end
				if h then
					if hit == false and punching == true and h.Health > 0 then
						if h.Parent:FindFirstChild('Blocking') then
							local blocking = h.Parent:FindFirstChild('Blocking')
							if not blocking.Value then
								blockdelay = 0
								hit = true
								UntagHumanoid(h)
								TagKO(h.Parent, player)
								local fx = Instance.new("StringValue")
								fx.Name = "HitSound"
								fx.Parent = script.Parent
								h:TakeDamage(punch_damage*2)
								h:LoadAnimation(script.Parent.UpperReaction):Play(0.1,nil,1)
								TagHumanoid(h, player)
							elseif blocking.Value then
								blockdelay = 3
								hit = true
								local fx = Instance.new("StringValue")
								fx.Name = "Hit_BlockSound"
								fx.Parent = script.Parent
								wait(2)
							end
						end
					end 
				end
			end)
		end
		spawn(function() -- seperate scope for touch time
			wait(attacktouchtime)
			hit = false
			connection:Disconnect()
		end)
		wait(2+blockdelay)
		punching = false
		if selected == true then 
			remoteevent:FireClient(player, 'PlayAnim', TwoHandAnim)
		end
	end
end

function Stomp()
	if punching == false and hit == false and blocking == false then
		punching = true
		norm = true
		local connection
		local fx = Instance.new("StringValue")
		fx.Name = "SwingSound"
		fx.Parent = script.Parent
		remoteevent:FireClient(player, 'StopAnim', TwoHandAnim)
		local punchrdm = 5
		if punchrdm == 5 then
			remoteevent:FireClient(player, 'PlayAnim', Punch3)
			connection = righthand.Touched:connect(function(p)
				local h
				if p.Parent:IsA('Accessory') or p.Parent:IsA('Hat') then
					h = p.Parent.Parent:FindFirstChild("Humanoid")
				else
					h = p.Parent:FindFirstChild("Humanoid")
				end
				if h then
					if hit == false and punching == true and h.Health > 0 then
						if h.Parent:FindFirstChild('Blocking') then
							local blocking = h.Parent:FindFirstChild('Blocking')
							if not blocking.Value then
								blockdelay = 0
								hit = true
								UntagHumanoid(h)
								TagKO(h.Parent, player)
								local fx = Instance.new("StringValue")
								fx.Name = "HitSound"
								fx.Parent = script.Parent
								h:TakeDamage(punch_damage*2)
								h:LoadAnimation(script.Parent.UpperReaction):Play(0.1,nil,1)
								TagHumanoid(h, player)
							elseif blocking.Value then
								blockdelay = 3
								hit = true
								local fx = Instance.new("StringValue")
								fx.Name = "Hit_BlockSound"
								fx.Parent = script.Parent
								wait(2)
							end
						end
					end 
				end
			end)
		end
		spawn(function() -- seperate scope for touch time
			wait(attacktouchtime)
			hit = false
			connection:Disconnect()
		end)
		wait(2+blockdelay)
		punching = false
		if selected == true then 
			remoteevent:FireClient(player, 'PlayAnim', TwoHandAnim)
		end
	end
end

remoteevent.OnServerEvent:connect(function(...)
	local args = {...}
	if hum == nil then return end
	if args[2] == 'Click' and hum.Health > 0 then
		norm = true
		Punch()
	elseif args[2] == 'Block' and hum.Health > 0 then
		Block()
	elseif args[2] == 'Strong' and hum.Health > 0 then
		Strong()
	elseif args[2] == 'Stomp' and hum.Health > 0 then
		Stomp()
	end
end)

I know this is a ServerScript and not a LocalScript, however, I want my ‘Fists’ tool to be able to work on a serverscript.

script.Parent.Unequipped:connect(function()
	selected = false
	player = game.Players:GetPlayerFromCharacter(script.Parent.Parent)
	char = script.Parent.Parent
	fistenabled = player.Character:WaitForChild('Fist') -- line 94
	fistenabled.Value = false
	blocked.Value = false
	if TwoHandAnim ~= nil then 
		remoteevent:FireClient(player, 'StopAnim', TwoHandAnim)
	end 

When they unequip the tool, the tool is no longer in their character. It is now in their backpack. To reference the player just do the following, also sorry I’m on mobile so it’s bad formatting.

Local player = script.Parent.Parent.Parent

I don’t actually know if the .Unequipped fires just before the tool is put into the backpack or as it enters the backpack under Player, but if its the latter,

script.Parent.Unequipped:connect(function()
selected = false
player = game.Players:GetPlayerFromCharacter(script.Parent.Parent)

script.Parent.Parent of the tool in the BackPack would be game.Players.(tool_users_name), therefore you don’t need to use :GetPlayerFromCharacter(). I’d suggest only defining the “player” variable in .Equipped :slight_smile:

(sorry I’ve edited this so many times bc I’m rubbish at explaining stuff)
basically, remove this line in your .Unequipped function:

player = game.Players:GetPlayerFromCharacter(script.Parent.Parent)

since you’ve already defined ‘player’ when the tool was equipped (unless you plan on people being able to steal other peoples punch tool) you don’t need it in .Unequipped!

Thats it? Just remove that line from the UnEquip function?

I think so! Give it a go and report back :sunglasses:

It has to be:

Local player = script.Parent.Parent.Parent

Because it’s;

Script-Tool-Backpack-Player

Variable “player” is already pre-defined at the start of the script! No need for the local :slight_smile:

2 Likes

No, it’s located in the ServerScriptService.

Parent = ServerScriptService
Parent = The Place Name

You’re right!! Sorry I missed that, I think he added in code later.

1 Like

Why don’t I need the local? The end) variable ends off that function of Equip. Therefore, it won’t define it to the unequip function for later usage in the script.

No no so, at the start of the script you set
Local player = nil
If in the unequipped function you wrote local player = script.Parent.Parent, as soon as that function is closed off with end) that “local player” variable wont be readable by anything outside of the .Unequipped function. However, if you forget the local altogether, you just change the value of the previously defined Local Player at the start of the script.

I’m sure my description is not 100% accurate and the lua gods will probably be giggle at me but thats how I explain it in my head! But just think if you use Local variable in a function, it is local to that function and cannot be used anywhere else! If you use local variable outside of a function (preferably at the start of a script if it’s going to be read/changed throughout the whole script) it is local to the entire script.

Um, could you reword that, I lost braincells.

1 Like

pls yes added some extra detail

anyway! did removing that line I mentioned earlier work?

oh! remove that line in .Unequipped too! Will set your “char” variable to the users Backpack :slight_smile:

I remove both the lines, and I get this:

  Players.49dec.Backpack.Fists.ServerHandler:63: attempt to index nil with 'Character'

could you post line 63 for me please, surrounded by context

fistenabled = player.Character:WaitForChild('Fist')
--onselected, save shoulders and get player
script.Parent.Equipped:connect(function()
	fistenabled = player.Character:WaitForChild('Fist')
	hum = char:WaitForChild('Humanoid')
	lefthand = char:WaitForChild('Left Arm')
	righthand = char:WaitForChild('Right Arm')
	blocked = char:WaitForChild('Blocked')
	hum.Died:connect(function()
		if lefthand:FindFirstChild('TouchInterest') then
			lefthand:FindFirstChild('TouchInterest'):Destroy()
		end
		if righthand:FindFirstChild('TouchInterest') then
			righthand:FindFirstChild('TouchInterest'):Destroy()
		end
		script.Parent:Destroy()
	end)
	repeat
		wait()
	until TwoHandAnim ~= nil and Punch1 ~= nil and Punch2 ~= nil and BlockAnim ~= nil
	if selected then
		return
	end
	fistenabled.Value = true
	selected = true
	remoteevent:FireClient(player, 'PlayAnim', TwoHandAnim)
end)

Ok so, maybe I didn’t explain clearly enough.

You don’t need player = game.Players:GetPlayerFromCharacter(script.Parent.Parent) in the .Unequipped function. Infact, running that in the .Unequipped function will break your script, because the script is then an descendant of the Player as the tool has been moved to the Backpack.

You do need it in the .Equipped function, as the tool is then a descendant of the Players character model, and therefore :GetPlayerFromCharacter() can successfully use a Character model to find the Player.

If you aren’t gonna give anyone player besides that one player the fist tool
you are better off defining the player once at the very top of the script
and redefining character every time its equipped

Well, it’s part of a gamepass, so people who buy the gamepass would receive the Fists tool…