The following script is a Mob Handler for my rpg game. It is meant to control all enemies in the game. The problem with it is that I think the script activity is excessive. 3% script activity just to handle abt 15 npcs that do more or less the same thing seems ridiculous to me.
I feel like I can make this a lot more optimized and use less stuff like polling.
to be more specific i just want my code to be more optimized and have less use of things like unnecessary polling and other bad practices
script:
local PS = game:GetService("Players")
local RpS = game:GetService("ReplicatedStorage")
local TS = game:GetService("TweenService")
local DS = require(RpS.GameModules.DataStore2)
local Mobs = workspace.Mobs
function mobhandle(Mob)
local MobClone = Mob:Clone()
local Torso = Mob.Torso
local Root = Mob.HumanoidRootPart
local Enemy = Mob:FindFirstChild("Enemy") or Mob:FindFirstChild("BlockingEnemy")
local Animator = Enemy.Animator
local _M = require(Mob.MobConfig)
local Billboard = Enemy.HUD
local DamageR = false
local DamageL = false
local DamageM = false
local function findNearestTorso(pos)
local found = nil
local dist = _M.FollowDistance
local thingy = dist/2
local Reg3 = Region3.new(Vector3.new(pos.X - thingy, pos.Y - thingy, pos.Z - thingy), Vector3.new(pos.X + thingy, pos.Y + thingy, pos.Z + thingy))
local parts = workspace:FindPartsInRegion3WithWhiteList(Reg3, workspace.Players:GetDescendants())
for _, v in pairs(parts) do
if PS:GetPlayerFromCharacter(v.Parent) then
found = v.Parent:WaitForChild("Torso")
break
end
end
return found
end
Enemy.MaxHealth = _M.MobHealth
Enemy.Health = Enemy.MaxHealth
Enemy.WalkSpeed = _M.MobWalkSpeed
Billboard.MobHealthBar.HealthText.Text = Enemy.Health.." / ".._M.MobHealth
task.spawn(function()
if Mob:FindFirstChild("CanBlock") then
local TriggerHP = Mob.CanBlock.TriggerHealth
local Min = Mob.CanBlock.MinCooldown
local Max = Mob.CanBlock.MaxCooldown
local anim = Mob:FindFirstChild("BlockAnim") and Animator:LoadAnimation(Mob.BlockAnim) or nil
if TriggerHP.Value <= 0 then TriggerHP.Value = _M.MobHealth / 2 end
while true do
if Enemy.Health > 0 then
if not Enemy.WalkToPoint then Enemy:GetPropertyChangedSignal("WalkToPoint"):Wait() end
if Enemy.Health > TriggerHP.Value then repeat task.wait(0.015) until Enemy.Health <= TriggerHP.Value end
if anim then
if anim.Length <= 0 then repeat task.wait(0.015) until anim.Length > 0 end
anim:Play()
end
Enemy.Name = "BlockingEnemy"
task.wait(math.random(2, 5))
if anim then
anim:Stop()
end
Enemy.Name = "Enemy"
task.wait(math.random(Min.Value, Max.Value))
else
break
end
end
end
end)
Enemy.HealthChanged:Connect(function()
Billboard.MobHealthBar.HealthText.Text = Enemy.Health.." / ".._M.MobHealth
TS:Create(Billboard.MobHealthBar.Fill, TweenInfo.new(0.1, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), {Size = UDim2.fromScale(math.floor((Enemy.Health / _M.MobHealth) * 1000)/1000, 1)}):Play()
end)
Enemy.Died:Connect(function()
local clock = os.clock()
if Mob:FindFirstChild("PlayerTag") then
if Mob.PlayerTag.Value then
local plr = Mob.PlayerTag.Value
local gold = DS("Gold", plr)
local xp = DS("XP", plr)
local kills = DS("Kills", plr)
gold:Increment(_M.AwardedGold, plr.leaderstats.Gold.Value)
xp:Increment(_M.AwardedXP, plr.otherstats.XP.Value)
kills:Increment(1, plr.otherstats.Kills.Value)
if _M.DropsWeapon == true then
for k, v in pairs(_M.WeaponList) do
if _M.WeaponDirectory:FindFirstChild(k) then
if Random.new(tick()):NextInteger(1, v) == 1 then
if not plr.Backpack:FindFirstChild(k) and not plr.StarterGear:FindFirstChild(k) then
_M.WeaponDirectory[k]:Clone().Parent = plr.Backpack
_M.WeaponDirectory[k]:Clone().Parent = plr.StarterGear
end
end
end
end
end
end
end
task.spawn(function()
for i, v in ipairs(Mob:GetDescendants()) do
if v:IsA("Motor6D") then
local a0, a1 = Instance.new("Attachment"), Instance.new("Attachment")
a0.CFrame, a1.CFrame = v.C0, v.C1
a0.Parent, a1.Parent = v.Part0, v.Part1
local s = Instance.new("BallSocketConstraint")
s.Attachment0, s.Attachment1 = a0, a1
s.LimitsEnabled = true
s.TwistLimitsEnabled = true
s.Parent = v.Parent
v:Destroy()
end
end
end)
if _M.DoesMobTeleportAfterKill == true and Mob:FindFirstChild("PlayerTag") then
task.wait(0.5)
local plr = Mob.PlayerTag.Value
local chr = workspace.Players:WaitForChild(plr.Name)
if chr and chr:FindFirstChild("HumanoidRootPart") then
chr.HumanoidRootPart.CFrame = _M.TeleportLocation
end
end
local timeleft = os.clock() - clock
task.wait(_M.RespawnTime - timeleft)
MobClone.Parent = Mob.Parent
Mob:Destroy()
end)
Billboard.MobName.Text = _M.MobName.." (Lv. "..tostring(_M.MobLevel)..")"
Billboard.MobRank.Text = _M.IsMobRanked and "[".._M.RankName.."]" or "[Regular]"
Mob.Torso.Touched:Connect(function(hit)
if PS:GetPlayerFromCharacter(hit.Parent) and not DamageM and not hit.Parent:FindFirstChildWhichIsA("ForceField", true) and Enemy.Health > 0 then
DamageM = true
hit.Parent.Humanoid.Health -= _M.MobDamage / 3
task.spawn(function()
local anim = Animator:LoadAnimation(Mob.HitAnim)
if anim.Length <= 0 then repeat task.wait(0.015) until anim.Length > 0 end
anim:Play()
end)
task.wait(1)
DamageM = false
end
end)
Mob["Right Arm"].Touched:Connect(function(hit)
if PS:GetPlayerFromCharacter(hit.Parent) and not DamageR and not hit.Parent:FindFirstChildWhichIsA("ForceField", true) and Enemy.Health > 0 then
DamageR = true
hit.Parent.Humanoid.Health -= _M.MobDamage / 3
task.spawn(function()
local anim = Animator:LoadAnimation(Mob.HitAnim)
if anim.Length <= 0 then repeat task.wait(0.015) until anim.Length > 0 end
anim:Play()
end)
task.wait(1)
DamageR = false
end
end)
Mob["Left Leg"].Touched:Connect(function(hit)
if PS:GetPlayerFromCharacter(hit.Parent) and not DamageL and not hit.Parent:FindFirstChildWhichIsA("ForceField", true) and Enemy.Health > 0 then
DamageL = true
hit.Parent.Humanoid.Health -= _M.MobDamage / 3
task.spawn(function()
local anim = Animator:LoadAnimation(Mob.HitAnim)
if anim.Length <= 0 then repeat task.wait(0.015) until anim.Length > 0 end
anim:Play()
end)
task.wait(1)
DamageL = false
end
end)
task.spawn(function()
while true do
repeat task.wait(0.015) until findNearestTorso(Torso.Position)
local target = findNearestTorso(Torso.Position)
if target then
Enemy:MoveTo(target.Position, target)
end
task.wait(_M.FollowDelay)
end
end)
end
local plr = PS.PlayerAdded:Wait()
plr.CharacterAdded:Wait()
for i, v in ipairs(Mobs:GetChildren()) do
for i, e in ipairs(v:GetChildren()) do
mobhandle(e)
end
v.ChildAdded:Connect(function(e)
mobhandle(e)
end)
end
sadly i just can’t understand how to use collection service and all of my attempts at using it failed even though i feel like it can help.