Загрузка данных
-- ENGINEER FLOATING SENTRY TEST V1
-- Один ограниченный запрос.
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")
local Workspace = game:GetService("Workspace")
local LocalPlayer = Players.LocalPlayer
local Character = LocalPlayer.Character
local Root = Character and Character:FindFirstChild("HumanoidRootPart")
local Humanoid = Character and Character:FindFirstChildOfClass("Humanoid")
-- Проверка на приватный сервер удалена — скрипт работает на любом сервере
assert(Character and Root and Humanoid, "Character is not ready")
assert(Humanoid.Health > 0, "Character is dead")
local gloveName = tostring(LocalPlayer:GetAttribute("Glove"))
local engineerTool =
Character:FindFirstChild("Engineer")
or LocalPlayer.Backpack:FindFirstChild("Engineer")
assert(
gloveName == "Engineer" or engineerTool,
"Equip Engineer first; current glove: " .. gloveName
)
local arenaValue = Character:FindFirstChild("isInArena")
assert(
arenaValue and arenaValue.Value == true,
"Enter the arena first"
)
local SentryRemote = ReplicatedStorage:FindFirstChild("Sentry")
assert(
SentryRemote and SentryRemote:IsA("RemoteEvent"),
"ReplicatedStorage.Sentry missing"
)
local report = {}
local function log(...)
local values = {...}
for index = 1, #values do
values[index] = tostring(values[index])
end
local line = table.concat(values, " ")
table.insert(report, line)
print(line)
end
local function copyReport()
local output = table.concat(report, "\n")
local clipboard = setclipboard or toclipboard
if type(clipboard) == "function" then
pcall(clipboard, output)
end
end
local function isTurret(object)
if not object or not object:IsA("Model") then
return false
end
return object.Name == "Turret"
or object:HasTag("Sentry")
or object:FindFirstChild("TurretStandBase", true) ~= nil
end
local function getAllowedGrass()
local result = {}
local Arena = Workspace:FindFirstChild("Arena")
assert(Arena, "Workspace.Arena missing")
for _, islandName in ipairs({
"main island",
"island1",
"island2",
"island3",
"island4"
}) do
local island = Arena:FindFirstChild(islandName)
local grass = island and island:FindFirstChild("Grass")
if grass and grass:IsA("BasePart") then
table.insert(result, grass)
end
end
local defaultIsland = Arena:FindFirstChild("default island")
if defaultIsland then
for _, object in ipairs(defaultIsland:GetChildren()) do
if object:IsA("BasePart")
and object.Material == Enum.Material.Grass then
table.insert(result, object)
end
end
end
return result
end
local function findGround()
local allowedGrass = getAllowedGrass()
assert(#allowedGrass > 0, "Allowed grass list is empty")
local forwardPosition =
Root.Position + Root.CFrame.LookVector * 6
local origin = Vector3.new(
forwardPosition.X,
Root.Position.Y + 60,
forwardPosition.Z
)
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Include
params.FilterDescendantsInstances = allowedGrass
params.IgnoreWater = true
return Workspace:Raycast(
origin,
Vector3.new(0, -150, 0),
params
)
end
log("=== ENGINEER FLOATING SENTRY TEST V1 ===")
log("Private server:", true) -- показываем true, так как защита снята
log("Player:", LocalPlayer.Name)
log("Glove:", gloveName)
log("Waiting 14 seconds to clear Engineer cooldown...")
log("Do not move and do not press E")
task.wait(14)
Character = LocalPlayer.Character
Root = Character and Character:FindFirstChild("HumanoidRootPart")
Humanoid = Character and Character:FindFirstChildOfClass("Humanoid")
assert(Character and Root and Humanoid and Humanoid.Health > 0,
"Character changed during cooldown wait")
local groundHit = findGround()
assert(
groundHit,
"No allowed grass ahead; face toward clear arena grass"
)
local FLOAT_HEIGHT = 12
local targetPosition =
groundHit.Position + Vector3.new(0, FLOAT_HEIGHT, 0)
-- Обычный клиент отправляет identity rotation.
-- Здесь меняется только высота, чтобы результат был однозначным.
local targetCFrame = CFrame.new(targetPosition)
local playerDistance = (Root.Position - targetPosition).Magnitude
log("Ground:", groundHit.Instance:GetFullName())
log("Ground position:", groundHit.Position)
log("Requested position:", targetPosition)
log("Requested grass gap:", FLOAT_HEIGHT)
log("Player distance:", string.format("%.3f", playerDistance))
assert(
playerDistance <= 15,
"Target unexpectedly farther than 15 studs"
)
local existing = {}
for _, object in ipairs(Workspace:GetChildren()) do
if isTurret(object) then
existing[object] = true
end
end
for _, object in ipairs(CollectionService:GetTagged("Sentry")) do
existing[object] = true
end
local newTurret
local addedConnection = Workspace.ChildAdded:Connect(function(object)
task.defer(function()
if not existing[object] and isTurret(object) then
newTurret = object
end
end)
end)
local sent, sendError = pcall(function()
SentryRemote:FireServer(targetCFrame)
end)
log("ONE REQUEST SENT:", sent)
log("SEND ERROR:", sendError)
local deadline = os.clock() + 6
repeat
task.wait(0.1)
for _, object in ipairs(CollectionService:GetTagged("Sentry")) do
if not existing[object] then
local ownerId = object:GetAttribute("OwnerId")
if ownerId == nil or ownerId == LocalPlayer.UserId then
newTurret = object
break
end
end
end
until newTurret or os.clock() >= deadline
addedConnection:Disconnect()
if not newTurret or not newTurret.Parent then
log("SERVER TURRET CREATED: false")
log("RESULT: REJECTED — SERVER BLOCKED FLOATING CFRAME")
copyReport()
return
end
task.wait(1)
local actualCFrame = newTurret:GetPivot()
local positionError =
(actualCFrame.Position - targetPosition).Magnitude
local supportParams = RaycastParams.new()
supportParams.FilterType = Enum.RaycastFilterType.Exclude
supportParams.FilterDescendantsInstances = {
Character,
newTurret
}
supportParams.IgnoreWater = true
local supportHit = Workspace:Raycast(
actualCFrame.Position + Vector3.new(0, 1, 0),
Vector3.new(0, -50, 0),
supportParams
)
local actualGap = supportHit
and actualCFrame.Position.Y - supportHit.Position.Y
or math.huge
log("SERVER TURRET CREATED: true")
log("Turret:", newTurret:GetFullName())
log("Requested pivot:", targetPosition)
log("Actual pivot:", actualCFrame.Position)
log("Position error:", string.format("%.3f", positionError))
log(
"Support:",
supportHit and supportHit.Instance:GetFullName() or "NONE"
)
log(
"Actual support gap:",
actualGap == math.huge
and "INF"
or string.format("%.3f", actualGap)
)
if positionError <= 4 and actualGap >= 8 then
log("RESULT: OP PASS")
log("SERVER ACCEPTED A FLOATING ENGINEER TURRET")
log("Placement validation only detected grass below")
elseif positionError <= 4 then
log("RESULT: PARTIAL — CREATED AT REQUEST, BUT SUPPORT IS CLOSE")
else
log("RESULT: REJECTED — SERVER SNAPPED/RECOMPUTED POSITION")
end
copyReport()