Quick actions

cmd+k|ctrl+k

Navigation

Languages

fakechar template

Snippet info

Language

Lua

Visibility

public

Author

likeableemmec

Created

2025-01-06T18:16:32.525497Z

Updated

2025-01-06T18:16:32.525497Z

-- *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)
INFO