I have a module script that handles NPCs in my game, and a server script that constructs npcs, and a local script that handles player interaction with the npc.
Everything works fine, but when I call the Purchase method from the server script, it calls that method for every single NPC in the workspace. Can anyone help me with this issue? It would be greatly appreciated
-- Server script that constructs a new npc every 5 seconds.
local NPC = require(script.Parent.NPCSHandler)
local PS = game:GetService("Players")
while task.wait(5) do
for _,v in PS:GetPlayers() do
local npc = NPC.New(v)
game.ReplicatedStorage.Events.NPCPurchases.OnServerEvent:Connect(function(player,action)
npc:Purchase(player,action)
end)
end
end
-- local script
RepS.Events.NPCPurchases.OnClientEvent:Connect(function(NPC, Obj)
if Player ~= NPC.CustomerOf then return end
local dialog = Instance.new("Dialog")
local dialogChoice = Instance.new("DialogChoice")
dialogChoice.UserDialog = "Sure"
dialogChoice.Parent = dialog
dialog.GoodbyeDialog = "Nah"
dialog.InitialPrompt = `I want to buy {Obj.Name} for {ItemConfigs[Obj.Name].Price}$`
dialog.Parent = NPC.Model.Head
dialog.DialogChoiceSelected:Connect(function(player: Instance, Choice: Instance)
if Choice.UserDialog == dialogChoice.UserDialog then
Events.NPCPurchases:FireServer(true)
else
Events.NPCPurchases:FireServer(false)
end
end)
end)
-- module script that handles npc actions
local module = {}
local paths = {}
local returnpaths = {}
module.__index = module
local NPCConfigs = require(game.ReplicatedStorage.NPCs.Configs)
local PlotFunctions = require(game.ServerScriptService.PlotFunctions)
local PathS = game:GetService("PathfindingService")
local function RandomizeChance()
local TotalWeight = 0
for i,v in NPCConfigs do
TotalWeight += v.AppearChance
end
local RandomNumber = math.random() * TotalWeight
local CurrentWeight = 0
for i,v in NPCConfigs do
CurrentWeight += v.AppearChance
if RandomNumber <= CurrentWeight then
return i
end
end
end
local function CalculatePaths()
for _,v in game.Workspace.Shops:GetChildren() do
local path = PathS:CreatePath()
local success, error = pcall(function()
path:ComputeAsync(game.Workspace.SpawnLocation.Position,v.NPCDestination.Position)
end)
if success and path.Status == Enum.PathStatus.Success then
paths[v] = path:GetWaypoints()
end
local back = PathS:CreatePath()
local success, error = pcall(function()
back:ComputeAsync(v.NPCDestination.Position,game.Workspace.SpawnLocation.Position)
end)
if success and path.Status == Enum.PathStatus.Success then
returnpaths[v] = back:GetWaypoints()
end
end
end
local function FindItemWithLargestPriceInRange(range, plot)
local ItemConfigs = require(game.ReplicatedStorage.Placables.Configs)
local plotObjects = plot.Objects
local object
local largestnum = 0
for i, v in pairs(plotObjects:GetChildren()) do
if ItemConfigs[v.Name].Price > largestnum and ItemConfigs[v.Name].Price <= range then
largestnum = ItemConfigs[v.Name].Price
object = v
end
end
return object
end
local function FindItemWithSmallestPriceInRange(range, plot)
local minval = range / 10
local ItemConfigs = require(game.ReplicatedStorage.Placables.Configs)
local plotObjects = plot.Objects
local object
if minval <= 20 then
minval = 20
end
local smallestnum = math.huge
for i,v in pairs(plotObjects:GetChildren()) do
if ItemConfigs[v.Name].Price < smallestnum and ItemConfigs[v.Name].Price >= minval then
smallestnum = ItemConfigs[v.Name].Price
object = v
end
end
return object
end
CalculatePaths()
function module.New(player)
if not PlotFunctions.GetPlot(player) then return end
local SelectedNPC = RandomizeChance()
local minval = NPCConfigs[SelectedNPC].PurchasingPower / 10
if minval <= 20 then
minval = 20
end
local self = setmetatable({
Model = NPCConfigs[SelectedNPC].Model:Clone(),
PurchasingPower = math.random(minval,NPCConfigs[SelectedNPC].PurchasingPower),
PurchasePriority = NPCConfigs[SelectedNPC].PurchasePriority,
Buys = NPCConfigs[SelectedNPC].Tendency,
ObjectToBuy = nil,
CustomerOf = player,
},module)
self:WalkIn()
return self
end
function module:SelectObjectToBuy()
local plot = PlotFunctions.GetPlot(self.CustomerOf)
local plotObjects = plot.Objects
local ItemConfigs = require(game.ReplicatedStorage.Placables.Configs)
local tbl = {}
for _,v in plotObjects:GetChildren() do
local weight = 0
if ItemConfigs[v.Name].Rarity == self.PurchasePriority then weight += 2 end
if ItemConfigs[v.Name].Price <= self.PurchasingPower then weight += 10 end
if self.Buys == "Expensive" then
if v == FindItemWithLargestPriceInRange(self.PurchasingPower, plot) then weight += 2 end
elseif self.Buys == "Cheap" then
if v == FindItemWithSmallestPriceInRange(self.PurchasingPower, plot) then weight += 2 end
end
tbl[v] = weight
end
local highestnum = 0
local object
for i,v in pairs(tbl) do
if v > highestnum then highestnum = v object = i end
end
if ItemConfigs[object.Name].Price > self.PurchasingPower then object = nil end
return object
end
function module:WalkIn()
local plot = PlotFunctions.GetPlot(self.CustomerOf)
local Humanoid: Humanoid = self.Model.Humanoid
self.Model:PivotTo(CFrame.new(workspace.SpawnLocation.CFrame.X, 5, workspace.SpawnLocation.CFrame.Z))
self.Model.Parent = plot.NPCs
for _,waypoint in paths[plot] do
Humanoid:MoveTo(waypoint.Position)
Humanoid.MoveToFinished:Wait()
end
self:Inquire()
end
function module:Inquire()
local dialog = Instance.new("Dialog")
dialog.Parent = self.Model.Head
dialog.GoodbyeDialog = "Nah"
local plot = PlotFunctions.GetPlot(self.CustomerOf)
local plotObjects = plot.Objects:GetChildren()
local ItemConfigs = require(game.ReplicatedStorage.Placables.Configs)
if plot and #plotObjects > 0 then
self.ObjectToBuy = self:SelectObjectToBuy()
if self.ObjectToBuy then
game.ReplicatedStorage.Events.NPCPurchases:FireClient(self.CustomerOf, self, self.ObjectToBuy)
else
self:WalkAway()
end
else
self:WalkAway()
end
end
function module:WaitInLine()
end
function module:WalkAway()
local plot = PlotFunctions.GetPlot(self.CustomerOf)
local humanoid = self.Model.Humanoid
for _,waypoint in returnpaths[plot] do
humanoid:MoveTo(waypoint.Position)
humanoid.MoveToFinished:Wait()
end
self:Destroy()
end
function module:Purchase(player, action)
local ItemConfigs = require(game.ReplicatedStorage.Placables.Configs)
if action == true and self.ObjectToBuy then
PlotFunctions.Delete(player, self.ObjectToBuy)
player.leaderstats.Money.Value += ItemConfigs[self.ObjectToBuy.Name].Price
self:WalkAway()
else
self:WalkAway()
end
end
function module:Destroy()
self.Model:Destroy()
self = nil
end
return module