103 lines
3.6 KiB
Plaintext
103 lines
3.6 KiB
Plaintext
--[[
|
|
Evercyan @ March 2023
|
|
DamageLib
|
|
|
|
DamageLib houses code relating to damage for weapons, and any additional sources of damage
|
|
you may add to your game. It is recommended to have all code for damage run through here for consistency.
|
|
|
|
If you're looking to adjust crit multiplier, gamepass rewards (ex. x3 damage), etc, you can do this under DamageLib:DamageMob().
|
|
]]
|
|
|
|
--> Services
|
|
local CollectionService = game:GetService("CollectionService")
|
|
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
|
local ServerStorage = game:GetService("ServerStorage")
|
|
|
|
--> Dependencies
|
|
local Mobs = require(ServerStorage.Modules.MobLib.MobList)
|
|
|
|
--> Variables
|
|
local DamageCd = {}
|
|
local Random = Random.new()
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
local DamageLib = {}
|
|
|
|
function DamageLib:TagMobForDamage(Player: Player, Mob, Damage: number)
|
|
if Mob.isDead then return end
|
|
|
|
local PlayerTags = Mob.Instance:FindFirstChild("PlayerTags")
|
|
if not PlayerTags then
|
|
PlayerTags = Instance.new("Configuration")
|
|
PlayerTags.Name = "PlayerTags"
|
|
PlayerTags.Parent = Mob.Instance
|
|
end
|
|
|
|
local ExistingTag = PlayerTags:GetAttribute(Player.UserId)
|
|
if ExistingTag then
|
|
PlayerTags:SetAttribute(Player.UserId, ExistingTag + Damage)
|
|
else
|
|
PlayerTags:SetAttribute(Player.UserId, Damage)
|
|
end
|
|
end
|
|
|
|
function DamageLib:DamageMob(Player: Player, Mob): number?
|
|
if Mob.isDead then return end
|
|
|
|
local pData = ReplicatedStorage.PlayerData:FindFirstChild(Player.UserId)
|
|
local Level = pData and pData:FindFirstChild("Stats") and pData.Stats:FindFirstChild("Level")
|
|
if not Level or (Level.Value < Mob.Config.Level[2]) then
|
|
return
|
|
end
|
|
|
|
-- Make sure the equipped tool can be found, so we can safely grab the damage from it.
|
|
-- Never pass damage as a number through a remote, as the client can manipulate this data.
|
|
local Character = Player.Character
|
|
local Tool = Character and Character:FindFirstChildOfClass("Tool")
|
|
local ItemConfig = Tool and Tool:FindFirstChild("ItemConfig") and require(Tool.ItemConfig)
|
|
if not ItemConfig or not ItemConfig.Damage then return end
|
|
|
|
-- Damage Cooldown
|
|
if DamageCd[Player.UserId] then return end
|
|
DamageCd[Player.UserId] = true
|
|
task.delay(ItemConfig.Cooldown - 0.03, function() -- We subtract just a tad so inconsistencies with timing on the client (ie. time to raycast) is less likely to stop a hit from going through
|
|
DamageCd[Player.UserId] = nil
|
|
end)
|
|
|
|
-- Calculate damage
|
|
local Damage = typeof(ItemConfig.Damage) == "table" and Random:NextInteger(unpack(ItemConfig.Damage)) or ItemConfig.Damage
|
|
local isCrit = Random:NextInteger(1, 10) == 1
|
|
|
|
if isCrit then
|
|
Damage *= 2
|
|
end
|
|
|
|
self:TagMobForDamage(Player, Mob, Damage)
|
|
Mob.Enemy.Health = math.clamp(Mob.Enemy.Health - Damage, 0, Mob.Enemy.MaxHealth)
|
|
ReplicatedStorage.Remotes.PlayerDamagedMob:FireClient(Player, Mob.Instance, Damage)
|
|
|
|
return Damage
|
|
end
|
|
|
|
ReplicatedStorage.Remotes.DamageMob.OnServerInvoke = function(Player, MobInstance: Model)
|
|
if MobInstance and typeof(MobInstance) == "Instance" and CollectionService:HasTag(MobInstance, "Mob") then
|
|
local Mob = Mobs[MobInstance]
|
|
|
|
if Mob then
|
|
-- Follow
|
|
local Enemy = Mob.Instance:FindFirstChild("Enemy")
|
|
if Enemy and (not Enemy.WalkToPart or not Enemy.WalkToPart:IsDescendantOf(Player.Character)) then
|
|
local HumanoidRootPart = Mob.Instance:FindFirstChild("HumanoidRootPart")
|
|
if HumanoidRootPart then
|
|
HumanoidRootPart.Anchored = false
|
|
HumanoidRootPart:SetNetworkOwner(Player)
|
|
Enemy:MoveTo(Player.Character:GetPivot().Position)
|
|
end
|
|
end
|
|
return DamageLib:DamageMob(Player, Mob)
|
|
end
|
|
end
|
|
end
|
|
|
|
return DamageLib |