mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 13:53:45 +03:00
Upload
This commit is contained in:
189
gamemodes/darkrp/plugins/weaponbalance/sv_plugin.lua
Normal file
189
gamemodes/darkrp/plugins/weaponbalance/sv_plugin.lua
Normal file
@@ -0,0 +1,189 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
local PLUGIN = PLUGIN
|
||||
|
||||
function ix.weapons:CalcCritChance(attackerChar, victim, range, hitBox, weaponClass)
|
||||
local attacker = attackerChar:GetPlayer()
|
||||
|
||||
if (!self.hitBoxList[hitBox]) then
|
||||
return 0, 0, 0
|
||||
end
|
||||
|
||||
local weaponCat = self.weaponList[weaponClass]
|
||||
if (!self.weaponCatList[weaponCat]) then
|
||||
return 0, 0, 0
|
||||
end
|
||||
|
||||
local hitBoxCrit = self:RemapClamp(range, self.hitBoxList[hitBox])
|
||||
local armorMod = (victim:IsPlayer() and victim:Armor() > 0 and self:GetArmorPen(weaponClass)) or 1
|
||||
local weaponSkillMod = self:GetWeaponSkillMod(attackerChar, weaponClass)
|
||||
local rangeSkillMod = self:GetRangeSkillMod(attackerChar, range)
|
||||
local effRangeMod = self:GetWeaponEffRangeMod(weaponClass, range)
|
||||
local aimPenalty = self:GetWeaponAimPenalty(weaponClass)
|
||||
local dodgeMod = 1
|
||||
if (victim:IsPlayer() and ix.fights and victim:GetFight() and victim:GetCharacter().fightInfoTable) then
|
||||
dodgeMod = (1 - 0.03 *
|
||||
(attackerChar:GetSkillScale("guns_moving_target_penalty")) * (victim:GetCharacter().fightInfoTable.movePointsSpend or 0) *
|
||||
(1 + victim:GetCharacter():GetSkillScale("speed_dodge_mod")))
|
||||
end
|
||||
|
||||
ix.log.Add(attacker, "weaponBalanceDebugOutput", hitBoxCrit, armorMod, weaponSkillMod, rangeSkillMod, effRangeMod, dodgeMod)
|
||||
local penalties, bonus = 0, 0
|
||||
if (hitBoxCrit < 0.60) then penalties = bit.bor(penalties, 1) elseif (hitBoxCrit >= 0.65) then bonus = bit.bor(bonus, 1) end
|
||||
if (armorMod < 0.85) then penalties = bit.bor(penalties, 2) end
|
||||
if (weaponSkillMod < 1) then penalties = bit.bor(penalties, 4) elseif (weaponSkillMod >= 1.1) then bonus = bit.bor(bonus, 4) end
|
||||
if (rangeSkillMod < 1) then penalties = bit.bor(penalties, 8) elseif (rangeSkillMod >= 1.1) then bonus = bit.bor(bonus, 8) end
|
||||
if (effRangeMod < 0.85) then penalties = bit.bor(penalties, 16) end
|
||||
if (aimPenalty < 1) then penalties = bit.bor(penalties, 32) end
|
||||
if (dodgeMod < 0.85) then penalties = bit.bor(penalties, 64) end
|
||||
|
||||
return hitBoxCrit * armorMod * weaponSkillMod * rangeSkillMod * effRangeMod * aimPenalty * dodgeMod, penalties, bonus
|
||||
end
|
||||
|
||||
function ix.weapons:CalcMeleeCritChance(attackerChar, victim, weaponClass)
|
||||
local attacker = attackerChar:GetPlayer()
|
||||
local baseCrit = self:GetMeleeWeaponBaseHitChance(attackerChar, weaponClass)
|
||||
local armorMod = (victim:IsPlayer() and victim:Armor() > 0 and self:GetMeleeArmorPen(weaponClass)) or 1
|
||||
local dodgeMod = 1
|
||||
if (victim:IsPlayer() and ix.fights and victim:GetFight() and victim:GetCharacter().fightInfoTable) then
|
||||
local movePoints = victim:GetCharacter().fightInfoTable.movePointsSpend or 0
|
||||
if (movePoints >= 8) then
|
||||
dodgeMod = 0.5
|
||||
elseif (movePoints >= 4) then
|
||||
dodgeMod = 0.75
|
||||
end
|
||||
end
|
||||
|
||||
ix.log.Add(attacker, "weaponMeleeBalanceDebugOutput", baseCrit, armorMod, dodgeMod)
|
||||
local penalties, bonus = 0, 0
|
||||
if (baseCrit < 0.1) then penalties = bit.bor(penalties, 128) elseif (baseCrit >= 0.3) then bonus = bit.bor(bonus, 128) end
|
||||
if (armorMod < 0.85) then penalties = bit.bor(penalties, 2) end
|
||||
if (dodgeMod < 0.85) then penalties = bit.bor(penalties, 64) end
|
||||
|
||||
return baseCrit * armorMod * dodgeMod, penalties, bonus
|
||||
end
|
||||
|
||||
function ix.weapons:BalanceDamage(victim, damage, attacker, hitgroup)
|
||||
local inflictor = damage:GetInflictor()
|
||||
if (!IsValid(inflictor)) then return end
|
||||
|
||||
if (inflictor.IsTFAWeapon and !inflictor.noDoubleDamageFix) then
|
||||
if (!attacker.ixCanDoDamage) then
|
||||
damage:SetDamage(0)
|
||||
return false
|
||||
else
|
||||
attacker.ixCanDoDamage = attacker.ixCanDoDamage - 1
|
||||
if (attacker.ixCanDoDamage == 0) then
|
||||
attacker.ixCanDoDamage = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (inflictor:IsPlayer()) then
|
||||
inflictor = inflictor:GetActiveWeapon()
|
||||
end
|
||||
|
||||
local weaponClass = inflictor:GetClass()
|
||||
if (IsValid(attacker:GetActiveWeapon()) and self:IsMelee(attacker:GetActiveWeapon():GetClass())) then
|
||||
weaponClass = attacker:GetActiveWeapon():GetClass()
|
||||
end
|
||||
|
||||
local range = -1
|
||||
local critChance, penalties, bonus, finalDamage, result
|
||||
local critRoll = math.random()
|
||||
if (!self:IsMelee(weaponClass)) then
|
||||
range = attacker:GetPos():Distance(victim:GetPos()) * 0.30 / 16
|
||||
critChance, penalties, bonus = self:CalcCritChance(attacker:GetCharacter(), victim, range, hitgroup, weaponClass)
|
||||
if (!critChance) then return end
|
||||
|
||||
result = critRoll < critChance and "crit" or "hit"
|
||||
local adjust = self.hitBoxDamageList[hitgroup] and self.hitBoxDamageList[hitgroup][result] or 0.9
|
||||
finalDamage = math.floor((self:GetWeaponBaseDamage(weaponClass) or damage:GetDamage()) * adjust)
|
||||
|
||||
if (victim:IsNPC() or victim:IsPlayer()) then
|
||||
if (result == "hit") then
|
||||
attacker:GetCharacter():DoAction("guns_hit")
|
||||
else
|
||||
attacker:GetCharacter():DoAction("guns_crit")
|
||||
end
|
||||
end
|
||||
else
|
||||
critChance, penalties, bonus = self:CalcMeleeCritChance(attacker:GetCharacter(), victim, weaponClass)
|
||||
if (!critChance) then return end
|
||||
|
||||
result = critRoll < critChance and "crit" or "hit"
|
||||
finalDamage = math.floor(self:GetMeleeWeaponBaseDamage(weaponClass, attacker:GetActiveWeapon().ixAttackType) * (result == "crit" and 1 or self:GetMeleeWeaponHitAdjsut(weaponClass)))
|
||||
|
||||
if (victim:IsNPC() or victim:IsPlayer()) then
|
||||
if (result == "hit") then
|
||||
attacker:GetCharacter():DoAction("melee_hit")
|
||||
else
|
||||
attacker:GetCharacter():DoAction("melee_crit")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ix.log.Add(attacker, "weaponBalanceDebugRolls", critChance, critRoll, string.utf8upper(result))
|
||||
|
||||
damage:SetDamage(finalDamage)
|
||||
|
||||
hook.Run("PostCalculatePlayerDamage", victim, damage, hitgroup)
|
||||
|
||||
if (victim:IsNPC() or victim:IsPlayer()) then
|
||||
ix.log.Add(attacker, "weaponBalanceResult", result, victim, hitgroup, math.Round(damage:GetDamage()), critChance)
|
||||
end
|
||||
|
||||
return true, result, range, critChance, penalties, bonus
|
||||
end
|
||||
|
||||
function ix.weapons:QueueDamageMessage(attacker, data)
|
||||
if (!self.dmgMessageQueue or !istable(self.dmgMessageQueue)) then
|
||||
self.dmgMessageQueue = {}
|
||||
end
|
||||
|
||||
local idx = tonumber(attacker:SteamID64())
|
||||
if (!self.dmgMessageQueue[idx]) then
|
||||
self.dmgMessageQueue[idx] = {}
|
||||
self.dmgMessageQueue[idx].lastIndex = 0
|
||||
self.dmgMessageQueue[idx].ply = attacker
|
||||
self.dmgMessageQueue[idx].stack = {}
|
||||
end
|
||||
|
||||
self.dmgMessageQueue[idx].stack[table.Count(self.dmgMessageQueue[idx].stack) + 1] = data
|
||||
end
|
||||
|
||||
timer.Create("ixDamageMessageStackConsumer", 0.25, 0, function()
|
||||
if (!ix.weapons.dmgMessageQueue or !istable(ix.weapons.dmgMessageQueue)) then return end
|
||||
|
||||
for i, queue in pairs(ix.weapons.dmgMessageQueue) do
|
||||
if (!queue.stack[queue.lastIndex + 1] or !IsValid(queue.ply)) then
|
||||
-- queue is drained
|
||||
ix.weapons.dmgMessageQueue[i] = nil
|
||||
continue
|
||||
end
|
||||
|
||||
local data = queue.stack[queue.lastIndex + 1]
|
||||
ix.chat.Send(queue.ply, "weapon_damage", "", false, queue.ply, {
|
||||
bCrit = data.bCrit,
|
||||
target = data.target,
|
||||
hitBox = data.hitBox,
|
||||
range = data.range,
|
||||
damage = data.damage,
|
||||
calcCrit = data.calcCrit,
|
||||
penalties = data.penalties,
|
||||
bonus = data.bonus,
|
||||
messageType = data.messageType
|
||||
})
|
||||
|
||||
queue.lastIndex = queue.lastIndex + 1
|
||||
end
|
||||
end)
|
||||
Reference in New Issue
Block a user