Need help for passing all models as arguments to module script?

Hello, quick question. So today I am trying to make robbable ATMS in one code. Basically one code will be handling all ATMs around the map. I have a module that handles all the existing ATMs placed around the map. I put two for now. Let’s get to the problem!

So the problem is the script works fine. I have a client script that will require the module. But somehow I did a for loop through all the atms and require the module, pass the arguments to it and this happened:

As you can see, An E Icon shows up to one of them but when I walk to the other one, nothing happens… Why? I’ll be showing the code.

Module script:

local UserInputService = game:GetService("UserInputService")
local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local RunService = game:GetService("RunService")
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart") or Character.PrimaryPart
local DefaultBarSize = UDim2.new(0,10,0,10)
local FullBarSize = UDim2.new(0,100,0,10)
local PlayerGui = Player:WaitForChild("PlayerGui")
local StarterGui = game:GetService("StarterGui")
local Players = game:GetService("Players")
local LabelButton = PlayerGui.MiniHeist.RobATM.ImageLabel

local ATMHeist = {}

function ATMHeist:RegisterATM(ATMModel)
	local StatusFolder = ATMModel.Status
	UserInputService.InputBegan:Connect(function(keyCode)
		if keyCode.KeyCode == Enum.KeyCode.E then
			local Magnitude = (ATMModel.RobATM.Position - HumanoidRootPart.Position).Magnitude
			if Magnitude <= 6 and StatusFolder.Open.Value == true then
				LabelButton.Loader.Visible = true
				while UserInputService:IsKeyDown(Enum.KeyCode.E) do
					wait()
					LabelButton.Loader.Fill.Size = LabelButton.Loader.Fill.Size + UDim2.new(0,1,0,0)
					
					if LabelButton.Loader.Fill.Size == FullBarSize then
						PlayerGui.UISounds.Cash:Play()
						LabelButton.Loader.Fill.Size = DefaultBarSize
						LabelButton.Loader.Visible = false
						LabelButton.Visible = false
						ATMModel.RobATM.RobATM.Event:FireServer({reason = "RobATM"})
						--script.Disabled = true
						break
					end		
					
					if not UserInputService:IsKeyDown(Enum.KeyCode.E) then
						--print("E key is not held... ")
						LabelButton.Loader.Fill.Size = DefaultBarSize
						wait(0.1)
						LabelButton.Loader.Visible = false
						break
					end
					
				end			
			end			
		end
	end)
	
	
	RunService.RenderStepped:Connect(function()
		LabelButton.Visible = false
		local Magnitude = (ATMModel.RobATM.Position - HumanoidRootPart.Position).Magnitude
		if Magnitude <= 6 and StatusFolder.Open.Value == true then
			LabelButton.Visible = true
			local ScreenPoint = workspace.CurrentCamera:WorldToScreenPoint(ATMModel.RobATM.CFrame.Position)
			LabelButton.Position = UDim2.new(0,ScreenPoint.X,0,ScreenPoint.Y,0)		
		end
	end)
end


return ATMHeist

Localscript requiring the module:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ATMModule = require(ReplicatedStorage.Modules.ATMHeist)
local ATMModels = workspace.ATMs:GetChildren()

for i,v in pairs(ATMModels) do
	if v:IsA("Model") then
		ATMModule:RegisterATM(v)
	end
end

----More Details----

How does the module work?
Answer: The module works as a handler for all the ATM models scattered around the map. So there are two ATMs in the map. It’s supposed to handle both of them. When required, there will be a function named “RegisterATM”. When called, it contains one parameter called “ATMModel” that means the model of every ATM on the map. It will register the model to the module as a parameter.

How is it required?
Answer: Before requiring the module, create 3 variables first. ReplicatedStorage service, the module, get all children of the ATMs folder in workspace (meaning it will get the two atms on the map). Then make a for in pairs loop then check if its a model then require the module, Call the function named “RegisterATM” then put “v” in the parameters. “v” means the variable of all the ATM models.

If you have any suggestions, reply below.
Got anymore questions to ask me? Ask below in the replies.

All help is appreciated!
Thanks in advance! :smiley:

The thing you should do is check if the player is whatever amount of studs near the atm which youve already done which is good but the second part is, since thats a billboard ui, just set the adornee of it to the nearest atm’s primary part if its a model and it will switch back in forth depending on how far you are from an atm, hope this helped

1 Like

@loveicicIe The E icon is not actually a billboard gui. Its actually an image in playergui, whenever I am close enough to the atm, the Icon will become visible and it will position itself to the atm. Check the module code above.

Yeah thats not a very good way of doing it, you should change it to a billboard gui entirely, trust me ive done things like this and a billboard ui is the best for this type of thing because you cant see the adornee very easily to the nearest part

1 Like

@loveicicIe Well that could help but in some games like Mad City, There are ATMs scattered around places like Bank. When you approach to one of them, it looks like the E Icon is coming from a imagelabel not a billboardgui. But I would still try ur method but did you notice the InputBegan connection? Thats what handles holding E then a loading bar will appear if E is held then the loading bar will fill up then fireserver to give the player some cash. Would it break the module code or no?

I dont think it would breeak the module code since its not directly linked to the E image label

1 Like

@loveicicIe Will it reference the billboard gui properly since the parameter named “ATMModel” is the two ATM models in the map?

Example:

local Icon = ATMModel.RobATM.BillboardGui

‘RobATM’ is actually an invisible part that acts as a node so thats where the Icon will work and popup.

1 Like

@loveicicIe Is it gonna work? Reply pls…

It looks like you’re making this wayy too complicated for what it does, there are easier ways to do this.
Your current code doesn’t check that there are other atms closer, just if one atm is close enough, it doesn’t take all the atms into account, so it’s likely making the E prompt invisible when one isn’t close enough but another is, and because of how :GetChildren() gets children, the one on the left is the one that has higher priority.
I wrote up a script that uses CollectionService and tags, which is a good way to keep things organized and clean. This is just a problem of getting the closest ATM, which can be done with a loop like this:

local ATMS = collectionService:GetTagged("ATM") --whatever, I prefer collectionService:GetTagged("ATM")

while true do
	wait(0.25)
	local LowestDist = math.huge
	local ClosestAtm
	for i,v in pairs(ATMS) do
		local CurrentDist = game.Players.LocalPlayer:DistanceFromCharacter(v.PrimaryPart.Position)
		if CurrentDist > LowestDist then
			LowestDist = CurrentDist
			ClosestAtm = v
		end
	end
	if ClosestAtm and LowestDist <= 6 then --whatever distance, 6 is what I did for this example
		--CreateIndicator for the atm, like loveicicIe said, it is easier to use a billboard Gui
	else
		--Remove all indicators
	end
end

You can then make the ClosestAtm defined before the loop so more of the script can access it and hook up a userInputService input began connection and check if there is a closestAtm and do whatever to that atm.
You can parent the BillboardGui you make to the StarterGui and just set it’s adornee to closestAtm (even if it’s nil, so that way it will stop showing E when no atm is close enough) when you loop through all the atms and everything will be good to go!

1 Like

@Styre_x Finally! After a few weeks of prototyping, I finally managed to fix it! Thanks for helping! Also by the way I’ve use some parts of this code but the entire code, I rewrote it entirely. Since this code is similar to crazyman32’s press E to sit code. I used his tutorial an applied the code but I revamped the entire code completely. Including all my ATM mechanics and everything. Also, I am not modularizing this robabble atm system anymore since I redid the entire code completely in one localscript. Again, its been weeks and I’ve been prototyping your code and I managed to fix my atms. Thanks.

1 Like