Seeking Guidance on Proper Tool Implementation and OOP

Hi guys,

I’ve been struggling a bit with going about making tools for my project. I’m still a bit of a beginner/intermediate with Lua.

The problem I currently have is that I don’t know if its good idea to handle all of these tools using just their own module scripts. I tried learning Knit but ended up confusing myself even more about single-script architecture.

I’ve also been struggling to learn OOP, specifically using it for actual objects/instances in the game (e.g. a street light or a gun). Most of the tutorials I’ve watched only teach OOP through using math or numbers and don’t actually apply this knowledge to actually making something in-game, though I could be wrong and I just haven’t looked properly.

For instance, I’ve recently made a simple med-kit tool that heals the player when they have below 100HP. I have 2 module scripts: one that handles the client’s input (clicking to heal, pressing Q to drop the med-kit) and one that handles the healing the player via the server. All of this works, but I just feel like I’m doing things wrong and that there are other alternative or better ways to do this.

For the code below, I place the client module script in replicated storage and the server into Server Script Service. I am using single-script architecture.

Client - unfinished code but will just fire server on mousebutton1click
local HealthKitClient = {}

local CollectionService = game:GetService("CollectionService")
local UserInputService = game:GetService("UserInputService")
local LocalPlayer = game:GetService("Players").LocalPlayer
local RemoteEvent = game:GetService("ReplicatedStorage"):WaitForChild("Remotes"):WaitForChild("RemoteEvent")

function PlayerAdded(player)
	if player ~= LocalPlayer then return end
	
end

game.Players.PlayerAdded:Connect(PlayerAdded)
for _, player in pairs(game.Players:GetPlayers()) do
	spawn(function() PlayerAdded(player) end)
end

return HealthKitClient
Server
local ToolServer = {}

local CollectionService = game:GetService("CollectionService")
local StoredTools = game:GetService("ReplicatedStorage"):WaitForChild("Tools")
local WorldModelTools = game:GetService("ReplicatedStorage"):WaitForChild("WorldModels")
local RemoteEvent = game:GetService("ReplicatedStorage"):WaitForChild("Remotes"):WaitForChild("RemoteEvent")

function connectTrigger(tool)
	local prompt = tool:FindFirstChild("PickUpPrompt", true)
	prompt.Triggered:Connect(function(player)
		local character = player.Character
		local backpack = player:WaitForChild("Backpack")
		for i, storedtool in ipairs(StoredTools:GetDescendants()) do
			if tool.Name == storedtool.Name then
				if not character:FindFirstChild(tool.Name) and not backpack:FindFirstChild(tool.Name) then
					local toolClone = storedtool:Clone()
					toolClone.Parent = backpack
					character.Humanoid:EquipTool(toolClone)
					tool:Destroy()
				end
			end
		end
	end)
end

for i, tool in ipairs(CollectionService:GetTagged("ToolPickup")) do
	connectTrigger(tool)
end

CollectionService:GetInstanceAddedSignal("ToolPickup"):Connect(connectTrigger) 

RemoteEvent.OnServerEvent:Connect(function(player, key)
	local playerChar = game.Workspace:FindFirstChild(player.Name)
	if playerChar then
		if key == "DropEvent" then 
			local tool = playerChar:FindFirstChildWhichIsA("Tool")
			if tool then
				for i, wmodel in ipairs(WorldModelTools:GetDescendants()) do
					if tool.Name == wmodel.Name then
						if playerChar:FindFirstChild(tool.Name) then
							local mwmodelClone = wmodel:Clone()
							local proxy = Instance.new("ProximityPrompt")
							proxy.Parent = mwmodelClone
							mwmodelClone.Parent = game.Workspace.Map.Items
							mwmodelClone.CFrame = player.Character.HumanoidRootPart.CFrame
							
							mwmodelClone:AddTag("ToolPickup")
							tool:Destroy()
						end
					end
				end
			end
		end
		
		if key == "HealthKitEvent" then 
			local humanoid = playerChar:WaitForChild("Humanoid")
			local maxHealth = humanoid.MaxHealth
			if playerChar:WaitForChild("Humanoid").Health == playerChar:WaitForChild("Humanoid").MaxHealth then 
				print("Health is already full") return end
			print(humanoid.Health)
			local tool = playerChar:FindFirstChildWhichIsA("Tool")
			if tool.Name == "HealthKit" then
				humanoid.Health += 20
				print("Healed, health is now:", humanoid.Health)
				wait(.1)
				tool:Destroy()
			end	
		end
	end
end)

print("ItemManager working...")
return ToolServer

Overall, I’m really struggling with what is considered the proper way to code/do things, which I’m aware is unrealistic since games can be coded in infinite ways, and I feel like I have to really scavenge to see what works and what doesn’t without any guidance.

Thank you for taking the time to read this

1 Like

There’s only 2 fields you need to be concern with when writing code for your game.

  1. Does the script have good/decent game performance? ( meaning little lag)
  2. Does it (try to) prevent players from cheating?

You can pretty much code your game anyway you want if you have those “rules” in mind.

1 Like