Script works, but it errors and the cframe is bullying me

Ok so I have 2 scripts. 1 a local inside a tool that fires info via remote event to a server script that makes parts and deals damage. These 2 scripts make up a fireball that shoots out. The scripts work, but there is an error message that plays which lags the script a bit and makes the fireball a bit glitchy. Its not a major issue though its annoying and not really sure how to fix it.
The error message:
ServerScriptService.NormalSpellDamage:21: attempt to index nil with ‘CFrame’

Local script, locate inside the tool:

local tool = script.Parent
local player = game:GetService("Players").LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local root = character:WaitForChild("HumanoidRootPart")
local canshoot = true
local event = game.ReplicatedStorage.NormalSpellEvents.Fireball
local event2 = game.ReplicatedStorage.NormalSpellEvents.Fireball2
local boomy = script.Parent.BallBoom
local boom = Instance.new("Explosion")
local newCFrame = root.CFrame
boom.BlastRadius = 3
ball = nil
fire = nil
function OnActivation()

event:FireServer()
	if canshoot == true then
		canshoot = false
		print('Activation works')
	event:FireServer(root,boom, player, boomy)



		wait(1)
		canshoot = true

	end

end


tool.Activated:Connect(OnActivation)

The server script, located in serverscriptservice:

local storage = game.ReplicatedStorage

local fireevent = storage.NormalSpellEvents.Fireball



local function onActivation(Player1, root, boom, player, boomy)
	local ball = Instance.new("Part")
	ball.Shape = Enum.PartType.Ball
	ball.Color = Color3.new(1, 0.333333, 0)
	ball.Size = Vector3.new(2,2,2)
	ball.Material = Enum.Material.Granite
	ball.CanCollide = false

	local fire = Instance.new("Fire")
	fire.Parent = ball
	ball.Parent = root

	local newCFrame = root.CFrame
	local cf = ball.CFrame

	ball.CFrame = newCFrame


	local Velocity = Instance.new("BodyVelocity")

	Velocity.maxForce = Vector3.new(math.huge, math.huge, math.huge) 
	Velocity.Velocity = ball.CFrame.lookVector * 30


	Velocity.Parent = ball

	ball.Touched:connect(function(hit) 
		if hit.Parent:FindFirstChild('Humanoid') and hit.Parent ~= player.Character then
			local humanoid1 = hit.Parent:FindFirstChild('Humanoid')
			humanoid1:TakeDamage(50)
			local boom = Instance.new("Explosion")
			boom.Parent = ball
			boom.Position = ball.Position

			boom.BlastPressure = 500
			boom.BlastRadius = 3
			boom.ExplosionType = "NoCraters"
			boom.DestroyJointRadiusPercent = 0

			ball.CanCollide = false
			ball.CanTouch = false
			ball.Transparency = 1
			fire:Destroy()

		end
	end)

	

	ball.Touched:connect(function(hit) 
		if hit:IsA("Part")  and hit.Parent ~= player.Character then
			local boom = Instance.new("Explosion")
			boom.Parent = ball
			boom.Position = ball.Position

			boom.BlastPressure = 500
			boom.BlastRadius = 3
			boom.ExplosionType = "NoCraters"
			boom.DestroyJointRadiusPercent = 0

			ball.CanCollide = false
			ball.CanTouch = false
			ball.Transparency = 1
			fire:Destroy()
			local sound = boomy
			sound:Play()

		end

	end)
	


end


fireevent.OnServerEvent:Connect(onActivation)



local storage = game.ReplicatedStorage

local fireevent2 = storage.NormalSpellEvents.Fireball2

Ive tried to define newcframe in the local script and fire it off to the serverscript but that caused the fireball’s direction definers too not work.

Whats the ball and root? (Parts?)

Ball is the fireball instance. Root is the hrp.

But I mean, they are parts or mesh, or what?

The ball is a part, as seen in the script. And the hrp is a part.

Try change to that
local ball = Instance.new("Part", workspace)

I’d recommend only receiving the player object in the server side part of your RemoteEvent, since exploiters will be able to mess with your script. Not only that, but it’s best to have the server directly find your HumanoidRootPart, create the Explosion, and such. This should also fix your CFrame error.

local function onActivation(Player1)
    local char = Player1.Character or Player1.CharacterAdded:Wait()
    local root = char:WaitForChild("HumanoidRootPart")
    local boom = --Directory
    local boomy = --Directory
end

Hope this helps!

The ball is parented to the humanoid root part already.

Wait sorry, im slightly confused. Could you explain?

As you currently have it set up, you’re sending all the information the server needs to create the fireball from the client (player). When you use a RemoteEvent, players can mess with what information is being sent, so you shouldn’t be sending the rootpart, explosion or ballBoom.

Instead, the server should be in charge of retrieving these objects. You have to remember the server/client model: the server sends a copy of what it sees to the clients, so everything the client has access to isn’t the real thing.

If the server itself gets the HumanoidRootPart, it’ll be using the real object. If you send your own rootPart, it won’t be as precise, and exploiters can mess with it. This may also be the reason you’re getting the cframe error.

1 Like

So should i just send over the local player and find the root part of the server?

You don’t have to send anything! The server already receives the player as the first argument whenever FireServer() is called:

--Local script:
event:FireServer()
--Server script:
event.OnServerEvent:Connect(function(player)
end)
1 Like

Oh ye, I forgot that remote events already do that.

Ok so thanks! I moved everything to the server side. it all seems to be working now. I get an error message about sound stuff but it isnt affecting the performance of the fireball at all. So im just gong to let it be. Thanks.