Okay, I am making a new game and I want a Fireball to shoot out and kill somebody when the letter F is pressed , but, 2 problems, when I press 'F' the fireball just stays in one place, and secondly, it does not kill somebody when it touches them. Here is the script:
Player = game.Players.LocalPlayer Char = Player.Character Torso = Char.Torso Mouse = Player:GetMouse() Attack = false function onKeyDown(key) Attack = false key = key:lower() if key == "f" and Attack == false then Attack = true print("Fireball successful!") Ball = Instance.new("Part") Ball.Parent = workspace Ball.Shape = "Ball" Ball.Size = Vector3.new(5,5,5) Ball.BrickColor = BrickColor.new("Really red") Ball.Transparency = 0.4 Ball.TopSurface = 0 Ball.BottomSurface = 0 Ball.CFrame = Torso.CFrame * CFrame.new(0,0.5,-5) Bv = Instance.new("BodyVelocity") Bv.Parent = Ball Bv.maxForce = Vector3.new(math.huge,math.huge,math.huge) Bv.velocity = Torso.CFrame.lookVector * 100 game.Debris:AddItem(Ball,4) wait(3) Attack = false end end Mouse.KeyDown:connect(onKeyDown)
I hope this can be fixed, thanks.
Skip to the bottom if you just want the working code, but if you want to understand why your script didn't work, read the analysis below. I explain things that aren't necessarily errors as well, so some things will work, I just prefer a differing method. I changed some variables to make them shorter, sorry.
Use local
whenever you define a variable (not when you call it again since it's already defined). It generally helps the script lag less, though the effect is minimal unless you call the variable a lot. It's just a good habit to get into.
The character will presumably die (especially if you're throwing a bunch of deadly fireballs around) so you'll need an update for characters of players. The first character won't cut it!
You have a boolean that keeps the player from spamming fireballs, except that you make it false as soon as the function runs, so it's essentially useless. The other two portions of the boolean are ok, and definition was ok.
You are making this ball fly at the speed of sound; I doubt anyone can even see it. I personally find Body-userdata things and the Touched event to be unreliable. Because of this, I tend to CFrame everything that moves. I know a lot of people like Lerp. I've never been a fan; I just write out something similar.
You lack a kill script. This is the part where I say "You're giving the client too much power" because I'm a FilteringEnabled fanatic. Personally, I would add a RemoteEvent for this thing. You'll see what I mean in the final code.
Now, you could make this code even more efficient than what I did by having the client project the object since it will be less of a burden to the server, with the server giving position values for the ball, but that isn't really what you asked for, so I'm going to give you the object being spawned in Workspace by the server.
Add this portion to the Server Script.
local cDownTab = {} local range = 100 -- This is in studs. local speed = 90 -- This is in studs per second. local fps = 20 -- This is how many times your fireball position is -- updated a second. Higher values may cause your speed lag, especially -- when more balls are in-game. You can solve this by making -- graphics local but keeping game logic server controlled. local intialTrans = .4 function checkFireBall(obj,plrN) if obj then for _,v in pairs(game.Players:GetChildren()) do if v.Name~=plrN and v.Character then local torso = v.Character:FindFirstChild("Torso") local humanoid = v.Character:FindFirstChild("Humanoid") if torso and humanoid and humanoid.Health>0 and (torso.Position-obj.Position).magnitude<obj.Size.X/2 then humanoid.Health = 0 end end end end end game.Workspace.Caller.OnServerEvent:connect(function(plr,arg) if arg[1] == "Fireball" and arg[2] then local plrN = plr.Name if not cDownTab[plrN] then if plr.Character then local humanoid = plr.Character:FindFirstChild("Humanoid") local torso = plr.Character:FindFirstChild("Torso") if humanoid and humanoid.Health>0 and torso then local Ball = Instance.new("Part") Ball.Parent = game.Workspace Ball.Shape = "Ball" Ball.Size = Vector3.new(5,5,5) Ball.BrickColor = BrickColor.new("Really red") Ball.Transparency = intialTrans Ball.TopSurface = 0 Ball.BottomSurface = 0 Ball.Anchored = true Ball.CanCollide = false Ball.CFrame = torso.CFrame*CFrame.new(0,0.5,-5) print("Fireball started.") local vectorCalc = (arg[2].p-Ball.Position).unit print("Arg", arg[2].p, "Pos", Ball.Position, "Calc", vectorCalc) coroutine.resume(coroutine.create(function() checkFireBall(Ball,plrN) -- Check its initial position. for i = 0,range*fps/speed do Ball.CFrame = CFrame.new(Ball.Position)*CFrame.new(vectorCalc*speed/fps) checkFireBall(Ball,plrN) wait(1/fps) end for i = .1,.9,.1 do Ball.Transparency = intialTrans+((1-intialTrans)*i) wait() end Ball:Destroy() end)) cDownTab[plrN] = true wait(3) print("Fireball successful!") cDownTab[plrN] = nil end end end end end)
Add this portion to the Client Script, like in the StarterPlayerScripts.
local plr = game.Players.LocalPlayer local mouse = plr:GetMouse() mouse.KeyDown:connect(function(key) if key:lower() == "f" then game.Workspace.Caller:FireServer({"Fireball",mouse.Hit}) end end)
You will need a RemoteEvent that looks like this in Workspace in order for this code to work. Hope this helped, and if it did, don't forget to upvote!