Description

[made by ai = might be buggy if you find a bug just fix it urself lol i got no idea how to script i make these for myself but you can use if you want i guess] Project ghoul simple auto farm script and tp to npcs HOW TO USE HOW TO USE: you just gotta manually grab the quest first turn on auto repeat and start the farm thats it, check profile for other scripts

Features

  • + Auto farm
  • + fly
  • + Auto quest
  • + Auto farming levels
  • + free
  • + keyless
  • + open source

Supported Executors

Xeno Volt Potassium Wave Delta Solara Opiumware Codex MacSploit Vega X Velocity

Script

Add Xeno Scripts as a preferred source
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local HttpService = game:GetService("HttpService")
local RunService = game:GetService("RunService")
local player = Players.LocalPlayer

if not player then return end
local playerGui = player:WaitForChild("PlayerGui")

local Settings = {
	Running            = false,
	Position           = "Above",
	Height             = 6,
	HeightMin          = 4,
	MaxEngageDist      = 30,
	ForceHitFallback   = false,
	AttackIntervalMin  = 0.28,
	AttackIntervalMax  = 0.5,
	SpamIntervalMin    = 0.12,
	SpamIntervalMax    = 0.2,
	SkillInterval      = 1.8,
	UseSkills          = true,
	SkillDefs = {
		{ key = "Z", what = "skill1", enabled = true,  last = 0, cd = 2.5 },
		{ key = "X", what = "skill2", enabled = true,  last = 0, cd = 3.0 },
		{ key = "C", what = "skill3", enabled = true,  last = 0, cd = 3.5 },
		{ key = "V", what = "skill4", enabled = false, last = 0, cd = 4.0 },
	},
	SearchInterval     = 0.12,
	EquipInterval      = 2,
	MarkRadius         = 300,
	InteractRetries    = 3,
	InteractRetryDelay = 1,
	AutoRepeatEnabled  = false,
	CurrentTarget      = nil,
	CurrentRoot        = nil,
	LastAttack         = 0,
	LastEquip          = 0,
	LastQuestName      = "",
	LastQuestProgress  = -1,
	QuestBusyUntil     = 0,
}

local isTeleporting = false
local teleportConnection = nil

local selectedNPC = nil
local npcList = {}
local npcButtons = {}

local startTime = 0
local runTimerConnection = nil

local randomFloat = function(min, max)
	return min + math.random() * (max - min)
end

local ATTACK_TAG = "Att\208\176ck"

local Events = ReplicatedStorage:WaitForChild("Events", 30)
local remote = Events and Events:WaitForChild("RemoteEvent", 30)
local mouseRequest = Events and Events:FindFirstChild("MouseRequest")

local aliveFolder    = workspace:WaitForChild("NPCs", 30):WaitForChild("Alive", 30)
local marksFolder    = workspace:FindFirstChild("NPCs") and workspace.NPCs:FindFirstChild("Marks")
local dialoguesFolder= workspace:FindFirstChild("dialogues")

local data = player:WaitForChild("data", 30)
local questData = data and data:WaitForChild("questData", 30)

local oldGui = playerGui:FindFirstChild("FarmingMenu")
if oldGui then oldGui:Destroy() end

local gui = Instance.new("ScreenGui")
gui.Name = "FarmingMenu"
gui.ResetOnSpawn = false
gui.IgnoreGuiInset = true
gui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
gui.Parent = playerGui

local main = Instance.new("Frame")
main.Size = UDim2.new(0, 350, 0, 490)
main.Position = UDim2.new(0, 25, 0.5, -200)
main.BackgroundColor3 = Color3.fromRGB(18, 18, 23)
main.BorderSizePixel = 0
main.Parent = gui
Instance.new("UICorner", main).CornerRadius = UDim.new(0, 10)
local stroke = Instance.new("UIStroke")
stroke.Color = Color3.fromRGB(70, 70, 82); stroke.Thickness = 1; stroke.Parent = main

local titleBar = Instance.new("Frame")
titleBar.Size = UDim2.new(1, 0, 0, 44)
titleBar.BackgroundColor3 = Color3.fromRGB(28, 28, 35)
titleBar.BorderSizePixel = 0
titleBar.Parent = main
Instance.new("UICorner", titleBar).CornerRadius = UDim.new(0, 10)

