"MouseButton2 is not a valid member of "Enum.KeyCode""

Hi,

I tried to find if a function is named after a Enum by using table.find. It works but I ran into another problem. If the function is named after a KeyCode, then the table.find that is looking for UserInputType will error, vice-versa. How do I get around this problem?

function Interaction.InteractConnections(self: ClassType): ()
	if not self.CurrentObject:FindFirstChild("Interact") then
		warn("Couldn't find interaction module inside of:", self.CurrentObject.Name)
		return
	end
	
	local ModuleScript = self.CurrentObject.Interact
	local Module = require(ModuleScript)
	
	local UITenums = Enum.UserInputType:GetEnumItems()
	local KCenums = Enum.KeyCode:GetEnumItems()

	for fnName, fnCode in pairs(Module) do
		if type(Module[fnName]) ~= "function" then
			continue
		end
	
		if table.find(UITenums, Enum.UserInputType[fnName])then
			print("UserInputType found inside of", ModuleScript.Name..":", fnName)
		end
		
		if table.find(KCenums, Enum.KeyCode[fnName]) then
			print("KeyCode found inside of", ModuleScript.Name..":", fnName)
		end
	end
end
1 Like

put return after your prints 30char

1 Like

Pretty sure you need to use UserInputType instead

Yeah but even if I do that, it will error if it’s a key code because it goes through this first:

		if table.find(UITenums, Enum.UserInputType[fnName])then
			print("UserInputType found inside of", ModuleScript.Name..":", fnName)
		end

and because it isnt a userinputtype, it will error. So adding a return in both statements wouldn’t work.

No, thats how I want my class to be. To support keycodes and userinputtypes

if table.find(UITenums, Enum.UserInputType[fnName])then

Mouse buttons are UserInputTypes!

If Enum.UserInputType[name] doesn’t have an index, it errors the function!

local index = table.find(Enum.UserInputType:GetEnumItems(),fnName) -- check enums for name
index = table.find(UITenums,Enum.UserInputType[index]) -- makes sure there's a table index or not
if index then -- now you have the current index 
index = UITenums[index] -- if the table wasn't changed, you can get the value now
2 Likes

I got an error:

 21:02:59.825  ReplicatedStorage.Source.Classes.Interaction:192: invalid argument #2 (string expected, got nil)  -  Studio
		local KCindex = table.find(Enum.KeyCode:GetEnumItems(),fnName)
		local UITindex = table.find(Enum.UserInputType:GetEnumItems(),fnName)
		UITindex = table.find(UITenums,Enum.UserInputType[UITindex])
		KCindex = table.find(KCenums,Enum.KeyCode[KCindex])
		
		if UITindex then
			print("UserInputType found inside of", ModuleScript.Name..":", fnName)
			--self.InteractionConnections:Connect(UserInputService.InputBegan, function(input: InputObject, gameProcessedEvent: boolean) 
			--	if input.UserInputType == Enum.UserInputType[fnName] then
			--		Module[fnName]()
			--	end
			--end)
		end
		
		if KCindex then
			print("KeyCode found inside of", ModuleScript.Name..":", fnName)
			--self.InteractionConnections:Connect(UserInputService.InputBegan, function(input: InputObject, gameProcessedEvent: boolean) 
			--	if input.KeyCode == Enum.KeyCode[fnName] then
			--		Module[fnName]()
			--	end
			--end)
		end

– fixed the local KCindex = table.find(Enum.KeyCode:GetEnumItems(),fnName)

1 Like

My bad!

You’ll always want to make sure the index isn’t nil, if you use table[index] as the table.find() search.
Your function is pretty much erroring because you’re running

table.find(validTable,existingTable[missingIndex]) == error
existingTable[missingIndex] would == nil because missingIndex wasn’t found

local index = table.find(Enum.UserInputType:GetEnumItems(),fnName) -- check enums for name
if index then -- if not nil continue
     index = table.find(UITenums,Enum.UserInputType[index]) 
     if index then -- now you have the current index 
          index = UITenums[index] -- if the table wasn't changed, you can get the value now
     end
end

I don’t know, it seems like your nesting the if statements just for it to have the same issues, but when I tried this:

local KCindex = table.find(Enum.KeyCode:GetEnumItems(),fnName)
		local UITindex = table.find(Enum.UserInputType:GetEnumItems(),fnName)
		
		if UITindex then
			UITindex = table.find(UITenums,Enum.UserInputType[UITindex])
			print("UserInputType found inside of", ModuleScript.Name..":", fnName)
			--self.InteractionConnections:Connect(UserInputService.InputBegan, function(input: InputObject, gameProcessedEvent: boolean) 
			--	if input.UserInputType == Enum.UserInputType[fnName] then
			--		Module[fnName]()
			--	end
			--end)
		end
		
		if KCindex then
			KCindex = table.find(KCenums,Enum.KeyCode[KCindex])
			print("KeyCode found inside of", ModuleScript.Name..":", fnName)
			--self.InteractionConnections:Connect(UserInputService.InputBegan, function(input: InputObject, gameProcessedEvent: boolean) 
			--	if input.KeyCode == Enum.KeyCode[fnName] then
			--		Module[fnName]()
			--	end
			--end)
		end

