zombiesurvival-evolved/gamemodes/zombiesurvival/gamemode/sh_weaponquality.lua

290 lines
11 KiB
Lua
Raw Permalink Normal View History

GM.WeaponQualityModifiers = {}
GM.WeaponQualities = {
{"Sturdy", 1.09, "Tuned"},
{"Honed", 1.19, "Modified"},
{"Perfected", 1.35, "Reformed"}
}
GM.WeaponQualityColors = {
{Color(235, 235, 115), Color(172, 219, 105)},
{Color(50, 90, 175), Color(35, 110, 145)},
{Color(160, 95, 235), Color(252, 100, 100)}
}
WEAPON_MODIFIER_MIN_SPREAD = 1
WEAPON_MODIFIER_MAX_SPREAD = 2
WEAPON_MODIFIER_FIRE_DELAY = 3 -- Rounds up based on tick rate.
WEAPON_MODIFIER_RELOAD_SPEED = 4
WEAPON_MODIFIER_CLIP_SIZE = 5
WEAPON_MODIFIER_MELEE_RANGE = 6
WEAPON_MODIFIER_MELEE_SIZE = 7
WEAPON_MODIFIER_MELEE_IMPACT_DELAY = 8
WEAPON_MODIFIER_PROJECTILE_VELOCITY = 9
WEAPON_MODIFIER_SHORT_TEAM_HEAT = 10
WEAPON_MODIFIER_SHOT_COUNT = 11
WEAPON_MODIFIER_BULLET_PIERCES = 12
WEAPON_MODIFIER_MAXIMUM_MINES = 13
WEAPON_MODIFIER_MAX_DISTANCE = 14
WEAPON_MODIFIER_AURA_RADIUS = 15
WEAPON_MODIFIER_RECOIL = 16
WEAPON_MODIFIER_DAMAGE = 17
WEAPON_MODIFIER_HEALRANGE = 18
WEAPON_MODIFIER_HEALCOOLDOWN = 19
WEAPON_MODIFIER_BUFF_DURATION = 20
WEAPON_MODIFIER_LEG_DAMAGE = 21
WEAPON_MODIFIER_REPAIR = 22
WEAPON_MODIFIER_TURRET_SPREAD = 23
WEAPON_MODIFIER_HEALING = 24
WEAPON_MODIFIER_HEADSHOT_MULTI = 25
WEAPON_MODIFIER_MELEE_KNOCK = 26
local index = 1
function GM:AddWeaponQualityModifier(id, name, displayraw, vartable)
local datatab = {Name = name, DisplayRaw = displayraw, VarTable = vartable}
self.WeaponQualityModifiers[id] = datatab
index = index + 1
return datatab
end
function GM:SetPrimaryWeaponModifier(swep, modifier, amount)
swep.PrimaryRemantleModifier = {Modifier = modifier, Amount = amount}
end
function GM:AttachWeaponModifier(swep, modifier, amount, qualitystart)
if not swep.AltRemantleModifiers then swep.AltRemantleModifiers = {} end
local datatab = {Amount = amount, QualityStart = qualitystart or 2}
swep.AltRemantleModifiers[modifier] = datatab
end
function GM:AddNewRemantleBranch(swep, no, printname, desc, branchfunc)
if not swep.Branches then swep.Branches = {} end
local datatab = {PrintName = printname, Desc = desc, BranchFunc = branchfunc}
swep.Branches[no] = datatab
return datatab
end
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_MIN_SPREAD, "Minimum Spread", false, {ConeMin = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_MAX_SPREAD, "Maximum Spread", false, {ConeMax = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_FIRE_DELAY, "Fire Delay", false, {Delay = true})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_RELOAD_SPEED, "Reload Speed", false, {ReloadSpeed = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_CLIP_SIZE, "Clip Size", true, {ClipSize = true}).ReqClip = true
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_MELEE_RANGE, "Melee Range", false, {MeleeRange = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_MELEE_SIZE, "Melee Size", false, {MeleeSize = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_MELEE_IMPACT_DELAY, "Melee Impact Delay", false, {SwingTime = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_PROJECTILE_VELOCITY, "Projectile Velocity", false, {ProjVelocity = true})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_SHORT_TEAM_HEAT, "Short Team Heat", false, {HeatBuildShort = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_SHOT_COUNT, "Shot Count", true, {NumShots = true})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_BULLET_PIERCES, "Bullet Pierces", true, {Pierces = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_MAXIMUM_MINES, "Maximum Mines", true, {MaxMines = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_MAX_DISTANCE, "Maximum Distance", false, {MaxDistance = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_AURA_RADIUS, "Aura Detection Radius", false, {AuraRange = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_RECOIL, "Recoil", false, {Recoil = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_DAMAGE, "Damage", false, {Damage = true, MeleeDamage = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_HEALRANGE, "Heal Range", false, {HealRange = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_HEALCOOLDOWN, "Healing Cooldown", false, {Delay = true})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_BUFF_DURATION, "Buff Duration", false, {BuffDuration = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_LEG_DAMAGE, "Slow Strength", false, {LegDamage = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_REPAIR, "Repair Strength", false, {Repair = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_TURRET_SPREAD, "Turret Bullet Spread", false, {TurretSpread = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_HEALING, "Healing Amount", false, {Heal = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_HEADSHOT_MULTI, "Headshot Damage Bonus", false, {HeadshotMulti = false})
GM:AddWeaponQualityModifier(WEAPON_MODIFIER_MELEE_KNOCK, "Knockback", false, {MeleeKnockBack = false})
local function ApplyWeaponModifier(modinfo, wept, datatab, remantledescs, i)
local displayed = false
local mtbl, basestat, newstat, qfactor
for var, isprimary in pairs(modinfo.VarTable) do
mtbl = isprimary and wept.Primary or wept
if mtbl[var] then
qfactor = i - (datatab.QualityStart - 1)
basestat = mtbl[var]
newstat = basestat + datatab.Amount * qfactor
mtbl[var] = newstat
if not displayed and qfactor > 0 then
local ispos = datatab.Amount > 0 and "+" or ""
local statincdesc = not modinfo.DisplayRaw and (((math.Round(newstat/basestat, 2)-1) * 100).. "% ")
or ((datatab.Amount * qfactor / (modinfo.ReqClip and wept.RequiredClip or 1)).. " ")
table.insert(remantledescs, ispos .. statincdesc .. modinfo.Name)
displayed = true
end
end
end
end
local function CreateQualityKillicon(oldc, newc, i, b, cols)
local kitbl = killicon.Get(oldc)
if kitbl then
local kifunc = #kitbl == 2 and killicon.Add or killicon.AddFont
local nkitbl = table.Copy(kitbl)
nkitbl[#kitbl] = cols and cols[i] or GAMEMODE.WeaponQualityColors[i][b and b+1 or 1]
kifunc(newc, unpack(nkitbl))
end
end
function GM:CreateWeaponOfQuality(i, orig, quality, classname, branch)
orig.RemantleDescs[branch and branch.No or 0][i] = {}
-- Doing it with a full copy prevents crash issues on scoped weapons.
-- TODO: Refactor me to not use the full weapon class once all self.BaseClass calls have been removed
local wept = weapons.Get(classname)
local remantledescs = orig.RemantleDescs[branch and branch.No or 0][i]
wept.BaseQuality = classname
wept.QualityTier = i
wept.Branch = branch and branch.No
if wept.PrintName then
wept.PrintName = (branch and branch.NewNames and branch.NewNames[i] or branch and quality[3] or quality[1]).." "..(branch and branch.PrintName or wept.PrintName)
end
if wept.PrimaryRemantleModifier then
local primod = wept.PrimaryRemantleModifier
ApplyWeaponModifier(self.WeaponQualityModifiers[primod.Modifier], wept, {Amount = primod.Amount, QualityStart = 1}, remantledescs, i)
else
if wept.Primary and wept.Primary.Damage then
wept.Primary.Damage = wept.Primary.Damage * quality[2]
end
if wept.MeleeDamage then
wept.MeleeDamage = wept.MeleeDamage * quality[2]
end
table.insert(remantledescs, "+" .. ((quality[2]-1) * 100) .. "% " .. "Damage")
end
if wept.AltRemantleModifiers then
for modifier, datatab in pairs(wept.AltRemantleModifiers) do
if modifier == "BaseClass" then continue end -- ???
ApplyWeaponModifier(self.WeaponQualityModifiers[modifier], wept, datatab, remantledescs, i)
end
end
if branch and branch.BranchFunc then
table.insert(remantledescs, 1, branch.Desc)
branch.BranchFunc(wept)
end
local newclass = self:GetWeaponClassOfQuality(classname, i, branch and branch.No)
if CLIENT then
CreateQualityKillicon(branch and branch.Killicon or classname, newclass, i, branch and branch.No, branch and branch.Colors)
end
local regscriptent = function(class, cbk, prefix)
local newent = self:GetWeaponClassOfQuality(class, i)
local afent = scripted_ents.Get((prefix or "") .. class)
if cbk then cbk(afent, newent) end
scripted_ents.Register(afent, (prefix or "") .. newent)
return newent
end
if wept.DeployClass then
wept.DeployClass = regscriptent(wept.DeployClass, function(ent, newcl)
if CLIENT then
CreateQualityKillicon(wept.DeployClass, newcl, i)
end
if self.DeployableInfo[wept.DeployClass] then
self:AddDeployableInfo(newcl, quality[1].." "..self.DeployableInfo[wept.DeployClass].Name, "")
end
end)
if wept.AmmoIfHas then
local newammo = self:GetWeaponClassOfQuality(wept.Primary.Ammo, i)
game.AddAmmoType({name = newammo})
wept.Primary.Ammo = newammo
end
if wept.Channel then
table.insert(self.ChannelsToClass[wept.Channel], wept.DeployClass)
end
end
if wept.GhostStatus then wept.GhostStatus = regscriptent(wept.GhostStatus, function(ent)
if ent.GhostEntityWildCard then
ent.GhostEntityWildCard = ent.GhostEntity
end
local ghostent = self:GetWeaponClassOfQuality(ent.GhostEntity, i)
ent.GhostEntity = ghostent
ent.GhostWeapon = newclass
end, "status_") end
weapons.Register(wept, newclass)
end
function GM:CreateWeaponQualities()
local allweapons = weapons.GetList()
local classname
for _, t in ipairs(allweapons) do
classname = t.ClassName
if string.sub(classname, 1, 14) == "weapon_zs_base" then
continue
end
local wept = weapons.Get(classname)
if wept and wept.AllowQualityWeapons then
local orig = weapons.GetStored(classname)
orig.RemantleDescs = {}
orig.RemantleDescs[0] = {}
if orig.Branches then
for no, _ in pairs(orig.Branches) do
orig.RemantleDescs[no] = {}
end
end
for i, quality in ipairs(self.WeaponQualities) do
self:CreateWeaponOfQuality(i, orig, quality, classname)
if orig.Branches then
for no, tbl in pairs(orig.Branches) do
local ntbl = table.Copy(tbl)
ntbl.No = no
self:CreateWeaponOfQuality(i, orig, quality, classname, ntbl)
end
end
end
end
end
end
function GM:GetWeaponClassOfQuality(classname, quality, branch)
return classname.."_"..string.char(113 + (branch or 0))..quality
end
function GM:GetDismantleScrap(wtbl, invitem)
local itier = wtbl.Tier
local quatier = wtbl.QualityTier
local dismantlediv = invitem and 2 or 1
local baseval = invitem and GAMEMODE.ScrapValsTrinkets[itier or 1] or GAMEMODE.ScrapVals[itier or 1]
local qu = (quatier or 0) + 1
local basicvalue = baseval * GAMEMODE.DismantleMultipliers[qu] - ((quatier or itier) and 0 or 1)
return math.floor((basicvalue * (wtbl.IsMelee and 0.75 or 1)) / (wtbl.DismantleDiv or dismantlediv))
end
function GM:GetUpgradeScrap(wtbl, qualitychoice)
local itier = wtbl.Tier
return math.ceil(self.ScrapVals[itier or 1] * qualitychoice * (wtbl.IsMelee and 0.85 or 1))
end
function GM:PointsToScrap(points)
return points / (70 / 32)
end