Best way to cast magic

hello developers,

I am trying to create a spellcasting system. And i though, what was the most optimized and eaziest way to cast a “fireball”.

Just i fireball that goes to the mouse.
(just like the rocket launcher from roblox, but instead with a keybind and

So i have 2 questions.

I was thinking of how to make the most optimized magic, without the server needing to do much. (so how would i move the spell, and what to do with the vfx (particles, etc…) and hitboxes?)

How would i create the system. Should i create moduletree and do everything in a module? or should i put everything cleanly in 1 single script? (for all spells)

No scripts needed but it will be appriciated (if you have a open source or a magic system that you could give me for example.)

When casting ‘magic’ are you just clicking once and then a fireball is cast?

Yeah (its accualy when you press q but thats super eazy to edit)

I have an idea that you can use. First, cast a ray from the tip of the tool or wand to where the mouse clicked. The destinations shall be where the ray hit. Then, summon a fireball (you can customize this however you want). Then create a BodyForce with this code (this will make it float and have no gravity)

local force = Instance.new("BodyForce", --your fireball here)
force.Force = Vector3.new(0, --your fireball here:GetMass() * game.Workspace.Gravity, 0)

Then assign the fireball’s CFrame to point towards the position where the ray hit, then simply affect the fireball’s velocity with (fireball here).CFrame.LookVector * (speed)

EDIT: I just realized that it was binded to a key. In that case, spawn the fireball Infront of the character

yeah i found that in roblox rocket launcher script,

local Rocket = Instance.new('Part') do
	-- Set up the rocket part
	Rocket.Name = 'Rocket'
	Rocket.FormFactor = Enum.FormFactor.Custom --NOTE: This must be done before changing Size
	Rocket.Size = ROCKET_PART_SIZE
	Rocket.CanCollide = false

	-- Add the mesh
	local mesh = Instance.new('SpecialMesh', Rocket)
	mesh.MeshId = MISSILE_MESH_ID
	mesh.Scale = MISSILE_MESH_SCALE

	-- Add fire
	local fire = Instance.new('Fire', Rocket)
	fire.Heat = 5
	fire.Size = 2

	-- Add a force to counteract gravity LOOK ITS HERE
	local bodyForce = Instance.new('BodyForce', Rocket)
	bodyForce.Name = 'Antigravity'
	bodyForce.Force = Vector3.new(0, Rocket:GetMass() * GRAVITY_ACCELERATION, 0)

	-- Clone the sounds and set Boom to PlayOnRemove
	local swooshSoundClone = SwooshSound:Clone()
	swooshSoundClone.Parent = Rocket
	local boomSoundClone = BoomSound:Clone()
	boomSoundClone.PlayOnRemove = true
	boomSoundClone.Parent = Rocket

	-- Attach creator tags to the rocket early on
	local creatorTag = Instance.new('ObjectValue', Rocket)
	creatorTag.Value = MyPlayer
	creatorTag.Name = 'creator' --NOTE: Must be called 'creator' for website stats
	local iconTag = Instance.new('StringValue', creatorTag)
	iconTag.Value = Tool.TextureId
	iconTag.Name = 'icon'

	-- Finally, clone the rocket script and enable it
	local rocketScriptClone = RocketScript:Clone()
	rocketScriptClone.Parent = Rocket
	rocketScriptClone.Disabled = false
end

is doing this the best? Just give a velocity to a part?

Or should i do something else like tweening for example?

Uhm, my magic doesn’t have gravity bc i added a antigravity “BodyForce”. So i don’t think that this is usefull.

FastCast is multipurpose. If you don’t want gravity then set the vectory gravity to -gravity.

1 Like

I’ve done something like this before, and here is the major pieces:

Client:

local mouse = plr:GetMouse()
	
UserInputService.InputBegan:Connect(function(input, gameStuff)
	if gameStuff then return end
	
	if input.KeyCode == Enum.KeyCode.F then
		local fireball = GetFireball(plr.Data.Strength.Value) --Get fireball instance
		
		game.ReplicatedStorage.PowerRemotes.Fireball:FireServer(char, mouse.UnitRay.Direction, fireball) --Fire to server
	end
end)

Server:

local PowerRemotes = game.ReplicatedStorage.PowerRemotes

PowerRemotes.Fireball.OnServerEvent:Connect(function(plr, char, unitRay, fireball)
	local fireballClone = fireball:Clone()
	fireballClone.Parent = workspace
	fireballClone.Name = plr.Name .. "-Fireball"
	fireballClone.CFrame = CFrame.new(
		char.HumanoidRootPart.Position + unitRay * fireballClone.Size.X,
		unitRay
	)
	local velocity = unitRay * 100
	local bv = Instance.new("BodyVelocity", fireballClone)
	bv.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
	bv.Velocity = velocity
	
	game.Debris:AddItem(fireballClone, 7)
end)

It’s good if you add some debounce on the client (but checks made on the server) & a collision handling to add damage to it. Hope it helps though!

Edit: If you want to make the fireball “fly” faster, just change in the server the velocity variable

Is this the most optimized way of casting a fireball?

Can’t really confirm you this because that’s the only way I’ve ever done before, there might be more efficient ways which all fireballs would be handled by a single script (server-side) & the only thing the client would do would be checking for user input.