Files
wnsrc/gamemodes/darkrp/plugins/weaponbalance/sh_plugin.lua
lifestorm df294d03aa Upload
2024-08-04 23:54:45 +03:00

345 lines
13 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

--[[
| 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/
--]]
PLUGIN.name = "Weapon Balance"
PLUGIN.author = "Gr4Ss & M!NT"
PLUGIN.description = "Changes the way damage is applied and allows weapons their damage to be rebalanced to be more RP appropriate."
ix.weapons = ix.weapons or {}
ix.weapons.messageTypes = {
["WEAPON_DAMAGE"] = 1,
["ARMOR_DAMAGE"] = 2,
["ARMOR_HALF_DAMAGE"] = 3,
["ARMOR_BREAK"] = 4
}
ix.config.Add("weaponBalanceDebugOutput", false, "Print output parameters for weapon balance.", nil, {
category = "Weapon Balance"
})
ix.config.Add("weaponBalanceDebugRolls", false, "Print rolls results for weapon balance.", nil, {
category = "Weapon Balance"
})
ix.config.Add("corpseMax", 8, "Maximum number of corpses that are allowed to be spawned.", nil, {
data = {min = 0, max = 20},
category = "Persistent Corpses"
})
ix.config.Add("npcArmorPenetration", 0.5, "Percentage of NPC damage which penetrates armor.", nil, {
data = {min = 0, max = 1, decimals = 2},
category = "Weapon Balance"
})
ix.config.Add("defaultArmorPenetration", 0.4, "Percentage of damage which penetrates armor when not specified by the item's configuration.", nil, {
data = {min = 0, max = 1, decimals = 2},
category = "Weapon Balance"
})
ix.config.Add("corpseDecayTime", 60, "How long it takes for a corpse to decay in seconds. Set to 0 to never decay.", nil, {
data = {min = 0, max = 1800},
category = "Persistent Corpses"
})
ix.option.Add("showAdditionalDamageInfo", ix.type.bool, false, {
category = "notice"
})
ix.option.Add("showDamageInfoChat", ix.type.bool, true, {
category = "notice"
})
ix.lang.AddTable("english", {
optShowAdditionalDamageInfo = "Ekstra Silah Hasarı Bilgisini Göster",
optdShowAdditionalDamageInfo = "Silah hasar sonucunuz hakkında ekstra bilgi gösterir: kritik şansınız, cezalarınız ve alınan bonuslar. Uyarı: sohbet-spam!",
optShowDamageInfoChat = "Sohbette Hasar Bilgilerini Göster",
optdShowDamageInfoChat = "Hasar bilgisini sohbette gösterir. Devre dışı bırakılırsa, hasar bilgisi bunun yerine konsola yazdırılır."
})
ix.lang.AddTable("spanish", {
optShowAdditionalDamageInfo = "Enseña más Información sobre el Daño del Arma",
optdShowDamageInfoChat = "Muestra la información sobre el daño en el chat. Si se desactiva, la información sobre el daño aparecerá en la consola.",
optShowDamageInfoChat = "Muestra Información de Daño en el chat",
optdShowAdditionalDamageInfo = "Muestra información extra sobre el resultado de daño de un arma: Tu posibilidad de crítico, penalizaciones y bonus. Cuidado: ¡Chat spam!"
})
do
local CLASS = {}
local iconOrange = ix.util.GetMaterial("willardnetworks/chat/gun_orange.png")
local iconRed = ix.util.GetMaterial("willardnetworks/chat/gun_red.png")
local orange = Color(255, 144, 0)
local orangeAlt = Color(255, 171, 62)
local orangeAlt2 = Color(255, 197, 122)
local red = Color(217, 83, 83)
local redAlt = Color(150, 83, 83)
if (CLIENT) then
function CLASS:OnChatAdd(speaker, text, anonymous, data)
if (!data.messageType) then return end
local icon = data.bCrit and iconRed or iconOrange
local color = orange
local critText = data.bCrit and "critically hit " or "hit "
local targetText = ((!IsValid(data.target) or data.target:IsPlayer()) and "your target") or data.target:GetClass()
local hitBoxText = (data.hitBox and " in the "..data.hitBox) or ""
local range = data.range == -1 and "" or " at "..data.range.." meters"
local suffix = ""
if (data.messageType == ix.weapons.messageTypes.WEAPON_DAMAGE) then
color = data.bCrit and red or orange
suffix = ", dealing "..data.damage.." damage"
elseif (data.messageType == ix.weapons.messageTypes.ARMOR_DAMAGE) then
color = data.bCrit and orangeAlt or orangeAlt2
suffix = ", dealing "..data.damage.." damage to their armor"
elseif (data.messageType == ix.weapons.messageTypes.ARMOR_HALF_DAMAGE) then
color = data.bCrit and orangeAlt or orangeAlt2
suffix = ", dealing "..data.damage.." damage, and dealing "..math.Round(data.damage / 2).." damage to their armor"
elseif (data.messageType == ix.weapons.messageTypes.ARMOR_BREAK) then
color = data.bCrit and red or redAlt
suffix = ", breaking their armor"
end
local punctuation = data.bCrit and "!" or "."
local finalText1 = table.concat({
"You ", critText, targetText, range, hitBoxText, suffix, punctuation
})
if (ix.option.Get("showDamageInfoChat")) then
chat.AddText(icon, color, finalText1)
else
MsgC(color, finalText1, "\n")
end
if (ix.option.Get("showAdditionalDamageInfo")) then
local penalties, bonus = {}, {}
if (bit.band(data.penalties, 1) == 1) then penalties[#penalties + 1] = "bodypart hit range" end
if (bit.band(data.penalties, 2) == 2) then penalties[#penalties + 1] = "target armor" end
if (bit.band(data.penalties, 4) == 4) then penalties[#penalties + 1] = "gun skill" end
if (bit.band(data.penalties, 8) == 8) then penalties[#penalties + 1] = "skill effective range" end
if (bit.band(data.penalties, 16) == 16) then penalties[#penalties + 1] = "gun effective range" end
if (bit.band(data.penalties, 32) == 32) then penalties[#penalties + 1] = "gun aim penalty" end
if (bit.band(data.penalties, 64) == 64) then penalties[#penalties + 1] = "target speed/movement" end
if (bit.band(data.penalties, 128) == 128) then penalties[#penalties + 1] = "melee skill" end
if (bit.band(data.bonus, 1) == 1) then bonus[#bonus + 1] = "bodypart hit range" end
if (bit.band(data.bonus, 4) == 4) then bonus[#bonus + 1] = "gun skill" end
if (bit.band(data.bonus, 8) == 8) then bonus[#bonus + 1] = "skill effective range" end
if (bit.band(data.bonus, 128) == 128) then bonus[#bonus + 1] = "melee skill" end
local finalText2 = table.concat({
"Final crit chance: ", math.Clamp(math.Round(data.calcCrit * 100), 0, 100), "%",
" | Penalties: ", (#penalties > 0 and table.concat(penalties, ", ")) or "none",
" | Bonus: ", (#bonus > 0 and table.concat(bonus, ", ")) or "none"
}, "")
if (ix.option.Get("showDamageInfoChat")) then
chat.AddText(icon, color, finalText2)
else
MsgC(color, finalText2, "\n")
end
end
end
end
ix.chat.Register("weapon_damage", CLASS)
end
ix.util.Include("sv_hooks.lua")
ix.util.Include("sv_util.lua")
ix.util.Include("sv_plugin.lua")
--PLUGIN:RegisterHitBox(hitBox, minRange, minRangeVal, maxRange, maxRangeVal, critAdjust, hitAdjust)
-- How to Modify damage, plz help. I was told the below does, but it doesn't affect the damage modifiers!!! @Gr4Ss
-- ^^ nvm I fix it :) - M!NT
ix.weapons:RegisterHitBox(HITGROUP_HEAD, 40, 0.1, 85, 0.05, 1.25, 1.0)
-- CENTER OF MASS
ix.weapons:RegisterHitBox(HITGROUP_CHEST, 40, 0.3, 85, 0.2, 1.1, 1.0)
ix.weapons:RegisterHitBox(HITGROUP_STOMACH, 40, 0.4, 85, 0.3, 1.1, 1.0)
ix.weapons:RegisterHitBox(HITGROUP_GENERIC, 40, 0.5, 85, 0.4, 1.1, 0.9)
ix.weapons:RegisterHitBox(HITGROUP_GEAR, 40, 0.5, 85, 0.4, 0.9, 0.7)
-- ARM
ix.weapons:RegisterHitBox(HITGROUP_LEFTARM, 40, 0.3, 85, 0.2, 0.9, 0.7)
ix.weapons:RegisterHitBox(HITGROUP_RIGHTARM, 40, 0.3, 85, 0.2, 0.9, 0.7)
-- LEG
ix.weapons:RegisterHitBox(HITGROUP_LEFTLEG, 40, 0.3, 85, 0.2, 0.9, 0.7)
ix.weapons:RegisterHitBox(HITGROUP_RIGHTLEG, 40, 0.3, 85, 0.2, 0.9, 0.7)
ix.weapons:RegisterWeaponCat("pistol", {
name = "Pistol",
baseDamage = 9,
armorPen = 0.2,
numShots = 3,
noSkillMod = 0.8,
minSkill = 0,
maxSkill = 20,
maxSkillMod = 1.1,
pointBlankMod = 1,
minEffRange = 0,
effRange = 40,
maxEffRange = 75
})
ix.weapons:RegisterWeaponCat("revolver", {
name = "Revolver",
baseDamage = 28,
armorPen = 0.4,
numShots = 1,
noSkillMod = 0.7,
minSkill = 0,
maxSkill = 30,
maxSkillMod = 1.2,
pointBlankMod = 1,
minEffRange = 0,
effRange = 40,
maxEffRange = 80
})
ix.weapons:RegisterWeaponCat("smg", {
name = "SMG",
baseDamage = 9,
armorPen = 0.4,
numShots = 4,
noSkillMod = 0.7,
minSkill = 10,
maxSkill = 30,
maxSkillMod = 1.2,
pointBlankMod = 1,
minEffRange = 0,
effRange = 50,
maxEffRange = 100
})
ix.weapons:RegisterWeaponCat("assaultrifle", {
name = "Assault Rifle",
baseDamage = 17,
armorPen = 0.4,
numShots = 3,
noSkillMod = 0.5,
minSkill = 20,
maxSkill = 40,
maxSkillMod = 1.2,
pointBlankMod = 0.8,
minEffRange = 1,
effRange = 75,
maxEffRange = 150
})
ix.weapons:RegisterWeaponCat("dmr", {
name = "DMR",
baseDamage = 24,
armorPen = 0.45,
numShots = 2,
noSkillMod = 0.4,
minSkill = 20,
maxSkill = 50,
maxSkillMod = 1.2,
pointBlankMod = 0.6,
minEffRange = 2,
effRange = 125,
maxEffRange = 250
})
ix.weapons:RegisterWeaponCat("boltaction", {
name = "Bolt Action Rifle",
baseDamage = 61,
armorPen = 0.4,
numShots = 1,
noSkillMod = 0.4,
minSkill = 30,
maxSkill = 50,
maxSkillMod = 1.1,
pointBlankMod = 0.4,
minEffRange = 3,
effRange = 300,
maxEffRange = 500
})
ix.weapons:RegisterWeaponCat("shotgun", {
name = "Shotgun",
baseDamage = 11,
armorPen = 0.2,
numShots = 1,
noSkillMod = 0.8,
minSkill = 5,
maxSkill = 20,
maxSkillMod = 1,
pointBlankMod = 1,
minEffRange = 0,
effRange = 40,
maxEffRange = 80
})
ix.weapons:RegisterWeaponCat("lmg", {
name = "Light Machine Gun",
baseDamage = 10,
armorPen = 0.1,
numShots = 8,
noSkillMod = 0.3,
minSkill = 40,
maxSkill = 50,
maxSkillMod = 1,
pointBlankMod = 0.6,
minEffRange = 1,
effRange = 75,
maxEffRange = 150
})
--[[
hit/critical = (hitBoxCrit(range, hitBox) * armorPen(hitBox == torso/stomach, weaponCat)) * ((weaponAimSkill(gunSkill, weaponCat) * rangeAimSkill(gunSkill, range)) * effectiveRangeMod(range, weaponCat)) * dodge(victimSpeedSkill, isFFMoving, range)
(max 0.7 * (max 1)) * ((max 1.2 * max 1.2) * max 1) * max 1
-> Hit: damage = (damage * hitBoxDamageCritAdjustment(hitBox))
-> Miss: damage = (damage * hitBoxDamageHitAdjustment(hitBox))
data points:
HitBox (for every hitbox):
minRange -- below & up to minRange -> minRangeVal
minRangeVal -- val between 0-0.7
-- in between minRange & maxRange -> interpolate between inRangeVal & maxRangeVal
maxRange -- from maxRange & above -> maxRangeVal
maxRangeVal -- val between 0-0.7
WeaponCat (for every weapon category):
armorPen -- lower crit chance if hitting armor -> between 0-1
noSkillVal -- penalty for zero/no skill -> val between 0-1
-- in between 0 and minAimSkill -> interpolate between noSkillLevel and 1
minAimSkill -- level at which no penalty/bonus is given -> aka val = 1
maxAimSkill -- level at which maximum aimSkill bonus is given
maxSkillVal -- bonus given at/above maxAimSkill, val between 1-1.2
pointBlankMod -- val between 0 and 1
-- in between 0 and MinEffrange -> interpolate between pointBlankMod and 1
MinEffRange
-- in between MinEffRange and EffRange -> mod = 1
EffRange
-- in between EffRange and MaxEffRange -> interpolate between 1 and 0.2
MaxEffRange
GunSkill:
zeroEffRange -- Effective range at level 0
maxEffRange -- Effective range at level 50
-- below effective range = 1.2 bonus
-- between eff range and max range = interpolate between 1.2 and 1
-- above max range = max(interpolate between 1 and .., 0) (same scale as eff range to max range)
zeroMaxRange -- Max Effective range at level 0
maxMaxRange -- Max Effective range at level 50
Weapon (for every weapon):
category
]]
function PLUGIN:TFA_CanBash(weapon)
return false
end
for _, item in pairs(ix.item.list) do
if (item.balanceCat and ix.weapons) then
if (item.isMelee) then
ix.weapons:RegisterMeleeWeapon(item.class, item.balanceCat)
else
ix.weapons:RegisterWeapon(item.class, item.balanceCat)
end
ix.weapons:RegisterWeaponExceptions(item.class, item.baseDamage, item.armorPen, item.aimPenalty, item.numShots)
end
end