local title = Instance.new("TextLabel")
title.BackgroundTransparency = 1
title.Position = UDim2.new(0, 14, 0, 0)
title.Size = UDim2.new(1, -55, 1, 0)
title.Font = Enum.Font.GothamBold
title.Text = "Simple Quest Farm"
title.TextColor3 = Color3.fromRGB(245, 245, 250)
title.TextSize = 17
title.TextXAlignment = Enum.TextXAlignment.Left
title.Parent = titleBar

local minimize = Instance.new("TextButton")
minimize.Size = UDim2.new(0, 34, 0, 30)
minimize.Position = UDim2.new(1, -40, 0, 7)
minimize.BackgroundTransparency = 1
minimize.Font = Enum.Font.GothamBold
minimize.Text = "—"
minimize.TextColor3 = Color3.fromRGB(230, 230, 235)
minimize.TextSize = 20
minimize.Parent = titleBar

local content = Instance.new("Frame")
content.BackgroundTransparency = 1
content.Position = UDim2.new(0, 12, 0, 52)
content.Size = UDim2.new(1, -24, 1, -60)
content.Parent = main

local function makeButton(name, text, y, w)
	local button = Instance.new("TextButton")
	button.Name = name
	button.Size = UDim2.new(w or 1, 0, 0, 36)
	button.Position = UDim2.new(0, 0, 0, y)
	button.BackgroundColor3 = Color3.fromRGB(36, 36, 44)
	button.BorderSizePixel = 0
	button.AutoButtonColor = true
	button.Font = Enum.Font.GothamSemibold
	button.Text = text
	button.TextColor3 = Color3.fromRGB(235, 235, 240)
	button.TextSize = 13
	button.Parent = content
	local c = Instance.new("UICorner")
	c.CornerRadius = UDim.new(0, 7)
	c.Parent = button
	return button
end

local toggleButton = makeButton("Toggle", "Farming: OFF", 0)
toggleButton.BackgroundColor3 = Color3.fromRGB(36, 36, 44)

local autoToggleButton = makeButton("AutoRepeat", "Auto Repeat: OFF", 42)

local aboveButton = makeButton("Above", "Position: ABOVE", 84)
local downButton  = makeButton("Down", "Position: DOWN", 126)

local skillsButton = makeButton("Skills", "Skills: ALL ON", 168)

local skillToggleButtons = {}
local skillTogglesFrame = Instance.new("Frame")
skillTogglesFrame.BackgroundTransparency = 1
skillTogglesFrame.Position = UDim2.new(0, 0, 0, 210)
skillTogglesFrame.Size = UDim2.new(1, 0, 0, 32)
skillTogglesFrame.Parent = content

for i, sd in ipairs(Settings.SkillDefs) do
	local b = Instance.new("TextButton")
	b.Name = "Skill" .. sd.key
	b.Size = UDim2.new(0.25, -4, 1, 0)
	b.Position = UDim2.new(0.25 * (i - 1), 4 * (i - 1), 0, 0)
	b.BackgroundColor3 = sd.enabled and Color3.fromRGB(63, 124, 235) or Color3.fromRGB(36, 36, 44)
	b.BorderSizePixel = 0
	b.Font = Enum.Font.GothamSemibold
	b.Text = sd.key
	b.TextColor3 = Color3.fromRGB(235, 235, 240)
	b.TextSize = 14
	b.Parent = skillTogglesFrame
	local c = Instance.new("UICorner")
	c.CornerRadius = UDim.new(0, 7)
	c.Parent = b
	skillToggleButtons[i] = b
end

local heightBox = Instance.new("TextBox")
heightBox.Size = UDim2.new(1, 0, 0, 32)
heightBox.Position = UDim2.new(0, 0, 0, 252)
heightBox.BackgroundColor3 = Color3.fromRGB(36, 36, 44)
heightBox.BorderSizePixel = 0
heightBox.ClearTextOnFocus = false
heightBox.Font = Enum.Font.Gotham
heightBox.TextSize = 13
heightBox.TextColor3 = Color3.fromRGB(240, 240, 245)
heightBox.Text = "Height: " .. tostring(Settings.Height)
heightBox.Parent = content
Instance.new("UICorner", heightBox).CornerRadius = UDim.new(0, 7)

local timerLabel = Instance.new("TextLabel")
timerLabel.Size = UDim2.new(1, 0, 0, 24)
timerLabel.Position = UDim2.new(0, 0, 0, 294)
timerLabel.BackgroundTransparency = 1
timerLabel.Font = Enum.Font.Gotham
timerLabel.TextSize = 14
timerLabel.TextColor3 = Color3.fromRGB(200, 200, 210)
timerLabel.TextXAlignment = Enum.TextXAlignment.Center
timerLabel.TextYAlignment = Enum.TextYAlignment.Center
timerLabel.Text = "Time: 00:00:00"
timerLabel.Parent = content

