Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local Enemy = {}
- Enemy.__index = Enemy
- local Tag = "Enemy"
- --//Services
- local Players = game:GetService("Players")
- local ReplicatedStorage = game:GetService("ReplicatedStorage")
- local CollectionService = game:GetService("CollectionService")
- --//Paths
- local Modules = ReplicatedStorage:WaitForChild("Modules")
- local Util = Modules:WaitForChild("Util")
- local EnemySpawn = workspace:WaitForChild("CombatTesting"):WaitForChild("EnemySpawn")
- --//Modules
- local Janitor = require(Util:WaitForChild("Janitor"))
- local HumanoidList = require(script.Parent.Parent.HumanoidList)
- --//CONSTANTS
- local AGGRORANGE = 50 --How many studs away player needs to be for enemy to attack
- local ATTACK_DELAY = 2
- local KILL_RANGE = 2.5
- local ATTACK_DAMAGE = 20
- --//Private Vars
- local States = {
- "Searching";
- "Attack";
- }
- local AttackDebounce = false
- local function GetDistance(p1, p2)
- return (p1.Position - p2.Position).magnitude
- end
- local function GetClosestVisibleTarget(enemy, targets, blacklist)
- --NOTE WE MAY NOT NEED BLACKLIST SO STOP COLLECTING IT
- local distances = {}
- for _, char in ipairs(targets) do
- if CollectionService:HasTag(char, Tag) then continue end
- distances[char] = GetDistance(enemy.PrimaryPart, char.PrimaryPart)
- end
- local low = math.huge
- local index
- for i, v in pairs(distances) do
- if v < low then
- low = v
- index = i
- end
- end
- return index
- end
- --//Enemy Functions/Methods
- function Enemy.new(instance)
- local self = setmetatable({}, Enemy)
- self._janitor = Janitor.new()
- self.Instance = instance
- self.Humanoid = instance.Humanoid
- return self
- end
- function Enemy:Attack()
- if self.Instance == nil then warn("An instance is required in order for the enemy to attack.") return end
- if self.Target == nil then warn("A target is required in order for the enemy to attack.") end
- self.State = States[2]
- local function takeDMG()
- while true do
- self.Humanoid:MoveTo(self.Target.HumanoidRootPart.Position)
- self.Humanoid.MoveToFinished:Wait()
- local plr = Players:GetPlayerFromCharacter(self.Target)
- if not plr then return end
- local distance = (self.Instance.HumanoidRootPart.Position - self.Target.HumanoidRootPart.Position).magnitude
- if distance <= KILL_RANGE then
- local playerDefense = plr:GetAttribute("Defense")
- if playerDefense then
- local hp = self.Target.Humanoid.Health
- local amt = (playerDefense * hp)
- self.Target.Humanoid:TakeDamage(amt)
- AttackDebounce = true
- else
- self.Target.Humanoid:TakeDamage(20)
- AttackDebounce = true
- end
- task.wait(ATTACK_DELAY)
- end
- end
- end
- task.spawn(takeDMG)
- local distance = (self.Instance.HumanoidRootPart.Position - self.Target.HumanoidRootPart.Position).magnitude
- if distance > AGGRORANGE then
- self:PrimeForAttack()
- end
- end
- function Enemy:PrimeForAttack()
- local keepGoing = true
- if self.Instance then
- while keepGoing do
- -- Get list of all nearby enemies and non-enemy humanoids
- -- Enemy list is used to ignore other enemies during later detection
- local humanoids = HumanoidList:GetCurrent()
- local friendlies = {}
- local characters = {}
- for _, object in pairs(humanoids) do
- if object and object.Parent and object.Parent:FindFirstChild("HumanoidRootPart") and object.Health > 0 and object.WalkSpeed > 0 then
- local torso = object.Parent:FindFirstChild("HumanoidRootPart")
- if torso then
- local plr = Players:GetPlayerFromCharacter(object.Parent)
- if plr then
- local distance = (self.Instance.HumanoidRootPart.Position - torso.Position).magnitude
- if distance <= AGGRORANGE then
- if CollectionService:HasTag(object, Tag) then
- table.insert(friendlies, object.Parent)
- else
- table.insert(characters, object.Parent)
- end
- end
- end
- end
- end
- end
- local target = GetClosestVisibleTarget(self.Instance, characters, friendlies)
- if target then
- keepGoing = false
- self.Target = target
- self:Attack()
- else
- self.Humanoid:MoveTo(EnemySpawn.Position)
- end
- task.wait(3)
- end
- end
- end
- function Enemy:Init()
- print("Enemy was initialized")
- self.State = States[1]
- self:PrimeForAttack()
- end
- return Enemy
Advertisement
RAW Paste Data
Copied
Advertisement