Flying script seems to be referencing the same HumanoidRootPart even after the player dies

Hi there, I have this flying script (which was originally written by @EgoMoose in 2018, and then later modified by @FirstVertex in 2021 to add mobile support) and whenever a player dies with it activated it stops working. Using some prints it seems like the script is putting the BodyVelocity and the BodyGyro into the players old HumanoidRootPart and I’m not sure how to stop it from doing it. I’ve tried setting up an event that triggers the setFlying() function whenever the player dies and then redefines the hrp variable, but all redefining the variable does is set it to nil. Below is the flying script and under it is the event I was talking about. Any help is appreciated :slight_smile:

I should note that I modified the script to run when a Gui button was pressed. The “Speed” variable used to just be the players walkspeed

local camera = game.Workspace.CurrentCamera;
local player = game.Players.LocalPlayer;
repeat task.wait() until player.Character
local character = player.Character
local hrp = character.HumanoidRootPart
local humanoid = character.Humanoid
local Button = script.Parent
local Speed = script.Parent.Parent.Parent.FlyPopUp.MainBackground.Confirm.Confirm.Speed

while (not character.Parent) do character.AncestryChanged:Wait(); end

local bodyGyro = Instance.new("BodyGyro");
bodyGyro.maxTorque = Vector3.new(1, 1, 1)*10^6;
bodyGyro.P = 10^6;

local bodyVel = Instance.new("BodyVelocity");
bodyVel.maxForce = Vector3.new(1, 1, 1)*10^6;
bodyVel.P = 10^4;

local isFlying = false;
local movement = {forward = 0, backward = 0, right = 0, left = 0};

-- functions
local function setFlying(flying)
	isFlying = flying;
	bodyGyro.Parent = isFlying and hrp or nil;
	bodyVel.Parent = isFlying and hrp or nil;
	bodyVel.Velocity = Vector3.new();
	
	if (isFlying) then
		bodyGyro.CFrame =  hrp.CFrame;
	end
end

Button.Activated:Connect(function()
	if (not humanoid or humanoid:GetState() == Enum.HumanoidStateType.Dead) then
		return;
	end
	setFlying(not isFlying)
end)

local function onUpdate(dt)
	if (isFlying) then
		local cf = camera.CFrame;
		local direction = cf.rightVector*(movement.right - movement.left) + cf.lookVector*(movement.forward - movement.backward);
		
		if (direction:Dot(direction) > 0) then
			direction = direction.unit;
		end

		bodyGyro.CFrame = cf;
		bodyVel.Velocity = direction * Speed.Value * 3;
	end
end

local function modifyMovement(newMovement)
	movement = newMovement or movement
	if (isFlying) then
		local isMoving = movement.right + movement.left + movement.forward + movement.backward > 0;
	end
	-- print('movement modified', movement)
end

local function movementBind(actionName, inputState, inputObject)
	if (inputState == Enum.UserInputState.Begin) then
		movement[actionName] = 1;

		modifyMovement()
	elseif (inputState == Enum.UserInputState.End) then
		movement[actionName] = 0;

		modifyMovement()
	end
	
	return Enum.ContextActionResult.Pass;
end

-- UPDATE 8/29/2021
-- THIS PART WAS REMIXED BY @FirstVertex
-- NOW FULLY SUPPORTING MOBILE CONTROLS!
-- See the WormHole for example flight: https://www.roblox.com/games/6665206183

-- STRATEGY: since CAS won't fire movement on mobile while flying, listen for touchmoves
-- on the thumbstick and inquire what's the current movement status from the current
-- controller who's still tracking the movement although it's not broadcasted by CAS

local CAS = game:GetService("ContextActionService");
local UIS = game:GetService("UserInputService");

-- these don't work on mobile while flying
CAS:BindAction("forward", movementBind, false, Enum.PlayerActions.CharacterForward);
CAS:BindAction("backward", movementBind, false, Enum.PlayerActions.CharacterBackward);
CAS:BindAction("left", movementBind, false, Enum.PlayerActions.CharacterLeft);
CAS:BindAction("right", movementBind, false, Enum.PlayerActions.CharacterRight);

-- recursively seek the Control Module and the Touch Control frame
local controller = require(player:FindFirstChild("ControlModule", true))
local touchFrame = player:FindFirstChild('TouchControlFrame', true)

if controller and touchFrame then
	local isMovingThumbstick = false
	-- tolerance for ignoring small values
	local deadZone = 0.15
	-- a factor used to normalize inputs between deadZone and 1 to 0-1
	local deadZoneNormalized = 1 - deadZone

	-- determine if the position is within the current thumbstick's bounds
	local function isTouchOnThumbstick(position)
		if not touchFrame then return false end
		-- "classic" thumbstick
		local classicFrame = touchFrame:FindFirstChild('ThumbstickFrame');
		-- "dynamic" thumbstick
		local dynamicFrame = touchFrame:FindFirstChild('DynamicThumbstickFrame');

		local stickFrame = (classicFrame and classicFrame.Visible) and classicFrame or dynamicFrame
		if (stickFrame) then
			local stickPos = stickFrame.AbsolutePosition
			local stickSize = stickFrame.AbsoluteSize
			-- is the given position inside the given box
			return position.X >= stickPos.X and
				position.X <= (stickPos.X + stickSize.X) and
				position.Y >= stickPos.Y and
				position.Y <= (stickPos.Y + stickSize.Y)
		end
		return false
	end

	UIS.TouchStarted:connect(function(touch, gameProcessedEvent)
		isMovingThumbstick = isTouchOnThumbstick(touch.Position)
	end)

	UIS.TouchEnded:connect(function(touch, gameProcessedEvent)
		if not isMovingThumbstick then return end
		isMovingThumbstick = false
		modifyMovement({forward = 0, backward = 0, right = 0, left = 0});
	end)

	UIS.TouchMoved:connect(function(touch, gameProcessedEvent)
		if not isMovingThumbstick then return end
		-- although CAS is not firing Enum.PlayerActions.Character* the controller is still tracking the movement, so just ask
		local mv = controller:GetMoveVector();
		local leftRight = mv.X;
		local foreBack = mv.Z;
		
		-- change the range from [0.15-1] to [0-1] if it is outside the deadzone
		movement.left = leftRight < -deadZone and -(leftRight-deadZone)/deadZoneNormalized or 0
		movement.right = leftRight > deadZone and (leftRight-deadZone)/deadZoneNormalized or 0

		movement.forward = foreBack < -deadZone and -(foreBack-deadZone)/deadZoneNormalized or 0
		movement.backward = foreBack > deadZone and (foreBack-deadZone)/deadZoneNormalized or 0

		modifyMovement()
	end)
end

game:GetService("RunService").RenderStepped:Connect(onUpdate)

humanoid.Died:Connect(function()
	setFlying(not isFlying)
	player.CharacterAdded:Connect(function(NewChar)
		hrp = NewChar:FindFirstChild("HumanoidRootPart")
		print("hrp redefined", hrp)
	end)
end)
-- ^This was added right after the setFlying() was defined
1 Like