Roblox/luau_corpus huggingface dataset:
-- Creates a new tree node from an object. Called when an object starts
-- existing in the game tree.
addObject = function(object,noupdate,parent)
	if script then
		-- protect against naughty RobloxLocked objects
		local s = pcall(check,object)
		if not s then
			return
		end
	end

	local parentNode

	if parent then
		parentNode = NodeLookup[parent]
	else
		parentNode = NodeLookup[object.Parent]
	end

	if not parentNode then
		return
	end

	local objectNode = {
		Object = object;
		Parent = parentNode;
		Index = 0;
		Expanded = false;
		Selected = false;
		Depth = depth(object);
	}

	connLookup[object] = Connect(object.AncestryChanged,function(c,p)
		if c == object then
			if p == nil then
				removeObject(c)
			else
				moveObject(c,p)
			end
		end
	end)

	NodeLookup[object] = objectNode
	insert(parentNode,#parentNode+1,objectNode)

	if not noupdate then
		if nodeIsVisible(objectNode) then
			updateList()
		elseif nodeIsVisible(objectNode.Parent) then
			updateScroll()
		end
	end
end

local function makeObject(obj, par)
	--[[local newObject = Instance_new(obj.ClassName)
	for i,v in pairs(obj.Properties) do
		ypcall(function()
			local newProp
			newProp = ToPropValue(v.Value,v.Type)
			newObject[v.Name] = newProp
		end)
	end
	newObject.Parent = par

	obj.Properties.Parent = par--]]

	RemoteEvent:InvokeServer("InstanceNew", obj.ClassName, obj.Properties)
end

local function writeObject(obj)
	local newObject = {ClassName = obj.ClassName, Properties = {}}
	for i,v in pairs(RbxApi.GetProperties(obj.className)) do
		if v["Name"] ~= "Parent" then
			print("thispassed")
			table.insert(newObject.Properties,{Name = v["Name"], Type = v["ValueType"], Value = tostring(obj[v["Name"]])})
		end
	end
	return newObject
end

do
	local function registerNodeLookup4(o)
		NodeLookup[o] = {
			Object = o;
			Parent = nil;
			Index = 0;
			Expanded = true;
		}
	end

	registerNodeLookup4(game)

	NodeLookup[DexOutput] = {
		Object = DexOutput;
		Parent = nil;
		Index = 0;
		Expanded = true;
	}

	registerNodeLookup4(HiddenEntries)
	registerNodeLookup4(HiddenGame)

	Connect(game.DescendantAdded,addObject)
	Connect(game.DescendantRemoving,removeObject)

	Connect(DexOutput.DescendantAdded,addObject)
	Connect(DexOutput.DescendantRemoving,removeObject)

	local function get(o)
		return o:GetChildren()
	end

	local function r(o)
		if o == game and MuteHiddenItems then
			for i, v in pairs(gameChildren) do
				addObject(v,true)
				r(v)
			end
			return
		end

		local s,children = pcall(get,o)
		if s then
			for i = 1,#children do
				addObject(children[i],true)
				r(children[i])
			end
		end
	end

	r(game)
	r(DexOutput)

	r(HiddenEntries)

	scrollBar.VisibleSpace = math.ceil(listFrame.AbsoluteSize.y/ENTRY_BOUND)
	updateList()
end
--////////////////////////////// Methods
--//////////////////////////////////////
local methods = {}
methods.__index = methods

function methods:GetInstance(className)
  if self.InstancePoolsByClass[className] == nil then
    self.InstancePoolsByClass[className] = {}
  end
  local availableInstances = #self.InstancePoolsByClass[className]
  if availableInstances > 0 then
    local instance = self.InstancePoolsByClass[className][availableInstances]
    table.remove(self.InstancePoolsByClass[className])
    return instance
  end
  return Instance.new(className)
end

function methods:ReturnInstance(instance)
  if self.InstancePoolsByClass[instance.ClassName] == nil then
    self.InstancePoolsByClass[instance.ClassName] = {}
  end
  if #self.InstancePoolsByClass[instance.ClassName] < self.PoolSizePerType then
    table.insert(self.InstancePoolsByClass[instance.ClassName], instance)
  else
    instance:Destroy()
  end
end
--[=[
	@return PROPERTY_MARKER
	Returns a marker that will transform the current key into
	a RemoteProperty once the service is created. Should only
	be called within the Client table of a service. An initial
	value can be passed along as well.

	RemoteProperties are great for replicating data to all of
	the clients. Different data can also be set per client.

	See [RemoteProperty](https://sleitnick.github.io/RbxUtil/api/RemoteProperty)
	documentation for more info.

	```lua
	local MyService = Knit.CreateService {
		Name = "MyService",
		Client = {
			-- Create the property marker, which will turn into a
			-- RemoteProperty when Knit.Start() is called:
			MyProperty = Knit.CreateProperty("HelloWorld"),
		},
	}

	function MyService:KnitInit()
		-- Change the value of the property:
		self.Client.MyProperty:Set("HelloWorldAgain")
	end
	```
]=]
function KnitServer.CreateProperty(initialValue: any)
	return { PROPERTY_MARKER, initialValue }
end
-- How many times per second the gun can fire
local FireRate = 20 / 30
-- (Hat Giver Script - Loaded.)

debounce = true

function onTouched(hit)
	if (hit.Parent:findFirstChild("Humanoid") ~= nil and debounce == true) then
		debounce = false
		h = Instance.new("Hat")
		p = Instance.new("Part")
		h.Name = "Valkyrie Helm"
		p.Parent = h
		p.Position = hit.Parent:findFirstChild("Head").Position
		p.Name = "Handle" 
		p.formFactor = 0
		p.Size = Vector3.new(1, 2, 1) 
		p.BottomSurface = 0 
		p.TopSurface = 0 
		p.Locked = true 
		script.Parent.Mesh:clone().Parent = p
		h.Parent = hit.Parent
		h.AttachmentForward = Vector3.new (-0, -0.124, -0.992)
		h.AttachmentPos = Vector3.new(0.07, -0.4, 0.5)
		h.AttachmentRight = Vector3.new (1, -0, 0)
		h.AttachmentUp = Vector3.new (0, 0.992, -0.124)
		wait(5)
		debounce = true
	end
end

script.Parent.Touched:connect(onTouched)
--// Hash: 9043abc9834370d0811d3561bb07616137d303330a5e983d0bce677e5fdf5cb35241b3933100842275d036cb9b9de3c8
-- Decompiled with the Synapse X Luau decompiler.

return {
	ButtonX = "rbxassetid://9876149963", 
	ButtonY = "rbxassetid://9876149854", 
	ButtonA = "rbxassetid://9876150181", 
	ButtonB = "rbxassetid://9876150092"
};
-- Decompiled with the Synapse X Luau decompiler.

local function u1(p1, p2)
	p2 = p2 or {};
	if type(p1) ~= "table" then
		return p1;
	end;
	if p2[p1] then
		return p2[p1];
	end;
	local v1 = {};
	p2[p1] = v1;
	for v2, v3 in next, p1 do
		v1[u1(v2, p2)] = u1(v3, p2);
	end;
	setmetatable(v1, u1(getmetatable(p1), p2));
	return v1;
end;
local l__HttpService__2 = game:GetService("HttpService");
return function(p3, p4)
	if p4 then
		return u1(p3);
	end;
	return l__HttpService__2:JSONDecode(l__HttpService__2:JSONEncode(p3));
end;
-- / Teams / --
local PlayingTeam = game.Teams.Playing
local LobbyTeam = game.Teams.Lobby
-- Decompiled with the Synapse X Luau decompiler.

client = nil;
service = nil;
return function(p1)
	local v1 = {
		Name = "Explorer", 
		Title = "Game Explorer", 
		Size = { 400, 300 }, 
		MinSize = { 150, 100 }, 
		AllowMultiple = false
	};
	local u1 = nil;
	local u2 = game;
	function v1.OnRefresh()
		u1(u2);
	end;
	local v2 = client.UI.Make("Window", v1);
	local u3 = nil;
	local u4 = game;
	local u5 = nil;
	local function u6(p2, p3, p4, p5)
		local v3 = u3:Add("TextLabel", {
			Text = "  " .. tostring(p3), 
			ToolTip = p2.ClassName, 
			TextXAlignment = "Left", 
			Size = UDim2.new(1, 0, 0, 30), 
			Position = UDim2.new(0, 0, 0, 30 * p4)
		});
		local v4 = {
			Text = "Delete", 
			Size = UDim2.new(0, 80, 0, 30), 
			Position = UDim2.new(1, -160, 0, 0), 
			Visible = not p5
		};
		function v4.OnClick()
			u2 = u2.Parent or game;
			client.Remote.Send("HandleExplore", p2, "Delete");
			p2:Destroy();
			u1(u2);
		end;
		local v5 = v3:Add("TextButton", v4);
		local v6 = v3:Add("TextButton", {
			Text = "Open", 
			Size = UDim2.new(0, 80, 0, 30), 
			Position = UDim2.new(1, -80, 0, 0), 
			OnClick = function()
				u4 = u2;
				u2 = p2;
				u1(p2);
			end
		});
	end;
	u1 = function(p6)
		local l__Text__7 = u5.Text;
		local v8 = 1;
		u3:ClearAllChildren();
		u6(p6.Parent or (u4 or game), "Previous Parent (Go Up..)", 0, true);
		local l__next__9 = next;
		local v10, v11 = p6:GetChildren();
		while true do
			local v12, v13 = l__next__9(v10, v11);
			if not v12 then
				break;
			end;
			v11 = v12;
			local u7 = v8;
			pcall(function()
				if v13.Name:sub(1, #l__Text__7):lower() == l__Text__7:lower() or v13.ClassName:sub(1, #l__Text__7):lower() == l__Text__7:lower() then
					u6(v13, v13.Name, u7);
					u7 = u7 + 1;
				end;
			end);		
		end;
		u3:ResizeCanvas(false, true, false, false, 5, 5);
	end;
	if v2 then
		u3 = v2:Add("ScrollingFrame", {
			List = {}, 
			ScrollBarThickness = 2, 
			BackgroundTransparency = 1, 
			Position = UDim2.new(0, 5, 0, 30), 
			Size = UDim2.new(1, -10, 1, -30)
		});
		u5 = v2:Add("TextBox", {
			Size = UDim2.new(1, -10, 0, 20), 
			Position = UDim2.new(0, 5, 0, 5), 
			BackgroundTransparency = 0.5, 
			BorderSizePixel = 0, 
			TextColor3 = Color3.new(1, 1, 1), 
			Text = "", 
			PlaceholderText = "Search", 
			TextStrokeTransparency = 0.8
		});
		u5.FocusLost:connect(function(p7)
			u1(u2, u5.Text);
		end);
		u1(game);
		local l__gTable__14 = v2.gTable;
		v2:Ready();
	end;
end;
-----------------------------------------------------------
----------------------- STATIC DATA -----------------------
-----------------------------------------------------------
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
local ReplicatedStorage = game:GetService("ReplicatedStorage").TankGunsFolder

local Modules = ReplicatedStorage:WaitForChild("Modules")

local Utilities = require(Modules.Utilities)
local Signal = Utilities.Signal
local table = Utilities.Table
local Thread = Utilities.Thread

local TargetEvent
if RunService:IsClient() then
	TargetEvent = RunService.RenderStepped
else
	TargetEvent = RunService.Heartbeat
end

local Projectiles = {}
local RemoveList = {}
--- Switches to the specified targeting mode.
-- @returns void
function TargetingModule:SetTargetingMode(NewTargetingMode)
	if (NewTargetingMode == 'Scoped') or (NewTargetingMode == 'Direct') then
		self.TargetingMode = NewTargetingMode
		self.TargetingModeChanged:Fire(NewTargetingMode)
	else
		error('Invalid targeting mode', 2)
	end
end
-- Event Bindings
DisplayIntermission.OnClientEvent:Connect(OnDisplayIntermission)
---------------------------------------------------

Displays = 3 -- Sets how many displays this scripts will use...
DisplayColor = Color3.fromRGB(85, 85, 255)
--[=[
	@within TableUtil
	@function Map
	@param tbl table
	@param predicate (value: any, key: any, tbl: table) -> newValue: any
	@return table

	Performs a map operation against the given table, which can be used to
	map new values based on the old values at given keys/indices.

	For example:

	```lua
	local t = {A = 10, B = 20, C = 30}
	local t2 = TableUtil.Map(t, function(value)
		return value * 2
	end)
	print(t2) --> {A = 20, B = 40, C = 60}
	```
]=]
local function Map<T, M>(t: { T }, f: (T, number, { T }) -> M): { M }
	assert(type(t) == "table", "First argument must be a table")
	assert(type(f) == "function", "Second argument must be a function")
	local newT = table.create(#t)
	for k, v in t do
		newT[k] = f(v, k, t)
	end
	return newT
end
--- Flash text color (good for visually showing updates to text)


return function(textLabel, speed)
	--- Variables
	speed = speed or 1
	
	--- Cache original text color (or grab it)
	local originalTextColor = _L.GUIFX.CacheProperty(textLabel, "TextColor3")
	
	--- Change to 'flashed' text
	if originalTextColor == Color3.new(1, 1, 1) then
		--- Half text color saturation
		textLabel.TextColor3 = Color3.new(
			originalTextColor.r / 2,  
			originalTextColor.g / 2, 
			originalTextColor.b / 2
		)
	else
		--- Double text color saturation
		textLabel.TextColor3 = Color3.new(
			originalTextColor.r * 2,  
			originalTextColor.g * 2, 
			originalTextColor.b * 2
		)
	end
	
	--- Revert (fade in)
	local tween = _L.Functions.FastTween(textLabel, {TextColor3 = originalTextColor}, {speed, EasingStyle})
end
-- Function to handle key input
local function handleKeyPress(input, gameProcessedEvent)
	if not gameProcessedEvent and input.KeyCode == Enum.KeyCode.LeftShift then
		setWalkspeed(desiredWalkspeed)
	end
end
--[=[
	@class Keyboard
	@client

	The Keyboard class is part of the Input package.

	```lua
	local Keyboard = require(packages.Input).Keyboard
	```
]=]
local Keyboard = {}
Keyboard.__index = Keyboard
--------------------) Settings
Damage = 0 -- the ammout of health the player or mob will take

Cooldown = 5 -- cooldown for use of the tool again

ZoneModelName = "Red ring" -- name the zone model

MobHumanoidName = "Humanoid"-- the name of player or mob u want to damage
----[FIRE FUNCTIONS WHEN PLUGIN SIZE CHANGES]----
local function PluginChanged()
	ResizeSlider()
end
PluginGui.Changed:Connect(PluginChanged)
-- TableUtil
-- Stephen Leitnick
-- September 13, 2017


type Table = {any}
type MapPredicate = (any, any, Table) -> any
type FilterPredicate = (any, any, Table) -> boolean
type ReducePredicate = (any, any, any, Table) -> any
type FindCallback = (any, any, Table) -> boolean
type IteratorFunc = (t: Table, k: any) -> (any, any)
----------------------------------------------------------------------------------------------------
--------------------=[ OUTROS ]=--------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
	,FastReload = false					--- Automatically operates the bolt on reload if needed
	,SlideLock = false
	,MoveBolt = false
	,BoltLock = false
	,CanBreachDoor = false
	,CanBreak = false					--- Weapon can jam?
	,JamChance = 1000					--- This old piece of brick doesn't work fine >;c
	,IncludeChamberedBullet = false		--- Include the chambered bullet on next reload
	,Chambered = false					--- Start with the gun chambered?
	,LauncherReady = false				--- Start with the GL ready?
	,CanCheckMag = false					--- You can check the magazine
	,ArcadeMode = false					--- You can see the bullets left in magazine
	,RainbowMode = false				--- Operation: Party Time xD
	,ModoTreino = false					--- Surrender enemies instead of killing them
	,GunSize = 6.5
	,GunFOVReduction = 5.5

	,BoltExtend = Vector3.new(0, 0, 0.4)
	,SlideExtend = Vector3.new(0, 0, 0.4)
-- initialize to idle
playAnimation("idle", 0.1, zombie)
pose = "Standing"
-----------------------------------------------------------------------------------------------

ItemID = 97569329 -- The ID of the Gamepass/T-Shirt.
OpenTime = 0 -- The time the door is open for.
OpenTrans = 1 -- The transparency of the door when it is open.
CloseTrans = 1 -- The transparency of the door when it is closed.
BuyGUI = true -- Set to false to stop the BuyGUI appearing.
KillOnTouch = false -- Set to false to stop players being killed when they touch it.
-- create a basic loading gui
local screenGui = Instance.new("ScreenGui")
local textLabel = Instance.new("TextLabel", screenGui)
textLabel.Text = "Loading"
textLabel.Position = UDim2.new(0.5, 0, 0.5, 0)
textLabel.AnchorPoint = Vector2.new(0.5, 0.5)
textLabel.Size = UDim2.new(1 , 0, 1, 100) -- make sure the topbar is covered
textLabel.FontSize = Enum.FontSize.Size14
screenGui.Parent = playerGui
--
--local TwinService = game:GetService("TweenService")
--local AnimationHighLight = TweenInfo.new(3)
--local Info = {FillTransparency = 0}
--local Animka = TwinService:Create(HighLight, AnimationHighLight, Info )
--local char = script.Parent
local hum = char:WaitForChild("Humanoid")
local deathAnim = hum:LoadAnimation(script.DeathAnim)
hum.BreakJointsOnDeath = false
local dead = false
--- Setting Fire ---
local fire = script.Fire
fire.Parent = pellet
fire.Enabled = true
damage = 15


local DebrisService = game:GetService('Debris')

function TagHumanoid(humanoid, vPlayer)
	-- Add more tags here to customize what tags are available.
	local creatorTag = Instance.new("ObjectValue")
	creatorTag.Value = vPlayer
	creatorTag.Name = "creator"
	creatorTag.Parent = humanoid
	DebrisService:AddItem(creatorTag, 1.5)
end

function FireScript(human)
	if human.Parent.Torso:FindFirstChild("FIRE")~= nil then
	else
		local FireBurn = script.FIRE:Clone()
		FireBurn.Parent = human.Parent.Torso
		FireBurn.FireDamage.Disabled = false
	end
end

function onTouched(hit)
	if hit and hit.Parent then
		if HitPeople[hit.Parent.Name] then
--

h = script.Parent.Parent:WaitForChild("Enemy")
pathService = game:GetService("PathfindingService")
targetV = script.Parent:WaitForChild("Target")

function closestTargetAndPath()
	local humanoids = {}
	if targetNPCs then
		local function recurse(o)
			for _,obj in pairs(o:GetChildren()) do
				if obj:IsA("Model") then
					if obj:findFirstChild("Humanoid") and obj:findFirstChild("Torso") and obj.Humanoid ~= h and obj.Humanoid.Health > 0 and not obj:findFirstChild("ForceField") then
						table.insert(humanoids,obj.Humanoid)
					end
				end
				recurse(obj)
			end
		end
		recurse(workspace)
	else
		for _,v in pairs(game.Players:GetPlayers()) do
			if v.Character and v.Character:findFirstChild("HumanoidRootPart") and v.Character:findFirstChild("Humanoid") and v.Character.Humanoid.Health > 0 and not v:findFirstChild("ForceField") then
				table.insert(humanoids,v.Character.Humanoid)
			end
		end
	end
	local closest,path,dist
	for _,humanoid in pairs(humanoids) do
		local myPath = pathService:ComputeRawPathAsync(h.Torso.Position,humanoid.Torso.Position,500)
		if myPath.Status ~= Enum.PathStatus.FailFinishNotEmpty then
			-- Now that we have a successful path, we need to figure out how far we need to actually travel to reach this point.
			local myDist = 0
			local previous = h.Torso.Position
			for _,point in pairs(myPath:GetPointCoordinates()) do
				myDist = myDist + (point-previous).magnitude
				previous = point
			end
			if not dist or myDist < dist then -- if true, this is the closest path so far.
				closest = humanoid
				path = myPath
				dist = myDist
			end
		end
	end
	return closest,path
end

function goToPos(loc)
	h:MoveTo(loc)
	local distance = (loc-h.Torso.Position).magnitude
	local start = tick()
	while distance > 4 do
		if tick()-start > distance/h.WalkSpeed then -- Something may have gone wrong. Just break.
			break
		end
		distance = (loc-h.Torso.Position).magnitude
		wait()
	end
end

while wait() do
	local target,path = closestTargetAndPath()
	local didBreak = false
	local targetStart
	if target and h.Torso then
		targetV.Value = target
		targetStart = target.Torso.Position
		roaming = false
		local previous = h.Torso.Position
		local points = path:GetPointCoordinates()
		local s = #points > 1 and 2 or 1
		for i = s,#points do
			local point = points[i]
			if didBreak then 
				break
			end
			if target and target.Torso and target.Health > 0 then
				if (target.Torso.Position-targetStart).magnitude < 1.5 then
					local pos = previous:lerp(point,.5)
					local moveDir = ((pos - h.Torso.Position).unit * 2)
					goToPos(previous:lerp(point,.5))
					previous = point
				end
			else
				didBreak = true
				break
			end
		end
	else
		targetV.Value = nil
	end
	if not didBreak and targetStart then
		goToPos(targetStart)
	end
end
-- emote bindable hook
script:WaitForChild("PlayEmote").OnInvoke = function(emote)
	-- Only play emotes when idling
	if pose ~= "Standing" then
		return
	end

	if emoteNames[emote] ~= nil then
		-- Default emotes
		playAnimation(emote, EMOTE_TRANSITION_TIME, Humanoid)
		
		return true, currentAnimTrack
	elseif typeof(emote) == "Instance" and emote:IsA("Animation") then
		-- Non-default emotes
		playEmote(emote, EMOTE_TRANSITION_TIME, Humanoid)

		return true, currentAnimTrack
	end
	
	-- Return false to indicate that the emote could not be played
	return false
end

if Character.Parent ~= nil then
	-- initialize to idle
	playAnimation("idle", 0.1, Humanoid)
	pose = "Standing"
end
--[[
	Creates an interest point that the monsters can pathfind to at specified position, and with specified weight. If no timeout is supplied, then the interest point exists forever
]]
function MonsterManager.createInterest(position, weight, timeout)
	local entry = {position = position, weight = weight}

	table.insert(interests, entry)

	if timeout then
		delay(
			timeout,
			function()
				interests = TableUtils.without(interests, entry)

				MonsterManager.updateMonsterInterests()
			end
		)
	end

	MonsterManager.updateMonsterInterests()
end
--[=[
	@param ... any -- Arguments to pass to the server
	Fires the equivalent server-side signal with the given arguments.

	:::note Outbound Middleware
	All arguments pass through any outbound middleware before being
	sent to the server.
	:::
]=]
function ClientRemoteSignal:Fire(...: any)
	if self._hasOutbound then
		self._re:FireServer(self:_processOutboundMiddleware(...))
	else
		self._re:FireServer(...)
	end
end
-------------------------
function onClicked()
Car.BodyVelocity.velocity = Vector3.new(0, -8, 0)
end
script.Parent.ClickDetector.MouseClick:connect(onClicked)
--// Recoil Settings	
	gunrecoil = -0.5; -- How much the gun recoils backwards when not aiming
	camrecoil = 0.26; -- How much the camera flicks when not aiming
	AimGunRecoil = -0.1; -- How much the gun recoils backwards when aiming
	AimCamRecoil = 0.13; -- How much the camera flicks when aiming
	
	CamShake = 0.5; -- THIS IS NEW!!!! CONTROLS CAMERA SHAKE WHEN FIRING
	AimCamShake = 0.5; -- THIS IS ALSO NEW!!!!
	
	Kickback = 1.5; -- Upward gun rotation when not aiming
	AimKickback = 0.2; -- Upward gun rotation when aiming
--

function Raycast.FindPartOnRayWithCallbackWithIgnoreList(ray, list, terrainCellsAreCubes, ignoreWater, loopout, callbackFunc)
	local maxDistance = ray.Direction.Magnitude
	local direction = ray.Direction.Unit
	
	loopout = loopout or 25
	local loopCount = 0
	
	local lastPosition = ray.Origin
	local distance = 0
	
	local hit, position, normal, material
	
	repeat
		local r = Ray.new(lastPosition, direction * (maxDistance - distance))
		hit, position, normal, material = WORKSPACE:FindPartOnRayWithIgnoreList(ray, list, terrainCellsAreCubes, ignoreWater, true)
		local result = callbackFunc(hit, position, normal, material)
		
		if (result == CALLBACKRESULT.Continue) then
			distance = (ray.Origin - position).Magnitude
			lastPosition = position
		elseif (result == CALLBACKRESULT.Finished) then
			return hit, position, normal, material
		elseif (result == CALLBACKRESULT.Fail or result == nil) then
			break
		end
		
		loopCount = loopCount + 1
	until (loopCount > loopout or distance >= maxDistance - 0.1)
	
	return
end

function Raycast.FindPartOnRayWithCallbackWithWhiteList(ray, list, terrainCellsAreCubes, ignoreWater, loopout, callbackFunc)
	local maxDistance = ray.Direction.Magnitude
	local direction = ray.Direction.Unit
	
	loopout = loopout or 25
	local loopCount = 0
	
	local lastPosition = ray.Origin
	local distance = 0
	
	local hit, position, normal, material
	
	repeat
		local r = Ray.new(lastPosition, direction * (maxDistance - distance))
		hit, position, normal, material = WORKSPACE:FindPartOnRayWithWhitelist(ray, list, terrainCellsAreCubes, ignoreWater, true)
		if hit then
			--print(hit:GetFullName())
			end
		local result = callbackFunc(hit, position, normal, material)
		
		if (result == CALLBACKRESULT.Continue) then
			distance = (ray.Origin - position).Magnitude
			lastPosition = position
		elseif (result == CALLBACKRESULT.Finished) then
			return hit, position, normal, material
		elseif (result == CALLBACKRESULT.Fail or result == nil) then
			break
		end
		loopCount = loopCount + 1
	until (loopCount > loopout or distance >= maxDistance - 0.1)
	
	return
end

function Raycast.FindPartOnRayWithCallback(ray, ignore, terrainCellsAreCubes, ignoreWater, callbackFunc)
	return Raycast.FindPartOnRayWithCallbackWithIgnoreList(ray, {ignore}, terrainCellsAreCubes, ignoreWater, callbackFunc)
end