I'm trying to practice OOP with zombies. What it's supposed to do is check if a player is around them, NOT an NPC. It will check the magnitude of each player's characters, and chooses the character model with the least magnitude. Then it chases that player using pathfinding service. However, instead of doing that, it just moves to another NPC with the same name. I am using 2 module scripts and a regular script to make it work.
Script (Placed in ServerScriptService):
local replicatedStorage = game:GetService("ReplicatedStorage") local zombieModel = workspace.Zombie local Zombie = require(game:GetService("ServerScriptService").Modules.NPCModule.ZombieModule) local newZombie = Zombie.new(zombieModel, "Zombie", workspace.Ground.Position + Vector3.new(0,10,0)) local model = newZombie.Model local zombiePosition = model.HumanoidRootPart.Position local targetPosition = nil model.Humanoid.WalkSpeed = newZombie.Speed model.Humanoid.Health = newZombie.Health model.HumanoidRootPart.Position = newZombie.SpawnLocation model.Parent = workspace game.Players.PlayerAdded:Connect(function(player) player.CharacterAdded:Connect(function(character) print("reached") game:GetService("RunService").Heartbeat:Connect(function() targetPosition = newZombie:GetClosestTarget() print(targetPosition) if targetPosition and character.HumanoidRootPart.Position == targetPosition then newZombie:FindTarget(zombiePosition, targetPosition) end end) end) end)
ZombieModule (Module script placed in ServerScriptService under a module called "NPCModule"):
local NPC = require(script.Parent) local runService = game:GetService("RunService") local replicatedStorage = game:GetService("ReplicatedStorage") local PFS = game:GetService("PathfindingService") local Zombie = {} Zombie.__index = Zombie function Zombie.new(model, zombieType, position) local newZombie = NPC.new(model, position) setmetatable(newZombie, Zombie) if zombieType == "Zombie" then print("is zombie") newZombie.Speed = 15 newZombie.ZombieType = zombieType print(newZombie.Model.Name) print(newZombie.Model.HumanoidRootPart.Name) end return newZombie end function Zombie:GetClosestTarget() local model = self.Model if model then print("not nil!") end local target = nil local lowestMagnitudeTarget = nil local lowestMagnitude = 99999999999999999 local targetPosition = nil local zombiePosition = model.HumanoidRootPart.Position for i, player in pairs(game.Players:GetPlayers()) do local characterModel = player.Character local hrpPosition = characterModel.HumanoidRootPart.Position print(hrpPosition) local magnitude = (hrpPosition - zombiePosition).Magnitude if magnitude < lowestMagnitude and game.Players:GetPlayerFromCharacter(characterModel)then lowestMagnitude = magnitude lowestMagnitudeTarget = hrpPosition end end target = lowestMagnitudeTarget return target end function Zombie:FindTarget(zombiePosition, targetPosition) local model = self.Model local zombieHumanoid = model.Humanoid local path = PFS:CreatePath({ AgentRadius = 2, AgentHeight = 5, AgentCanJump = true, AgentCanClimb = true, Costs = { Water = 20 } }) while true do path:ComputeAsync(zombiePosition, targetPosition) if path.Status == Enum.PathStatus.Success then for i, waypoint in pairs(path:GetWaypoints()) do if waypoint.Action == Enum.PathWaypointAction.Jump then zombieHumanoid:ChangeState(Enum.HumanoidStateType.Jumping) end zombieHumanoid:MoveTo(waypoint.Position) zombieHumanoid.MoveToFinished:Wait() end end end end return Zombie
NPCModule (Module script placed in ServerScriptService):
local NPC = {} NPC.__index = NPC function NPC.new(model, position) local newNPC = {} setmetatable(newNPC, NPC) newNPC.Model = model:Clone() newNPC.Health = 100 newNPC.Speed = 16 newNPC.InteractionDistance = 2 newNPC.SpawnLocation = position return newNPC end return NPC
As always, thank you for your time.
hiya!
i'm not all too sure myself as to why you're code isn't working, although i thought cleaning it up would help; hopefully give a new aspect to the code
changes
script in ServerScriptService
local replicatedStorage = game:GetService("ReplicatedStorage") local zombieModel = workspace.Zombie local Zombie = require(game:GetService("ServerScriptService").Modules.NPCModule.ZombieModule) local newZombie = Zombie.new(zombieModel, "Zombie", workspace.Ground.Position + Vector3.new(0,10,0)) local model = newZombie.Model local zombiePosition = model.HumanoidRootPart.Position local targetPosition = nil model.Humanoid.WalkSpeed = newZombie.Speed model.Humanoid.Health = newZombie.Health model.HumanoidRootPart.Position = newZombie.SpawnLocation model.Parent = workspace game:GetService("RunService").Heartbeat:Connect(newZombie.AdvancedAI)
zombie module
local NPC = require(script.Parent) local runService = game:GetService("RunService") local replicatedStorage = game:GetService("ReplicatedStorage") local PFS = game:GetService("PathfindingService") local Zombie = {} Zombie.__index = Zombie function Zombie.new(model, zombieType, position) local newZombie = NPC.new(model, position) setmetatable(newZombie, Zombie) if zombieType == "Zombie" then print("is zombie") newZombie.Speed = 15 newZombie.ZombieType = zombieType print(newZombie.Model.Name) print(newZombie.Model.HumanoidRootPart.Name) end return newZombie end function Zombie:AdvancedAI() local ClosestTarget = self:GetClosestTarget() if not ClosestTarget then -- warn("unable to identify a close target - wth") return false -- fail :( end self:FindTarget(self.Model.HumanoidRootPart.Position, ClosestTarget.HumanoidRootPart.Position) return true -- success! end function Zombie:GetClosestTarget() assert(self.Model, string.format("no model exists! (got %s)", tostring(self.Model or nil))) --[[ if you don't fancy a hard error, here's a less ASSERTIVE assert: if not self.Model then -- end the call return end ]] local target = nil local lowestMagnitudeTarget = nil local lowestMagnitude = 12^12 -- aka a big hecking number local zombiePosition = self.Model.HumanoidRootPart.Position for i, player in pairs(game.Players:GetPlayers()) do local characterModel = player.Character local magnitude = (characterModel.HumanoidRootPart.Position - zombiePosition).Magnitude if magnitude < lowestMagnitude then lowestMagnitude = magnitude lowestMagnitudeTarget = characterModel end end return lowestMagnitudeTarget end function Zombie:FindTarget(zombiePosition, targetPosition) local model = self.Model local zombieHumanoid = model.Humanoid local path = PFS:CreatePath({ AgentRadius = 2, AgentHeight = 5, AgentCanJump = true, AgentCanClimb = true, Costs = { Water = 20 } }) while true do path:ComputeAsync(zombiePosition, targetPosition) if path.Status == Enum.PathStatus.Success then for i, waypoint in pairs(path:GetWaypoints()) do if waypoint.Action == Enum.PathWaypointAction.Jump then zombieHumanoid:ChangeState(Enum.HumanoidStateType.Jumping) end zombieHumanoid:MoveTo(waypoint.Position) zombieHumanoid.MoveToFinished:Wait() end end end end return Zombie