-- *EXTREMELY* EXPERIMENTAL. THIS CODE SUCKS. IM SORRY.
local player = owner :: Player
local char = player.Character
if char then
char:Destroy()
end
script.Name = player.Name .. "'s FakeChar test"
local HIP_HEIGHT = 3
local JUMP_POWER = 50
local WALK_SPEED = 16
local model = Instance.new("WorldModel")
model.Name = player.Name
model.Parent = script
local hrp = Instance.new("Part")
hrp.Name = "HumanoidRootPart"
hrp.Size = Vector3.new(2, 2, 1)
hrp.Anchored = false
hrp.CanCollide = true
hrp.Parent = model
hrp:SetNetworkOwner(player)
local vel = Vector3.zero
local key_movement = {
["W"] = false,
["A"] = false,
["S"] = false,
["D"] = false;
}
local params = RaycastParams.new()
params.RespectCanCollide = true
local ignore_updates = false -- skips over a frame if you want to change, for example, upwards velocity
local colliding_enabled = true
local receive_keys = Instance.new("RemoteEvent")
receive_keys.Name = "ReceiveKeys"
receive_keys.Parent = script
NLS([[
script.Name = "Keys"
local main_script = workspace:FindFirstChild(owner.Name .. "'s FakeChar test")
local receive_keys = main_script.ReceiveKeys
local model = main_script:FindFirstChild(owner.Name)
local hrp = model.HumanoidRootPart
local uis = game:GetService("UserInputService")
uis.InputBegan:Connect(function(key, typing)
if typing then
return
end
receive_keys:FireServer(key.KeyCode)
end)
uis.InputEnded:Connect(function(key)
receive_keys:FireServer(key.KeyCode, true)
end)
]])
receive_keys.OnServerEvent:Connect(function(remote_player, key, ending)
if not ending then
ending = false
end
if remote_player ~= player then
return
end
if typeof(key) ~= "EnumItem" then
return
end
local key_name = key.Name
if key_name == "Space" then
if ending then
return
end
local hrp_ray = workspace:Raycast(hrp.Position, Vector3.yAxis * -(HIP_HEIGHT+0.05))
if hrp_ray then
ignore_updates = true
vel = Vector3.yAxis * JUMP_POWER / 50
end
elseif key.Name == "F" then
if ending then
return
end
colliding_enabled = not colliding_enabled
end
for name, value in key_movement do
if name == key_name then
key_movement[name] = not ending
end
end
end)
local function calculate_rays(dt)
if ignore_updates then
ignore_updates = false
return vel
end
local hrp_ray = workspace:Raycast(hrp.Position, Vector3.yAxis * -(HIP_HEIGHT+0.05))
if hrp_ray then
vel = Vector3.yAxis * ((HIP_HEIGHT-0.05) - hrp_ray.Distance)
else
vel -= Vector3.yAxis * (workspace.Gravity/50) * dt
end
return vel
end
local updated_cf = CFrame.new()
local receive_camera = Instance.new("UnreliableRemoteEvent")
receive_camera.Name = "ReceiveCamera"
receive_camera.Parent = script
NLS([[
script.Name = "Camera"
local main_script = workspace:FindFirstChild(owner.Name .. "'s FakeChar test")
local receive_camera = main_script.ReceiveCamera
local model = main_script:FindFirstChild(owner.Name)
local hrp = model.HumanoidRootPart
local camera = workspace.CurrentCamera
camera.CameraSubject = hrp
local run_service = game:GetService("RunService")
run_service:BindToRenderStep("Movement", Enum.RenderPriority.Camera.Value, function(dt)
receive_camera:FireServer(camera.CFrame)
end)
]])
local auto_rotate = true
receive_camera.OnServerEvent:Connect(function(remote_player, new_cf)
if remote_player ~= player then
return
end
if not auto_rotate then
return
end
updated_cf = new_cf
end)
local last_safe_cf = hrp.CFrame
local function move()
if not colliding_enabled then
return
end
local dir = (hrp.Position - last_safe_cf.Position)
local ray = workspace:Raycast(hrp.Position, dir.Unit, params)
if ray then
vel = Vector3.zero
hrp.CFrame = last_safe_cf
return
end
end
local function calculate_movement(dt)
-- main movement
local addition = Vector3.zero
for name, value in key_movement do
if value then
if name == "W" then
addition += hrp.CFrame.LookVector * WALK_SPEED
elseif name == "S" then
addition += hrp.CFrame.LookVector * -WALK_SPEED
elseif name == "A" then
addition += hrp.CFrame.RightVector * -WALK_SPEED
elseif name == "D" then
addition += hrp.CFrame.RightVector * WALK_SPEED
end
end
end
local new_cf = (updated_cf.LookVector * Vector3.new(1, 0, 1))
local normalized_cf = (new_cf + addition).Unit
local offset = normalized_cf * dt * WALK_SPEED
if addition == Vector3.zero then
return Vector3.zero
end
-- collisions
move()
last_safe_cf = hrp.CFrame
return offset
end
local runservice = game:GetService("RunService")
runservice.Heartbeat:Connect(function(dt)
local hrp_offset = Vector3.zero
hrp_offset += calculate_rays(dt)
hrp_offset += calculate_movement(dt)
local new_position = hrp.Position + hrp_offset
hrp.CFrame = CFrame.new(new_position, new_position + updated_cf.LookVector * Vector3.new(1, 0, 1))
end)