Shooting a fireball towards the mouse (with camera-lock on)

  1. What do you want to achieve?

Shoot a fireball in a line, in the direction of the players mouse, about 70 units out, while the shoulder lock camera is enabled. This needs to work even if I shoot at empty sky (no click surface) because in my game a big part is being able to target flying enemies to attack.

  1. What is the issue?

If I have the lock cursor camera turned off I fire a tween to shoot my fireball and it works great (fireball shoots from my position in a lookvector away from my humanoidrootpart), however if I have the lock camera turned on I want the projectile to shoot towards the mouse, but it just sits in front of the player.

  1. What solutions have you tried so far?

Here’s some server code: If shoulderCam is false the tween works great… it’s the tween in the else that’s failing.

if shoulderCam == false then
	tweenservice:Create(fireball, TweenInfo.new(3, 0, 0), {CFrame = player.Character.HumanoidRootPart.CFrame + player.Character.HumanoidRootPart.CFrame.lookVector * 70, Transparency = 1}, Enum.EasingStyle.Quint,Enum.EasingDirection.Out):Play()
else
	tweenservice:Create(fireball, TweenInfo.new(3, 0, 0), {CFrame = CFrame.new(player.Character.HumanoidRootPart.Position, mousePosition).LookVector * 70, Transparency = 1}, Enum.EasingStyle.Quint, Enum.EasingDirection.Out):Play()
end

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

Maybe it has to do with how I am getting “mousePosition”? Here is how I retrieve that (on the client):

-- Detect shoulder cam vs regular mouse use
local shoulderCam = false
local mousePosition = nil
if UserInputService.MouseBehavior == Enum.MouseBehavior.LockCenter then
	shoulderCam = true

	local mouse = player:GetMouse()
	local mouseHit = mouse.Hit
	local result = RayResult(mouseHit.Position.X, mouseHit.Position.Y)
	
	mousePosition = result.Position
end

and RayResult:

local function RayResult(x, y)
	local parameters = RaycastParams.new()
	parameters.FilterType = Enum.RaycastFilterType.Exclude
	parameters.FilterDescendantsInstances = {workspace.Scenery, workspace.Plots, player}
	
	local unitRay = camera:ScreenPointToRay(x, y)
    
	return workspace:Raycast(unitRay.Origin, unitRay.Direction * 500, parameters)
end

The shoulderCam and mousePosition are passed to the server via:

script.RemoteEvent:FireServer(shoulderCam, mousePosition)

I’ve tried playing with the raycast, the distance, also, converting from the Vector3 to the CFrame in the tween might be off, I’m just getting into that.

Should be all relevant code. Let me know if you all see something out of line. Thanks!

4 Likes

this is getting a 3d coordinate

This requires a 2D coorindate

Should work if you change that line to be

local result = RayResult(mouse.X, mouse.Y)
1 Like

sigh, I wrote a whole reply and I accidently closed the window.

Thank you for the suggestion @Snow. I made the change and the fireball is in the correct position, it’s just not moving forward. I am getting an error in the console related to my CFrame tween:

“TweenService:Create property named ‘CFrame’ cannot be tweened due to type mismatch (property is a ‘CoordinateFrame’, but given type is ‘Vector3’)” - Seems my mousePosition which is a Vector3 is not correct in my tween. Not sure how to fix it though. A Vector3 doesn’t have Position or CFrame.

Here is the tween line again it is complaining about:

tweenservice:Create(fireball, TweenInfo.new(3, 0, 0), {CFrame = CFrame.new(player.Character.HumanoidRootPart.Position, mousePosition).LookVector * 70, Transparency = 1}, Enum.EasingStyle.Quint, Enum.EasingDirection.Out):Play()

Tried a few variations including:

tweenservice:Create(fireball, TweenInfo.new(3, 0, 0), {CFrame = CFrame.new(mousePosition).LookVector * 70, Transparency = 1}, Enum.EasingStyle.Quint, Enum.EasingDirection.Out):Play()

That didn’t work either.

1 Like

No worries, you tried and really thats all I care about (*its the only way to get better) :slight_smile:
(Answer is at the bottom but figured I’d help as much as possible)

So, specifically related to the part about “A Vector3 doesn’t have Position or CFrame” – gonna use this as a very quick and hopefully very helpful “Roblox / Lua / Luau” teaching opportunity so you can better solve any problems and be super game dev.

This is the reference page on the roblox wiki. You’ve probaly seen it before, but there’s a lot of pages on there and they all kind of look the same. This one is one of the specifics you might care about. On the left you’ll see

  • Classes
  • DataTypes
  • Enums
  • Globals
  • Libraries

Only going to focus on the first two for now. “Classes” are basically the objects you insert into studio, like a part, or a screengui. You can find them all here and even their “Parent” classes (i.e. the objects that you cant insert directly, and are there to be used as as templates for the main objects. The most common example is how the BasePart is a parent class to Part, and it “inherits”.

If “Classes” are the types of objects, then DataType’s are the value of the objects properties (e.g. its name and CFrame). This is where the answer to your problem actually starts but the previous stuff is good context. If you open that list of DataTypes on the wiki, youll see a fairly long list of different things, all sorted alphabetically. In the C’s you’ll see CFrame and towards the bottom youll see Vector3. But you wont see Position anywhere, because that is the name of a property. It nerd terms, it is a property of a Class (in this case Part) and not its own DataType.

But if you Click on CFrame itll bring you to its documentation page. On the right youll see another list, with five main sections (note: the list may be expanded already)

  • Summary
  • Constructors
  • Properties
  • Methodds
  • Math operations

Under the properties section youll notice that CFrame actually does have a Position..

What’s going on here is that Position usually refers to a Vector3 datatype, whereas CFrame refers to the CFrame datatype (yes it is annoying that they couldn’t keep the names the same for both of them.)
But why does CFrame have a position? Well you can think of Objects (i.e. classes) as being tables, with each property and its value being a Key/Value pair. This is how it would look for the Position and CFrame properties on a Part

Example_Part = {
	Position = Vector3.new(0,1,0), -- X, Y, Z axis
	CFrame = {
		Position = Vector3.new(0,1,0), -- Also a position, still referring to XYZ
		Rotation = Vector3.new(0,0,0), -- A Vector3 represeting the rotation (in radians not degrees) about each axis (XYZ)
	},
}

So by doing CFrame.Position, you can get the Vector3 data that was stored there and use it as intended.

Going back to your code:

-- Changed for formatting but same stuff

local ts = game:GetService("TweenService")
local tweenInfo = TweenInfo.new(3, Enum.EasingStyle.Quint, Enum.EasingDirection.Out,0,0,0)
local targetCFrame = player.Character.HumanoidRootPart.CFrame.lookVector * 75 -- lookVector is a Vector3
local tweenProperties = {Transparency = 1, CFrame = CFrame,new(targetCFrame)} -- Create a CFrame using my Vector3
ts:Create(fireball, tweenInfo, tweenProperties):Play()
game.Debris:AddItem(fireball, 3) -- Optional, remove fireball after 3 seconds (tween length)

Hope this helps and good luck :slight_smile:

1 Like

Thank you Snow, this got me much closer. It still doesn’t seem to project, but I have an idea of how to work on it now. Thanks, marking as answer.

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