local npcDropdownBtn = Instance.new("TextButton")
npcDropdownBtn.Size = UDim2.new(0.7, 0, 0, 32)
npcDropdownBtn.Position = UDim2.new(0, 0, 0, 328)
npcDropdownBtn.BackgroundColor3 = Color3.fromRGB(40, 40, 50)
npcDropdownBtn.BorderSizePixel = 0
npcDropdownBtn.Font = Enum.Font.GothamSemibold
npcDropdownBtn.Text = "Select NPC"
npcDropdownBtn.TextColor3 = Color3.fromRGB(235, 235, 240)
npcDropdownBtn.TextSize = 13
npcDropdownBtn.Parent = content
Instance.new("UICorner", npcDropdownBtn).CornerRadius = UDim.new(0, 7)

local npcTeleportBtn = Instance.new("TextButton")
npcTeleportBtn.Size = UDim2.new(0.28, 0, 0, 32)
npcTeleportBtn.Position = UDim2.new(0.72, 0, 0, 328)
npcTeleportBtn.BackgroundColor3 = Color3.fromRGB(0, 160, 80)
npcTeleportBtn.BorderSizePixel = 0
npcTeleportBtn.Font = Enum.Font.GothamSemibold
npcTeleportBtn.Text = "TP to NPC"
npcTeleportBtn.TextColor3 = Color3.fromRGB(235, 235, 240)
npcTeleportBtn.TextSize = 13
npcTeleportBtn.Parent = content
Instance.new("UICorner", npcTeleportBtn).CornerRadius = UDim.new(0, 7)

local npcListFrame = Instance.new("ScrollingFrame")
npcListFrame.Size = UDim2.new(1, 0, 0, 100)
npcListFrame.Position = UDim2.new(0, 0, 0, 366)
npcListFrame.BackgroundColor3 = Color3.fromRGB(30, 30, 38)
npcListFrame.BorderSizePixel = 0
npcListFrame.ScrollBarThickness = 4
npcListFrame.CanvasSize = UDim2.new(0, 0, 0, 0)
npcListFrame.Visible = false
npcListFrame.Parent = content
Instance.new("UICorner", npcListFrame).CornerRadius = UDim.new(0, 7)

local listLayout = Instance.new("UIListLayout")
listLayout.SortOrder = Enum.SortOrder.LayoutOrder
listLayout.Padding = UDim.new(0, 2)
listLayout.Parent = npcListFrame

