Hello, I'm working on my NPC for my game and so far have achieved awesome progress it works flawlessly as of so far however, to make it easier for my self i'd love to get into Module scripts as that will allow me to easily navigate through my code when it comes to error fixing and adding code in general. The issue is, where do i get started? I understand the practicality of module scripts but when i open up one of those scripts i feel really awkward on how to use them.
Here is all my code for the NPC for those who are interested:
-Controller
local Event = script.Parent:WaitForChild("findTarget") local npcStorage = workspace.Game.npcStorage while true do wait(1) if #npcStorage:GetChildren() >0 then Event:FireServer() else script.Parent:WaitForChild("Target").Value = "" end end
-TargetFinder
local Event = script.Parent:WaitForChild("findTarget") Event.OnServerEvent:Connect(function() local NPC = script.Parent.Parent local myTeam = NPC.AI:WaitForChild("Team") local HRP = NPC:WaitForChild("HumanoidRootPart") local Target = NPC.AI:WaitForChild("Target") local NPCs = workspace.Game.npcStorage local closestTarget = nil local targetsDistance = nil for _, NPC in pairs(NPCs:GetChildren()) do local eHRP = NPC:FindFirstChild("HumanoidRootPart") for _, child in pairs(NPC:GetChildren()) do if child.Name == "AI" and child:FindFirstChild("Team").Value ~= myTeam.Value then --and (HRP.Position - eHRP.Position).magnitude < targetsDistance then local Team = child:FindFirstChild("Team") closestTarget = NPC.Name targetsDistance = (HRP.Position - eHRP.Position).magnitude Target.Value = closestTarget end end end end)
-Movement
local atkDistance = 3.5 local Tower = workspace.Game:FindFirstChild("RedTower") --/// myNPC local NPC = script.Parent.Parent local HRP = NPC:WaitForChild("HumanoidRootPart") local Hum = NPC:WaitForChild("Humanoid") local AI = NPC:WaitForChild("AI") local Team = AI:WaitForChild("Team") local Target = AI:WaitForChild("Target") local moveToTower = AI:WaitForChild("moveToTower") --/// Event local Event = script.Parent:WaitForChild("Trigger") local findTarget = script.Parent:WaitForChild("findTarget") Hum:MoveTo(Tower.Target.Position) Target.Changed:Connect(function() --/// Enemy NPC local eNPC = workspace.Game.npcStorage:FindFirstChild(Target.Value) local eHRP = eNPC:FindFirstChild("HumanoidRootPart") while true do wait(.1) if Target.Value == "" or eNPC:FindFirstChild("Humanoid").Health <= 0 then Target.Value = "" Hum:MoveTo(Tower.Target.Position) --/// Attack or Move elseif (HRP.Position - eHRP.Position).magnitude <atkDistance then -- Checks if the distance between the enemy and NPC is less than 5 studs Event:FireServer() elseif Target.Value ~= nil then Hum:MoveTo(eHRP.Position) --Hum.MoveToFinished:Wait() -- May improve srv performance but will make NPCs appear derpy as they may walk to far than suppose to end end end)
If you need to know any more information please let me know. And thankyou if you can explain how to use Module Scripts.
ModuleScript
objects have default code already pasted, similar to Script
s and LocalScript
s how they have print("Hello world")
as the default code. This is the default code for modules:local module = {} return module
local module = {} -- You can name them anything, I just used the default name function module.functionInModule() print("I’m a function inside a module!") end return module -- required to work
local
before function
. local function
local module = require(game.Workspace.ModuleScript) -- i put in workspace module.functionInModule() -- prints code
ModuleScript
s is that they take on the behaviour of a Script
or a LocalScript
, depending on what you use. For example, if you used LocalPlayer
in a module, you MUST require
it from a LocalScript
else the script will error and LocalPlayer
will return nil
, since LocalPlayer
is client-side only.Hello there! I am excited that you are giving ModuleScripts
a chance for the sake of organization.
Although there are good practices and bad practices many people use modules to a different extent, because as is with a normal script, it heavily depends on your coding style and how much code you can handle in your regular scripts before you consider it unorganized.
With that in mind, first I will teach you the basic functionality of a module, and then I will show you how I use modules.
--
A module is like any other script, the code in it runs from top to bottom, and it only runs once.
If you have a loop inside it, that loop will obviously still loop, but a ModuleScript is not a function that you call.
The primary differences are as follows:
required
return exactly one value
Module Script
print("ModuleScript is running") return true
"Normal" (Server) Script
local testing = require(script.Testing) --> true if testing then print("TEST MODE ACTIVATED!") else print("THIS IS NOT A DRILL!") end
In this example, all the module does is print that it is running, and then returns true
. In this case, I am letting the script that is requiring it know that the game is currently in "test mode", whatever that means.
With that being said, you can require the same module in multiple scripts, and then they will all know that the game is in test mode. If you want to change the test mode, you just have to change it in the module, and not have to worry about each individual script.
Module Script
local quickmaths = {} quickmaths.Add = function(a, b) if a and b then local res = a + b print(("%d + %d = %d"):format(a, b, res)) return res else print("2 + 2 = 4") return 2 + 2 end end quickmaths.Subtract = function(a, b) if a and b then local res = a - b print(("%d - %d = %d"):format(a, b, res)) return res else print("4 - 1 = 3") print("QUICKMATHS") return 4 - 1 end end return quickmaths
"Normal" (Server) Script
local quickmaths = require(script.quickmaths) local seven = quickmaths.Add(5, 2) local four = quickmaths.Subtract(seven, 3) quickmaths.Add() quickmaths.Subtract()
ModuleScripts
are extensions of normal scripts. You can throw the clutter in them. Functions, tables, math, libraries. What does that leave your normal script looking like?
If you've done it right, at the end of it all, it is short, readable, and easy to understand the flow of the game.
--
Final notes:
Contact me on Discord if you have any questions, or would like more information about modules that I have not provided in this answer. My Discord tag is amanda#9999.
local Object = {} --------------- Function.Waves(BrickColor.new("Cyan"), Torso, 1, 0.5) local Effects = game:GetService("ServerStorage"):WaitForChild("Skills") local Meshes = Effects:WaitForChild("Assets") local Parts = workspace:WaitForChild("PartStorage") local rep = game:GetService("ReplicatedStorage") local Assets = rep:WaitForChild("Assets") local auras = rep:WaitForChild("Aura") local auras2 = rep:WaitForChild("WideAuras") ----------- DUST 2.0 function Object.Dust(root, duration) local dust = Assets.Dust:Clone() dust.Parent = root wait(duration) dust.Rate = 0 game.Debris:AddItem(dust, 5) end return Object ------ script local object = require(module) ----- define everything in the script you call the module functions local plr = plr local char = character local root = char.HumanoidRootPart object.Dust(root, 5)