Nothing errored but also nothing happened.

One thing I thought of, index types! Make sure the tables have the same kinds, either numerical indexes, or character-ed name,

table[1]

table["dictionaryValue"]

other than this I’m lost too, hope you get this fixed

2 Likes

Why not just use the actual EnumItem as the key? That way, you can just check if the key exists in the array from :GetEnumItems():

local inputs = {
	[Enum.KeyCode.R] = function()
		print("Player has pressed R")
	end;

	[Enum.UserInputType.MouseButton1] = function()
		print("Player has left clicked")
	end;

	[Enum.KeyCode.B] = function()
		print("Player has pressed B")
	end;

	[Enum.UserInputType.MouseButton2] = function()
		print("Player has right clicked")
	end;
}

for key, func in pairs(inputs) do
	if (table.find(Enum.UserInputType:GetEnumItems(), key)) then
		print("This is a UserInputType:" .. key.Name)
		func()
	end
	
	if (table.find(Enum.KeyCode:GetEnumItems(), key)) then
		print("This is a KeyCode:" .. key.Name)
		func()
	end
end
3 Likes

I have it set up like this:
Screen Shot 2024-03-24 at 9.31.10 PM

Door has a tag called “Interactable”. The class checks all the tag items and looks for the module called Interact. Then inside the module you have functions that are named by controls.

The door interact has:

local Door = {}

function Door.MouseButton1()
	print("Mousebutton1")
end

function Door.MouseButton2()
	print("MouseButton2")
end

return Door

The class automatically checks for these functions and connects them once the player is able to interact with the Door. Now the player is able to right click or left click or use the key e on the door. The reason it is set up like this because I feel like it is more easier to change and more readable. If the player isn’t interacting with the door anymore, it disconnects all the interaction connections.

So TLDR: I can’t put a table with the enums inside the class because this is how I want it to be set up.

2 Likes

UITindex = table.find(UITenums,Enum.UserInputType[UITindex].Name) – added .name
KCindex = table.find(KCenums,Enum.KeyCode[KCindex].Name)

Was this it possibly??

2 Likes

It didn’t work but luckily I found a solution that didn’t seem very performant to me.

Output:

  21:54:44.924  KeyCode found inside of Interact: E  -  Client - Interaction:222
  21:54:44.924  UserInputType found inside of Interact: MouseButton1  -  Client - Interaction:209
  21:54:44.924  UserInputType found inside of Interact: MouseButton2 

Door module:

local Door = {}

function Door.E()
	print("E")
end
	
function Door.MouseButton1()
	print("Mousebutton1")
end

function Door.MouseButton2()
	print("MouseButton2")
end

return Door

Function:

	local function CheckEnums(string): string
		for _, v in pairs(KCenums) do
			if v.Name == string then
				return "KeyCode"
			end
		end
		
		for _, v in pairs(UITenums) do
			if v.Name == string then
				return "UserInputType"
			end
		end
		
		return "None"
	end
	
	for fnName, fnCode in pairs(Module) do
		if type(Module[fnName]) ~= "function" then
			continue
		end
		
		local EnumType = CheckEnums(fnName)

		if EnumType == "UserInputType" and table.find(UITenums, Enum.UserInputType[fnName])then
			print("UserInputType found inside of", ModuleScript.Name..":", fnName)
			
			self.InteractionConnections:Connect(UserInputService.InputBegan, function(input: InputObject, gameProcessedEvent: boolean) 
				if input.UserInputType == Enum.UserInputType[fnName] then
					Module[fnName]()
				end
			end)
			
			continue -- don't need to go to the other if statement if it goes through this.
		end
		
		
		if EnumType == "KeyCode" and table.find(KCenums, Enum.KeyCode[fnName]) then
			print("KeyCode found inside of", ModuleScript.Name..":", fnName)
			
			self.InteractionConnections:Connect(UserInputService.InputBegan, function(input: InputObject, gameProcessedEvent: boolean) 
				if input.KeyCode == Enum.KeyCode[fnName] then
					Module[fnName]()
				end
			end)
			
			continue
		end
	end

A lot of for in pairs loops. I’d still take any solution that is less performant than this.

If you connect InputBegan regardless of which input it is, I suggest just checking if input.KeyCode.Name or input.UserInputType.Name exists in the module:

self.InteractionConnections:Connect(UserInputService.InputBegan, function(input: InputObject, gameProcssedEvent: boolean)
	local func = Module[input.KeyCode.Name] or Module[input.UserInputType.Name] -- If you pressed E, this would basically be Module["E"]
	
	if (func ~= nil) then
		func()
	end
end)
1 Like

a cheaty fun way is to pcall printing it and if it errors you know it isn’t there lmao

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.