Make interaction prompt more efficient

This is my current Interaction prompt setup, and it feels super cluttered. InteractionChanged() fires whenever the players current Interaction changes (duh)

local ButtonOrder = {
	[1] = {
		Button = HUD["1"],
		Start = UDim2.new(0, 10, 0.5, 0),
		Position = UDim2.new(0, 0, 0.5, 0)
	},
	[2] = {
		Button = HUD["2"],
		Start = UDim2.new(0.5, 0, 0, 10),
		Position = UDim2.new(0.5, 0, 0, 0)
	},
	[3] = {
		Button = HUD["3"],
		Start = UDim2.new(1, -10, 0.5, 0),
		Position = UDim2.new(1, 0, 0.5, 0)
	},
	[4] = {
		Button = HUD["4"],
		Start = UDim2.new(0.5, 0, 1, -10),
		Position = UDim2.new(0.5, 0, 1, 0)
	},
}

local function InteractionChanged()
	if not HUD.Enabled then
		for _, v in pairs(ButtonOrder) do -- Make buttons invis / reset pos
			v.Button.Visible = false
			v.Button.Position = v.Start
		end
		
		return
	end
	
	local Interaction = CurrentInteraction.Value
	
	for _, v in ipairs(ButtonOrder) do -- Make visible / pos them
		v.Button.Visible = true
		v.Button:TweenPosition(v.Position, Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.1, true)
		wait(0.05)
	end
	
	if Interaction.Parent == PetHolder then -- Pet
		for _, button in pairs(HUD:GetChildren()) do
			if button:IsA("TextButton") then
				if button.Name == "1" then
					button.Button.Title.Text = "Change name"
				elseif button.Name == "2" then
					button.Button.Title.Text = "Carry"
				elseif button.Name == "3" then
					
				elseif button.Name == "4" then
					
				end
			end
		end
	else -- Player
		for _, button in pairs(HUD:GetChildren()) do
			if button:IsA("TextButton") then
				-- Set button texts
				if button.Name == "1" then -- Add friend / Gift cash
					print(Player:IsFriend(Interaction.UserId))
					if Player:IsFriend(Interaction.UserId) then
						button.Button.Title.Text = "Gift cash"
					else
						button.Button.Title.Text = "Add friend"
					end
				elseif button.Name == "2" then
					
				elseif button.Name == "3" then
					
				elseif button.Name == "4" then
					
				end
				
				button.Activated:Connect(function()
					if button.Name == "1" then
						if Player:IsFriend(Interaction.UserId) then
							-- Prompt gift cash
						else
							-- Send friend request
							StarterGui:SetCore("PromptSendFriendRequest", Interaction)
						end
					end
				end)
			end
		end
	end
end

Me currently looping through each button and checking its name to set what text should appear in it, but then also checking the buttons name when its clicked feels some what redundant. How can I tidy this up? I’d also like it to only show the necessary buttons. Currently I have all 4 buttons setup, but I don’t know what to do if I only want say 2 buttons to show, but showing buttons 1 and 2 only would look odd, as they are the ones on the left and top. So to some how do a radial type thing, which I’ve tried, but I get problems because its a BillboardGui and you get problems with descendants that clip the Gui. Even with ClipDescendants false, stuff still gets clipped or doesn’t work

This is what it currently does
ezgif.com-gif-maker (10)

1 Like

You have a good start with the ordered button table. You can use it to tidy up some more things.

For example, all the other attributes you hard-code (name, , you can put in here instead:

local ButtonOrder = {
	[1] = {
		Button = HUD["1"],
		Start = UDim2.new(0, 10, 0.5, 0),
		Position = UDim2.new(0, 0, 0.5, 0),
        PetName = "Change Name",
        PlayerName = function(Player, Interaction)
            if Player:IsFriend(Interaction.UserId) then
                return "Gift cash"
            else
                return "Add friend"
            end
        end,
        PlayerFunction = function(Player, Interaction)
            if Player:IsFriend(Interaction.UserId) then
                -- Prompt gift cash
            else
                -- Send friend request
                StarterGui:SetCore("PromptSendFriendRequest", Interaction)
            end
        end,
	},
	-- .
    -- .
    -- . etc
}

You would make these extra table keys for each button depending on what they are for, and you can change the names to something more meaningful (but they all have to be the same name). This leads to getting rid of the if statements in the loops,

local function InteractionChanged()
	if not HUD.Enabled then
		for _, v in pairs(ButtonOrder) do -- Make buttons invis / reset pos
			v.Button.Visible = false
			v.Button.Position = v.Start
		end
		
		return
	end
	
	local Interaction = CurrentInteraction.Value
	
	for _, v in ipairs(ButtonOrder) do -- Make visible / pos them
		v.Button.Visible = true
		v.Button:TweenPosition(v.Position, Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.1, true)
		wait(0.05)
        
        if Interaction.Parent == PetHolder then -- Pet
			v.Button.Name = v.PetName
	    else -- Player
			-- Set button texts
            v.Button.PlayerName(Player, Interaction)
			v.Button.Activated:Connect(function()
                v.PlayerFunction(Player, Interaction)
			end)
		end
	end
end

There’s some more cleaning up you can do in terms of disconnecting the event when a new InteractionChanged fires but the main logic looks a lot cleaner, with the data/methods for each button in its own section. I’ve only done the cleaning for Button1, you will have to do the rest. Hopefully I’ve shown enough so that you can do that for the rest of the buttons.

I really don‘t understand your code, it would take me a little bit of time (this dosen‘t mean this is bad)

Maybe you could use the ProximityService (even if this is beta for now, after this will be out of beta it would work) for the initial „press E“.

I never tried to do something like this, I think it dosen‘t look bad.

I’ve already got my own interaction system setup, but will probs transfer to ProximityService when its out of Beta. This question relates more so to the menu after pressing the E key.

1 Like

Oh, now I understand better what you mean. I am currently start to take a break from Roblox, but maybe if I then have time I could try to find the best method to handle this (and look into your script to even understand it).