Dropping a Tool Where the Users Mouse is

I’m trying to make it so that when the user presses Q, they drop their tool on the surface that their mouse is on. I know that this will require UIS and most likely Raycasting, but I have a hard time understanding raycasting so I’m looking for a bit of help. As a bonus, it would be nice if I could limit how far the user can drop the tool

I know it’s not good to make a post without starting code, but I’m really unsure how to start with this, so any help is appreciated.

2 Likes

I guess as pseudo-code/guidance you could do something like:

Player presses Q then reparent their tool to the workspace
The tool’s handle position is then moved to the mouse.hit.position

To make a range limit on dropping, you could use Magnitude to get the distance between the player and the mouse position.
Then if its beyond range then return.

Ok, the first part sounds simple enough. Only thing I’m not sure about is Magnitude. Do you have any resources that could help with that?

local __MAGNITUDE = (__CHARACTER.HumanoidRootPart.Position - __MOUSE.hit.Position).Magnintude 
-- GetDistanceFromCharacter() Could work too but i'm not sure..

Could you explain what this does? I assume it requires other pieces for it to work.

Its the distance from the player’s character to the mouse

Im not so sure but you might need to use a remote event for this.

-- client
if keycode == Enum.Keycode.Q then -- if key pressed on the keyboard is Q then..
   dropEvent:FireServer(mouse.Hit.Position, tool) -- Fire a remote event containing the mousepos and the tool.
end 

-- server
dropEvent.OnServerEvent:Connect(function(plr, mousePos, tool)
   if not tool:IsA("Tool") then return end
   if not tool:FindFirstChild("Handle") then return end

   local distance = player:DistanceFromCharacter(mousePos)
   if distance > limit then return end -- Checking if the distance is over the limit 

   tool.Handle.Position = mousePos -- Changing the handle's position to mousepos
   tool.Parent = workspace -- Reparenting the tool
end)

hope this helps :smiley: Added some new stuff
mark this as a solution if it worked.

Yes you do need an remote event to achieve this.
But to be more secure you should check the tool on the server instead of sending it to the server.
Since they could send something that is not a tool and change the position of the wrong thing.

And turns out you don’t need to use magnitude as with the player argument in the server event, you can just use player:DistanceFromCharater(mousePos)

1 Like

Ok, so I’m setting this up now, and just wanna make sure I get everything right. 1st, how would I define the mouse.Hit.Position in the Client script? 2nd, for the Server script, would I just use the players service for the player:DistanceFromCharacter? Last, how would I make this apply to all tools globally, because I noticed in the Client script, it has you specify a tool?

1:

local plr = game.Players.LocalPlayer
local mouse = plr:GetMouse()

2: No, its a Player instance method.
3: You mean all your tools in your backpack?

Yeah, like I want this to apply to all tools that the player picks up, instead of specifying different ones.

-- Client
if keycode == Enum.Keycode.Q then 
   dropEvent:FireServer(mouse.Hit.Position)
end 

-- Server
dropEvent.OnServerEvent:Connect(function(plr, mousePos)
  local limit = 100 -- You can change it to your liking.

  for _, tool in ipairs(plr.Backpack:GetChildren()) do
      if tool:FindFirstChild("Handle") then
         local handle = tool.Handle

         local distance = plr:DistanceFromCharacter(mousePos)
         if distance > limit then continue end

         tool.Handle.Position = mousePos
         tool.Parent = workspace
      end
   end
end)

mark this as a solution if it worked

1 Like

Ok, so I may just be missing something, but I set up print functions to confirm if this works. It prints when the even is fired in the Client, and prints when it is received in the Server, but it doesn’t actually drop the sword. There’s no errors, and no underlines. I added all the necessary variables as well (I think). Sorry about this.

It was probably because you equipped the sword when pressing Q, try the single tool drop version.

Ah I see. Could I make is so whatever tool the player is holding, he drops it? Not necessary, just would be a nice addition

You need zero raycasting for this, unless you want to prevent a player from dropping a tool through an impassable surface (such as a wall or terrain).

When the player clicks, set a variable to the mouse’s position like:

local mouseClickPosition = Mouse.Target.Position

Then, you just remove the tool from the player’s Character and put it into workspace, and then set its position to mouseClickPosition.

Optional step: if you want it so that a player can only drop the tool within a certain distance, you need to use .Magnitude to check how far the tool is from mouseClickPosition. You can do this like:

local maxRange = 30 -- 30 is just an example. put any number here, it is the maximum range in Studs.
if (tool.Position - mouseClickPosition).Magnitude < maxRange  then
    --> Congratulations! mouseClickPosition is within 30 studs of the tool!
    --> Remove tool from player's inventory and move it to mouseClickPosition.
else
    --> Oh no, you clicked more than 30 studs away from your character! This is illegal!!!
    print("Clicked outside max range, player cannot drop tool from this far away.")
end

Congratulations!

You dont need the magnitude thing, you can just do player:DistanceFromCharacter(mousePos) < maxRange

oh, didn’t know that existed, i’ll keep that in mind

you might want to close the topic now

So I was trying to make it so the tool you have equipped would be the one that’s dropped. I tried putting a Bool value in the tool, and when the tool is equipped, the value is set to true. When the tool is unequipped, the value is set to false.

local dropEvent = game.ReplicatedStorage.dropEvent

dropEvent.OnServerEvent:Connect(function(plr, mousePos, tool)
	local limit = 10 -- You can change it to your liking.
	
	for _, tool in ipairs(plr.Backpack:GetChildren()) do
	if tool:GetDescendants("Equipped").Value == true then
		if tool:FindFirstChild("Handle") then
			local handle = tool.Handle

			local distance = plr:DistanceFromCharacter(mousePos)
			if distance > limit then continue end
			
			tool.Parent = workspace
			tool.Handle.Position = mousePos + Vector3.new(0,1,0)
			end	
		end
	end
end)

I added the line under the start of the loop, and there are no errors, but it doesn’t seem to be working. Is there something wrong?

it should be tool:FindFirstChild("Equipped").Value.
If you are a beginner, make sure to watch scripting tutorials + practice.