Your First Script
Resolving the DataModel, walking to a player, and reading and writing something real.
Every script starts the same way: get the DataModel address, then walk down from it. Nothing is global and nothing is cached for you.
local dm = get_datamodel()
print("datamodel at", dm)
local players = find_first_child(dm, "Players")
local workspace_ = find_first_child(dm, "Workspace")
print(get_classname(players)) --> "Players"
print(get_instance_path(players)) --> "Players"get_children returns a table of addresses. Everything else — names, classes, parents — is a call rather than a field.
local dm = get_datamodel()
local players = find_first_child(dm, "Players")
for _, player in ipairs(get_children(players)) do
print(read_name(player), get_classname(player))
local character = find_first_child(player, "Character")
if character ~= 0 then
local root = find_first_child(character, "HumanoidRootPart")
if root ~= 0 then
print(" at", read_BasePart_Position and "..." or root)
end
end
endZero means nothing found
The explorer functions return 0, not nil, when they find nothing. Check ~= 0 before you use an address — passing 0 to a read accessor is how you get a garbage value instead of an error.
Two ways to get at a value. The offset accessors are the readable option and know the type for you; the raw memory functions are there when you have an address and know what is at it.
local part = find_instance_by_path("Workspace.Baseplate")
-- Named accessor: knows the offset and the type.
print(read_BasePart_Transparency(part))
write_BasePart_Transparency(part, 0.5)
-- Raw: you supply the address and pick the width.
local address = part + 0x100
print(read_float(address))
write_float(address, 1.0)Raw writes are not checked
A write to the wrong address does not error — it corrupts whatever was there. Read the value back first and satisfy yourself it looks like what you expect before you write.
There are no events. Anything continuous is a loop with a wait, and task.spawn puts it on its own thread so it does not block the rest of your script.
task.spawn(function()
while true do
local dm = get_datamodel()
if dm ~= 0 then
local players = find_first_child(dm, "Players")
for _, player in ipairs(get_children(players)) do
-- per-player work
end
end
wait(0.1)
end
end)Resolve from get_datamodel() inside the loop rather than above it. That way a rejoin picks up the new tree instead of leaving the loop reading a dead one.