local function refreshNPCList()
	for _, btn in ipairs(npcButtons) do btn:Destroy() end
	npcButtons = {}
	npcList = {}

	for _, obj in ipairs(workspace:GetDescendants()) do
		if obj:IsA("Model") and obj:FindFirstChildOfClass("Humanoid") then
			local hum = obj:FindFirstChildOfClass("Humanoid")
			if hum and hum.Health > 0 and not Players:GetPlayerFromCharacter(obj) then
				table.insert(npcList, obj)
			end
		end
	end

	npcListFrame.CanvasSize = UDim2.new(0, 0, 0, #npcList * 34)

	for i, npc in ipairs(npcList) do
		local btn = Instance.new("TextButton")
		btn.Size = UDim2.new(1, -10, 0, 30)
		btn.Position = UDim2.new(0, 5, 0, 0)
		btn.BackgroundColor3 = Color3.fromRGB(50, 50, 60)
		btn.BorderSizePixel = 0
		btn.Font = Enum.Font.Gotham
		btn.Text = npc.Name
		btn.TextColor3 = Color3.fromRGB(240, 240, 245)
		btn.TextSize = 13
		btn.Parent = npcListFrame
		Instance.new("UICorner", btn).CornerRadius = UDim.new(0, 5)

		btn.MouseButton1Click:Connect(function()
			selectedNPC = npc
			npcDropdownBtn.Text = npc.Name
			npcListFrame.Visible = false
		end)

		table.insert(npcButtons, btn)
	end
end

npcDropdownBtn.MouseButton1Click:Connect(function()
	npcListFrame.Visible = not npcListFrame.Visible
	if npcListFrame.Visible then refreshNPCList() end
end)

local function smoothTeleport(targetPos, duration)
	if isTeleporting then return false end
	local character = player.Character
	if not character then return false end
	local root = character:FindFirstChild("HumanoidRootPart")
	if not root then return false end

	if teleportConnection then teleportConnection:Disconnect() end

	isTeleporting = true
	local startPos = root.Position
	local startTime = tick()

	teleportConnection = RunService.RenderStepped:Connect(function(dt)
		local elapsed = tick() - startTime
		local alpha = math.min(elapsed / duration, 1)
		local eased = 1 - (1 - alpha) ^ 2
		local newPos = startPos + (targetPos - startPos) * eased

		local char = player.Character
		local rt = char and char:FindFirstChild("HumanoidRootPart")
		if rt then
			rt.CFrame = CFrame.new(newPos)
			rt.AssemblyLinearVelocity = Vector3.zero
			rt.AssemblyAngularVelocity = Vector3.zero
		end

		if alpha >= 1 then
			local rt2 = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
			if rt2 then
				rt2.CFrame = CFrame.new(targetPos)
				rt2.AssemblyLinearVelocity = Vector3.zero
				rt2.AssemblyAngularVelocity = Vector3.zero
			end
			if teleportConnection then
				teleportConnection:Disconnect()
				teleportConnection = nil
			end
			isTeleporting = false
		end
	end)
	return true
end

local function getCharacter()
	local character = player.Character
	if not character then return nil, nil, nil end
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	local root = character:FindFirstChild("HumanoidRootPart")
	if not humanoid or not root or not root:IsA("BasePart") or humanoid.Health <= 0 then
		return nil, nil, nil
	end
	return character, humanoid, root
end

local function getModelRoot(instance)
	if not instance or not instance:IsA("Model") then return nil end
	local root = instance.PrimaryPart or instance:FindFirstChild("HumanoidRootPart")
	if root and root:IsA("BasePart") then return root end
	local torso = instance:FindFirstChild("UpperTorso") or instance:FindFirstChild("Torso")
	if torso and torso:IsA("BasePart") then return torso end
	return nil
end

local function getQuest()
	if not questData then return nil end
	local raw = questData.Value
	if not raw or raw == "" then return nil end
	local ok, result = pcall(HttpService.JSONDecode, HttpService, raw)
	if not ok or type(result) ~= "table" then return nil end
	return result
end

local function getQuestProgress(quest)
	if not quest then return 0, 0 end
	return tonumber(quest.progress) or 0, tonumber(quest.maxProgress) or 0
end

local function buildCastRay(targetRoot, playerRoot)
	local cam = workspace.CurrentCamera
	local eyePos = cam and cam.CFrame.Position or playerRoot.Position
	local aimPos = targetRoot.Position + Vector3.new(
		randomFloat(-0.4, 0.4), randomFloat(-0.2, 0.6), randomFloat(-0.4, 0.4))
	local dir = (aimPos - eyePos).Unit
	if dir.Magnitude ~= dir.Magnitude then dir = Vector3.new(0, 0, -1) end
	local origin = playerRoot.CFrame + Vector3.new(randomFloat(-0.05, 0.05), 0, randomFloat(-0.05, 0.05))
	return {
		origin = origin,
		direction = dir,
		raw = CFrame.lookAt(origin.Position, origin.Position + dir * 50),
	}
end

local function hasWeapon(character)
	for _, child in ipairs(character:GetChildren()) do
		if child:IsA("Tool") or child.Name == "Weapon" then return true end
	end
	return false
end

local function equipWeapon(character)
	if hasWeapon(character) then return true end
	if not remote then return false end
	if os.clock() - Settings.LastEquip >= Settings.EquipInterval then
		Settings.LastEquip = os.clock()
		pcall(function() remote:FireServer("RequestEquip") end)
	end
	return false
end

local function fireM1(castRay)
	remote:FireServer("Attack", { castRay = castRay }, ATTACK_TAG)
end

local function fireSkill(skillName, castRay)
	remote:FireServer("Attack", { isSkill = true, what = skillName, castRay = castRay })
end

if mouseRequest and mouseRequest:IsA("RemoteFunction") then
	local mouse = player:GetMouse()
	mouseRequest.OnClientInvoke = function()
		local _, _, root = getCharacter()
		if not root then return nil end
		local tr = getModelRoot(Settings.CurrentTarget)

		if Settings.Running and tr and tr.Parent then
			local cam = workspace.CurrentCamera
			local eyePos = cam and cam.CFrame.Position or root.Position
			local dir = (tr.Position - eyePos).Unit
			if dir.Magnitude ~= dir.Magnitude then dir = Vector3.new(0, 0, -1) end
			return {
				origin = root.CFrame,
				direction = dir,
				raw = CFrame.lookAt(root.Position, tr.Position),
			}
		end

		return {
			origin = root.CFrame,
			direction = mouse.UnitRay.Direction,
			raw = mouse.Hit,
		}
	end
end

local function attackTarget(targetRoot, character, playerRoot)
	if not targetRoot or not targetRoot.Parent then return end

	local dist = (targetRoot.Position - playerRoot.Position).Magnitude
	if dist > Settings.MaxEngageDist then return end

	local now = os.clock()
	local castRay = buildCastRay(targetRoot, playerRoot)

	if Settings.UseSkills then
		for _, sd in ipairs(Settings.SkillDefs) do
			if sd.enabled and now - sd.last >= sd.cd then
				sd.last = now + randomFloat(0.1, 0.4)
				Settings.LastAttack = now + 0.35
				pcall(function() fireSkill(sd.what, castRay) end)
				return
			end
		end
	end

	local anySkillPending = false
	if Settings.UseSkills then
		for _, sd in ipairs(Settings.SkillDefs) do
			if sd.enabled and now - sd.last >= sd.cd then
				anySkillPending = true
			end
		end
	end

	local minInt, maxInt = Settings.AttackIntervalMin, Settings.AttackIntervalMax
	if Settings.UseSkills and not anySkillPending then
		minInt, maxInt = Settings.SpamIntervalMin, Settings.SpamIntervalMax
	end
	if now - Settings.LastAttack < randomFloat(minInt, maxInt) then
		return
	end
	Settings.LastAttack = now
	pcall(function() fireM1(castRay) end)
end

if remote then
	remote.OnClientEvent:Connect(function(action, payload)
		if action ~= "HitboxDetection" or not Settings.Running or not Settings.ForceHitFallback then
			return
		end
		local desc = payload and payload._desc
		if not (desc and desc.GUID and desc.passed) then return end

		local _, _, root = getCharacter()
		local target = Settings.CurrentTarget
		local tr = getModelRoot(target)
		if not (root and tr) or not isAliveNPC(target) then return end

		local boxSize = tonumber(desc.passed.hitboxSize) or 16
		local engageDist = boxSize * 1.25 + Settings.MaxEngageDist * 0.5 + 6
		if (tr.Position - root.Position).Magnitude > engageDist then return end

		task.wait(0.32)
		if not Settings.Running then return end
		pcall(function()
			remote:FireServer("userHit", {
				Who = target,
				GUID = desc.GUID,
			})
		end)
	end)
end

local floatTime = 0
local driftOffset = Vector3.zero
local driftTimer = 0

RunService.RenderStepped:Connect(function(dt)
	if isTeleporting then return end
	if not Settings.Running then return end
	local _, humanoid, root = getCharacter()
	if not humanoid or not root then return end

	local targetRoot = Settings.CurrentRoot
	if not targetRoot or not targetRoot.Parent then return end

	floatTime += dt
	driftTimer += dt
	if driftTimer > randomFloat(3, 6) then
		driftTimer = 0
		driftOffset = Vector3.new(randomFloat(-0.3, 0.3), 0, randomFloat(-0.3, 0.3))
	end

	local vertical = Settings.Position == "Above" and Settings.Height or -Settings.Height
	local bob = math.sin(floatTime * 0.7) * 0.5
	local desiredPos = targetRoot.Position + Vector3.new(driftOffset.X, vertical + bob, driftOffset.Z)

	root.Anchored = false
	root.CFrame = CFrame.lookAt(desiredPos, desiredPos + (targetRoot.Position - desiredPos).Unit)
	root.AssemblyLinearVelocity = Vector3.zero
	root.AssemblyAngularVelocity = Vector3.zero
	humanoid.AutoRotate = false
end)

local function stopFly()
	Settings.CurrentTarget = nil
	Settings.CurrentRoot = nil
	local _, humanoid, root = getCharacter()
	if humanoid then humanoid.AutoRotate = true end
	if root then
		root.AssemblyLinearVelocity = Vector3.zero
		root.AssemblyAngularVelocity = Vector3.zero
	end
end

player.CharacterAdded:Connect(function()
	Settings.CurrentTarget = nil
	Settings.CurrentRoot = nil
	if teleportConnection then
		teleportConnection:Disconnect()
		teleportConnection = nil
	end
	isTeleporting = false
end)

local function interactQuestNPC()
	local quest = getQuest()
	local npcName = quest and quest.questName
	local npc = nil

	if npcName and dialoguesFolder then
		npc = dialoguesFolder:FindFirstChild(npcName)
	end
	if not npc and dialoguesFolder then
		local _, _, root = getCharacter()
		if not root then return false end
		local bestD = math.huge
		for _, m in ipairs(dialoguesFolder:GetChildren()) do
			local p = getModelRoot(m)
			if p then
				local d = (p.Position - root.Position).Magnitude
				if d < bestD then bestD, npc = d, m end
			end
		end
	end
	if not npc then return false end

	local _, _, root = getCharacter()
	local npcRoot = getModelRoot(npc)
	if not (root and npcRoot) then return false end

	local targetPos = npcRoot.CFrame * CFrame.new(0, 0, 3)
	local success = smoothTeleport(targetPos.Position, 2.0)
	if not success then
		root.CFrame = targetPos
	end

	while isTeleporting do task.wait(0.05) end

	local pe = npc:FindFirstChild("ProximityEvent")
	if not pe then return false end

	for i = 1, Settings.InteractRetries do
		if not npc.Parent then break end
		pcall(function()
			if pe:IsA("RemoteEvent") then
				pe:FireServer()
			elseif pe:IsA("RemoteFunction") then
				pe:InvokeServer()
			end
		end)
		task.wait(Settings.InteractRetryDelay)
	end
	return true
end

local function tryRepeatQuest()
	pcall(function() remote:FireServer("RepeatQuestChoice", "repeat") end)
end

task.spawn(function()
	while gui.Parent do
		task.wait(0.4)
		if Settings.Running and Settings.AutoRepeatEnabled then
			local ok, hud = pcall(function()
				return playerGui.HUD.RepeatQuest
			end)
			if ok and hud and hud.Visible and hud:FindFirstChild("repeat") then
				tryRepeatQuest()
				hud.Visible = false
			end
		end
	end
end)

local function doQuestTurnInCycle()
	interactQuestNPC()
	tryRepeatQuest()
	Settings.QuestBusyUntil = os.clock() + 4
end

local lastProgressTick = os.clock()
local lastProgSeen     = -1

if questData then
	questData.Changed:Connect(function()
		local quest = getQuest()
		if not quest or not quest.questName then return end
		local prog, maxp = getQuestProgress(quest)
		if quest.questName ~= Settings.LastQuestName or prog ~= Settings.LastQuestProgress then
			Settings.LastQuestName = quest.questName
			Settings.LastQuestProgress = prog
			lastProgSeen = prog
			lastProgressTick = os.clock()
		end
	end)
end

local function normalizeName(name)
	return tostring(name or ""):lower():gsub("[^%w]", "")
end

local function isAliveNPC(inst)
	if not inst or not inst:IsA("Model") then return false end
	local h = inst:FindFirstChildOfClass("Humanoid")
	if not h or h.Health <= 0 then return false end
	return getModelRoot(inst) ~= nil
end

local function getLiveNPCs()
	local out = {}
	for _, obj in ipairs(aliveFolder:GetChildren()) do
		if isAliveNPC(obj) and not Players:GetPlayerFromCharacter(obj) then
			table.insert(out, obj)
		end
	end
	return out
end

local function getQuestMarkPos(quest)
	local tName = type(quest.targetNPC) == "string" and quest.targetNPC or ""
	if tName == "" or not marksFolder then return nil end
	local mk = marksFolder:FindFirstChild(tName)
	local part = mk and (mk:IsA("BasePart") and mk or mk:FindFirstChildWhichIsA("BasePart", true))
	return part and part.Position or nil
end

local function findBestTarget(quest, playerRoot)
	local npcs = getLiveNPCs()
	if #npcs == 0 then return nil end

	local wanted = normalizeName(quest.targetNPC)

	local named = {}
	for _, npc in ipairs(npcs) do
		local base = normalizeName(npc.Name):gsub("%d+$", "")
		if wanted ~= "" and base == wanted then
			table.insert(named, npc)
		end
	end

	local refPos, candidates
	if #named > 0 then
		candidates = named
		refPos = playerRoot.Position
	else
		local markPos = getQuestMarkPos(quest)
		if markPos then
			candidates = npcs
			refPos = markPos
		else
			return nil
		end
	end

	local best, bestDist = nil, math.huge
	for _, npc in ipairs(candidates) do
		local root = getModelRoot(npc)
		if root then
			local dist = (root.Position - refPos).Magnitude
			if dist <= Settings.MarkRadius and dist < bestDist then
				bestDist, best = dist, npc
			end
		end
	end
	return best
end

local farmStep
farmStep = function()
	if not Settings.Running then return end
	if os.clock() < Settings.QuestBusyUntil then return end

	local character, humanoid, playerRoot = getCharacter()
	if not character or not humanoid or not playerRoot then
		stopFly()
		return
	end

	local quest = getQuest()
	if not quest or not quest.questName then
		stopFly()
		return
	end

	local prog, maxp = getQuestProgress(quest)

	if maxp > 0 and prog < maxp then
		if prog ~= lastProgSeen then
			lastProgSeen = prog
			lastProgressTick = os.clock()
		elseif os.clock() - lastProgressTick > 12 then
			stopFly()
			lastProgressTick = os.clock()
			task.delay(0.6, function()
				pcall(function() remote:FireServer("RequestEquip") end)
			end)
			Settings.QuestBusyUntil = os.clock() + 1.2
			return
		end
	end

	if maxp > 0 and prog >= maxp then
		if Settings.AutoRepeatEnabled then
			doQuestTurnInCycle()
		else
			stopFly()
		end
		return
	end
	if maxp <= 0 then
		stopFly()
		return
	end

	local target = Settings.CurrentTarget
	if target then
		if not target.Parent or not isAliveNPC(target) then
			target = nil
			Settings.CurrentRoot = nil
		else
			Settings.CurrentRoot = getModelRoot(target)
		end
	end
	if not target then
		target = findBestTarget(quest, playerRoot)
		if not target then
			stopFly()
			return
		end
		Settings.CurrentTarget = target
		Settings.CurrentRoot = getModelRoot(target)
	end

	if not equipWeapon(character) then
		return
	end

	local targetRoot = Settings.CurrentRoot
	if targetRoot and targetRoot.Parent and isAliveNPC(target) then
		attackTarget(targetRoot, character, playerRoot)
	else
		Settings.CurrentTarget = nil
		Settings.CurrentRoot = nil
	end
end

local function updatePositionButtons()
	if Settings.Position == "Above" then
		aboveButton.BackgroundColor3 = Color3.fromRGB(63, 124, 235)
		downButton.BackgroundColor3 = Color3.fromRGB(36, 36, 44)
	else
		aboveButton.BackgroundColor3 = Color3.fromRGB(36, 36, 44)
		downButton.BackgroundColor3 = Color3.fromRGB(63, 124, 235)
	end
end

local function refreshSkillButtons()
	local anyOn, allOn = false, true
	for i, sd in ipairs(Settings.SkillDefs) do
		skillToggleButtons[i].BackgroundColor3 = sd.enabled
			and Color3.fromRGB(63, 124, 235) or Color3.fromRGB(36, 36, 44)
		if sd.enabled then anyOn = true else allOn = false end
	end
	skillsButton.Text = "Skills: " .. (allOn and "ALL ON" or (anyOn and "SOME" or "ALL OFF"))
end

toggleButton.Activated:Connect(function()
	if Settings.Running then
		Settings.Running = false
		stopFly()
		toggleButton.Text = "Farming: OFF"
		toggleButton.BackgroundColor3 = Color3.fromRGB(36, 36, 44)
		if runTimerConnection then
			runTimerConnection:Disconnect()
			runTimerConnection = nil
		end
	else
		startTime = os.clock()
		if runTimerConnection then runTimerConnection:Disconnect() end
		runTimerConnection = RunService.Heartbeat:Connect(function()
			local elapsed = os.clock() - startTime
			local hours = math.floor(elapsed / 3600)
			local minutes = math.floor((elapsed % 3600) / 60)
			local seconds = math.floor(elapsed % 60)
			timerLabel.Text = string.format("Time: %02d:%02d:%02d", hours, minutes, seconds)
		end)
		Settings.Running = true
		stopFly()
		toggleButton.Text = "Farming: ON"
		toggleButton.BackgroundColor3 = Color3.fromRGB(35, 100, 62)
	end
end)

autoToggleButton.Activated:Connect(function()
	Settings.AutoRepeatEnabled = not Settings.AutoRepeatEnabled
	autoToggleButton.Text = "Auto Repeat: " .. (Settings.AutoRepeatEnabled and "ON" or "OFF")
	autoToggleButton.BackgroundColor3 = Settings.AutoRepeatEnabled and Color3.fromRGB(63, 124, 235) or Color3.fromRGB(36, 36, 44)
end)

skillsButton.Activated:Connect(function()
	local turnOn = false
	for _, sd in ipairs(Settings.SkillDefs) do
		if sd.enabled then turnOn = true end
	end
	turnOn = not turnOn
	for _, sd in ipairs(Settings.SkillDefs) do
		sd.enabled = turnOn
	end
	refreshSkillButtons()
end)

for i, sd in ipairs(Settings.SkillDefs) do
	skillToggleButtons[i].Activated:Connect(function()
		sd.enabled = not sd.enabled
		refreshSkillButtons()
	end)
end
refreshSkillButtons()

aboveButton.Activated:Connect(function()
	Settings.Position = "Above"
	updatePositionButtons()
end)
downButton.Activated:Connect(function()
	Settings.Position = "Down"
	updatePositionButtons()
end)

heightBox.FocusLost:Connect(function()
	local num = tonumber(tostring(heightBox.Text):match("[-%d%.]+"))
	if num then
		Settings.Height = math.clamp(num, Settings.HeightMin, 80)
		heightBox.Text = "Height: " .. tostring(Settings.Height)
	else
		heightBox.Text = "Height: " .. tostring(Settings.Height)
	end
end)

npcTeleportBtn.Activated:Connect(function()
	if not selectedNPC then return end
	local rootPart = selectedNPC.PrimaryPart or selectedNPC:FindFirstChild("HumanoidRootPart")
	if not rootPart or not rootPart:IsA("BasePart") then return end
	local targetPos = rootPart.Position + Vector3.new(0, 3, 0)
	smoothTeleport(targetPos, 2.0)
end)

local minimized = false
minimize.Activated:Connect(function()
	minimized = not minimized
	content.Visible = not minimized
	main.Size = minimized and UDim2.new(0, 350, 0, 44) or UDim2.new(0, 350, 0, 490)
	minimize.Text = minimized and "+" or "—"
end)

UserInputService.InputBegan:Connect(function(input, processed)
	if processed then return end
	if input.KeyCode == Enum.KeyCode.K then
		main.Visible = not main.Visible
	elseif input.KeyCode == Enum.KeyCode.Up then
		Settings.Height = math.clamp(Settings.Height + 1, Settings.HeightMin, 80)
		heightBox.Text = "Height: " .. Settings.Height
	elseif input.KeyCode == Enum.KeyCode.Down then
		Settings.Height = math.clamp(Settings.Height - 1, Settings.HeightMin, 80)
		heightBox.Text = "Height: " .. Settings.Height
	elseif input.KeyCode == Enum.KeyCode.PageUp then
		Settings.Height = math.clamp(Settings.Height + 5, Settings.HeightMin, 80)
		heightBox.Text = "Height: " .. Settings.Height
	elseif input.KeyCode == Enum.KeyCode.PageDown then
		Settings.Height = math.clamp(Settings.Height - 5, Settings.HeightMin, 80)
		heightBox.Text = "Height: " .. Settings.Height
	end
end)

do
	local dragging, dragStart, startPos = false, nil, nil
	titleBar.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
			dragging = true
			dragStart = input.Position
			startPos = main.Position
			input.Changed:Connect(function()
				if input.UserInputState == Enum.UserInputState.End then dragging = false end
			end)
		end
	end)
	UserInputService.InputChanged:Connect(function(input)
		if not dragging then return end
		if input.UserInputType ~= Enum.UserInputType.MouseMovement and input.UserInputType ~= Enum.UserInputType.Touch then return end
		if dragStart and startPos then
			local delta = input.Position - dragStart
			main.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + delta.X, startPos.Y.Scale, startPos.Y.Offset + delta.Y)
		end
	end)
end

task.spawn(function()
	while gui.Parent do
		task.wait(60)
		if Settings.Running then
			pcall(function()
				remote:FireServer("RequestEquip")
			end)
		end
	end
end)

updatePositionButtons()

task.spawn(function()
	while gui.Parent do
		if Settings.Running then
			local ok, err = pcall(farmStep)
			if not ok then
				stopFly()
			end
		end
		task.wait(Settings.SearchInterval)
	end
end)
Script worked? 🚀 Boost it to #1 so others find it too.

Comments (1)

Log in to add a comment.

Nexusri00

Nexusri00Author

1 month ago

whats my life purpose