mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 13:53:45 +03:00
Upload
This commit is contained in:
458
gamemodes/ixhl2rp/plugins/arccwbase/sh_plugin.lua
Normal file
458
gamemodes/ixhl2rp/plugins/arccwbase/sh_plugin.lua
Normal file
@@ -0,0 +1,458 @@
|
||||
--[[
|
||||
| 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;
|
||||
|
||||
PLUGIN.name = "ArcCW Base";
|
||||
PLUGIN.description = "Adds compatibility with ArcCW, integrating the weapons and attachments with helix items. Also links ArcCW SWEPs spread, recoil and sway to characters \"gun\" skill.";
|
||||
PLUGIN.author = "Gr4Ss & LegAz";
|
||||
|
||||
if (!ArcCW) then return end
|
||||
|
||||
PLUGIN.attachmentTranslate = {}
|
||||
|
||||
for k, v in pairs(ArcCW.AttachmentTable) do
|
||||
local ITEM = ix.item.Register(k, nil, false, nil, true)
|
||||
ITEM.name = v.PrintName
|
||||
ITEM.category = "Attachment"
|
||||
ITEM.model = "models/props_lab/box01a.mdl"
|
||||
ITEM.description = "A box containing a "..v.PrintName.." attachment."
|
||||
end
|
||||
|
||||
ix.util.Include("sh_config.lua") -- moving config into another plugin just for visuals @offlegaz
|
||||
ix.util.Include("sv_plugin.lua")
|
||||
ix.util.Include("cl_plugin.lua")
|
||||
|
||||
ix.config.Add("forceUseMagazineSystem", true, "Should magazines be mandatory for item weapons, or is it OK to fall back to the Source ammo pool?", nil, {
|
||||
category = "general",
|
||||
})
|
||||
|
||||
if (CLIENT) then
|
||||
function ArcCW:PlayerTakeAtt(ply, att, amt) end
|
||||
|
||||
function ArcCW:PlayerGiveAtt(ply, att, amt) end
|
||||
end
|
||||
|
||||
ix.config.Add("shootDbLevelReduction", 0, "How many DB to reduce the ARCCW sound levels by (this effects how far away it can be heard).", nil, {
|
||||
data = {min = 1, max = 50, decimals = 1},
|
||||
category = "general"
|
||||
})
|
||||
|
||||
ix.config.Add("shootOtherDbLevelReduction", 50, "How many DB to reduce the ARCCW sound levels by (non gunshot sound effects).", nil, {
|
||||
data = {min = 1, max = 100, decimals = 1},
|
||||
category = "general"
|
||||
})
|
||||
|
||||
ix.config.Add("shootOtherVolumeLevelReduction", 0.5, "How much to reduce the ARCCW sound levels by (non gunshot sound effects).", nil, {
|
||||
data = {min = 0, max = 1, decimals = 3},
|
||||
category = "general"
|
||||
})
|
||||
|
||||
ix.config.Add("shootDbLevelReductionClose", 50, "How many DB to reduce the ARCCW sound levels by (this effects how far away close sounds can be heard).", nil, {
|
||||
data = {min = 1, max = 100, decimals = 1},
|
||||
category = "general"
|
||||
})
|
||||
|
||||
ix.config.Add("shootVolumeReduction", 0, "How much to reduce the ARCCW sound levels by (this effects how far loud it is).", nil, {
|
||||
data = {min = 0, max = 1, decimals = 3},
|
||||
category = "general"
|
||||
})
|
||||
|
||||
ix.config.Add("shootSoundDSP", 2, "Which DSP preset to use for close sounds (don't change this unless you know what you're doing!)", nil, {
|
||||
data = {min = 0, max = 140, decimals = 0},
|
||||
category = "general"
|
||||
})
|
||||
|
||||
ix.config.Add("shootSoundDSPDistant", 31, "Which DSP preset to use for distant sounds (don't change this unless you know what you're doing!)", nil, {
|
||||
data = {min = 0, max = 140, decimals = 0},
|
||||
category = "general"
|
||||
})
|
||||
|
||||
ix.config.Add("burnTime", 3, "How long someone should be ignited for after they've been lit up by an incendiary grenade", nil, {
|
||||
data = {min = 0, max = 60, decimals = 1},
|
||||
category = "general"
|
||||
})
|
||||
|
||||
ix.config.Add("shotsBeforeBreakingWeapon", 900, "How many shots can single weapon handle without breaking", nil, {
|
||||
data = {min = 0, max = 9999},
|
||||
category = "general"
|
||||
})
|
||||
|
||||
function PLUGIN:CanPlayerEquipItem(client, item)
|
||||
if (item.isWeapon and item:GetData("broken", false)) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
sound overrides for ArcCW
|
||||
]]
|
||||
|
||||
local sndTbl = {} -- a table which we can use to queue up sounds asynchronously
|
||||
local function networkAllPendingArcSounds()
|
||||
while true do
|
||||
for i, snd in ipairs(sndTbl) do
|
||||
if !snd.ent or !IsValid(snd.ent) then
|
||||
continue
|
||||
end
|
||||
|
||||
if (!snd.filter) then
|
||||
snd.ent:EmitSound(snd.fsound, snd.lvl, 100, snd.vol, CHAN_STATIC, SND_NOFLAGS,
|
||||
snd.useDSP and snd.dsp or 0)
|
||||
else
|
||||
local _snd = CreateSound(snd.ent, snd.fsound, snd.filter)
|
||||
_snd:SetSoundLevel(snd.lvl)
|
||||
if (snd.useDSP) then
|
||||
_snd:SetDSP(snd.dsp or 0)
|
||||
end
|
||||
_snd:PlayEx(snd.vol, 255)
|
||||
end
|
||||
|
||||
table.remove(sndTbl, i)
|
||||
end
|
||||
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
|
||||
local function insertArcSound(ent, fsound, filter, lvl, vol, dsp, useDSP)
|
||||
sndTbl[#sndTbl + 1] = {
|
||||
ent = ent,
|
||||
fsound = fsound,
|
||||
filter = filter,
|
||||
lvl = lvl,
|
||||
vol = vol,
|
||||
dsp = dsp,
|
||||
useDSP = useDSP
|
||||
}
|
||||
end
|
||||
|
||||
local sndCO = coroutine.create(networkAllPendingArcSounds)
|
||||
|
||||
if (SERVER) then
|
||||
timer.Create("ixNetworkArcCWSounds", 0.1, 0, function()
|
||||
-- gun sounds are kind of low-priority. improves S2K performance if we don't block the main thread with them
|
||||
if (!sndCO or !coroutine.resume(sndCO)) then
|
||||
-- there is something wrong with the table.Add
|
||||
ErrorNoHalt("ArcCW sound coroutine failed to resume. Attempting to recreate coroutine.\n")
|
||||
sndTbl = {}
|
||||
sndCO = coroutine.create(networkAllPendingArcSounds)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local function isShootSound(ent, fsound)
|
||||
if (fsound == ent.ShootSound or fsound == ent.ShootSoundSilenced or fsound == ent.DistantShootSound) then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
timer.Simple(1, function()
|
||||
local tbl = weapons.GetStored("arccw_base") -- baller way of shoving our own shit code into arccw
|
||||
|
||||
-- ^^ make sure we're the last to load so the override actually works
|
||||
function tbl:MyEmitSound(fsound, level, pitch, _vol, chan, useWorld)
|
||||
if !fsound then return end
|
||||
|
||||
fsound = self:GetBuff_Hook("Hook_TranslateSound", fsound) or fsound
|
||||
local client = self:GetOwner()
|
||||
local weapon = client:GetActiveWeapon()
|
||||
local useDSP = isShootSound(weapon, fsound) -- don't play DSP on reloading and equipping sfx
|
||||
if istable(fsound) then fsound = self:TableRandom(fsound) end
|
||||
|
||||
if fsound and fsound != "" then
|
||||
local lvl = math.Clamp(level or 150 - ix.config.Get("shootDbLevelReductionClose", 10), 60, 160)
|
||||
local vol = _vol or 1 - ix.config.Get("shootVolumeReduction", 0.1)
|
||||
local dsp = ix.config.Get("shootSoundDSP", 2)
|
||||
|
||||
local lvl2 = math.Clamp(level or 150 - ix.config.Get("shootDbLevelReduction", 60), 60, 160)
|
||||
local vol2 = math.Clamp(_vol or 1 - ix.config.Get("shootVolumeReduction", 0.1) - 0.1, 0, 1)
|
||||
local dsp2 = ix.config.Get("shootSoundDSPDistant", 31)
|
||||
|
||||
if (!useDSP) then
|
||||
lvl = math.Clamp(lvl - ix.config.Get("shootOtherDbLevelReduction", 50), 60, 160)
|
||||
vol = vol - ix.config.Get("shootOtherVolumeLevelReduction", 0.1)
|
||||
end
|
||||
|
||||
if (CLIENT and client == LocalPlayer()) then
|
||||
-- client plays their own sound
|
||||
-- nevermind, we can't do this because i can't use CRecipientFilters to filter out the client serverside
|
||||
-- nevermind, apparently they don't duplicate any more ?????????????
|
||||
-- TODO: reimplement when that feature makes it to main gmod branch
|
||||
weapon:EmitSound(fsound, level, pitch, vol, chan or CHAN_STATIC)
|
||||
|
||||
elseif (client and SERVER) then
|
||||
-- filter for distant sounding gunshots
|
||||
if (useDSP) then
|
||||
local filter = RecipientFilter()
|
||||
filter:AddAllPlayers()
|
||||
filter:RemovePlayer(client)
|
||||
filter:RemovePVS(client:GetPos())
|
||||
|
||||
insertArcSound(weapon, fsound, filter, lvl2, vol2, dsp2, true)
|
||||
end
|
||||
|
||||
weapon:EmitSound(fsound, lvl, 100, vol, CHAN_STATIC, SND_NOFLAGS, dsp)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function ArcCW:PlayerGetAtts(client, attachment)
|
||||
if (!IsValid(client)) then return 0 end
|
||||
if (GetConVar("arccw_attinv_free"):GetBool()) then return 999 end
|
||||
|
||||
if (attachment == "") then return 999 end
|
||||
|
||||
local attachmentData = ArcCW.AttachmentTable[attachment]
|
||||
if (!attachmentData) then return 0 end
|
||||
if (attachmentData.Free) then return 999 end
|
||||
|
||||
local character = client:GetCharacter()
|
||||
if (!character) then return 0 end
|
||||
|
||||
if (!client:IsAdmin() and attachmentData.AdminOnly) then
|
||||
return 0
|
||||
end
|
||||
|
||||
if (attachmentData.InvAtt) then
|
||||
attachment = attachmentData.InvAtt
|
||||
end
|
||||
|
||||
local weapon = client:GetActiveWeapon()
|
||||
if (SERVER and client.ixAttachAttempt and
|
||||
client.ixAttachAttempt.attachment == attachment and
|
||||
client.ixAttachAttempt.time + 1 > CurTime()) then
|
||||
weapon = client.ixAttachAttempt.weapon
|
||||
end
|
||||
|
||||
local amount = character:GetInventory():GetItemCount(PLUGIN.attachmentTranslate[attachment] or attachment)
|
||||
for _, v in ipairs(weapon:GetNetVar("ixItemDefaultWeaponAtts", {})) do
|
||||
if (v == attachment) then amount = amount + 1 end
|
||||
end
|
||||
|
||||
if (SERVER and weapon.ixItem) then
|
||||
for _, v in pairs(weapon.ixItem:GetData("WeaponAttachments", {})) do
|
||||
if (v.attachment == attachment) then
|
||||
amount = amount + 1
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif (CLIENT and weapon:GetNetVar("ixItemID")) then
|
||||
local item = ix.item.instances[weapon:GetNetVar("ixItemID")]
|
||||
if (item) then
|
||||
for _, v in pairs(item:GetData("WeaponAttachments", {})) do
|
||||
if (v.attachment == attachment) then
|
||||
amount = amount + 1
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return amount
|
||||
end
|
||||
|
||||
function PLUGIN:ArcCW_PlayerCanAttach(client, weapon, attachment, slot, detach)
|
||||
client.ixAttachAttempt = nil
|
||||
client.ixDeattachAttempt = nil
|
||||
|
||||
if (detach) then
|
||||
client.ixDeattachAttempt = {
|
||||
weapon = weapon,
|
||||
attachment = attachment,
|
||||
slot = slot
|
||||
}
|
||||
return
|
||||
end
|
||||
if (attachment == "") then return end
|
||||
|
||||
local weapon2 = client.ixAttachWeapon or client:GetActiveWeapon()
|
||||
if (weapon2 != weapon) then return end
|
||||
|
||||
client.ixAttachAttempt = {
|
||||
weapon = weapon,
|
||||
attachment = attachment,
|
||||
slot = slot,
|
||||
time = CurTime()
|
||||
}
|
||||
for _, v in ipairs(weapon:GetNetVar("ixItemDefaultWeaponAtts", {})) do
|
||||
if (v == attachment) then
|
||||
client.ixAttachAttempt.mode = "default"
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
if (weapon.ixItem) then
|
||||
for _, v in pairs(weapon.ixItem:GetData("WeaponAttachments", {})) do
|
||||
if (v.attachment == attachment) then
|
||||
client.ixAttachAttempt.mode = "reattach"
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local character = client:GetCharacter()
|
||||
if (character) then
|
||||
local inventory = character:GetInventory()
|
||||
if (self.attachmentTranslate[attachment]) then
|
||||
if (!inventory:HasItem(self.attachmentTranslate[attachment])) then
|
||||
return false
|
||||
end
|
||||
elseif (!inventory:HasItem(attachment)) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
client.ixAttachAttempt.mode = "item"
|
||||
return true
|
||||
end
|
||||
|
||||
-- Give one ammo otherwise ArcCW doesn't let us reload
|
||||
function PLUGIN:KeyPress(client, key)
|
||||
if (key == IN_RELOAD) then
|
||||
local weapon = client:GetActiveWeapon()
|
||||
if (IsValid(weapon) and weapon:GetNetVar("ixItemID") and client:GetAmmoCount(weapon:GetPrimaryAmmoType()) == 0) then
|
||||
if (client.ixPreReloadAmmoGiven) then
|
||||
-- We still have 1 ammo from some previous attempt, lets remove this first!
|
||||
client:SetAmmo(math.max(client:GetAmmoCount(client.ixPreReloadAmmoGiven) - 1, 0), client.ixPreReloadAmmoGiven)
|
||||
end
|
||||
client:SetAmmo(1, weapon:GetPrimaryAmmoType())
|
||||
client.ixPreReloadAmmoGiven = weapon:GetPrimaryAmmoType()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Take the ammo again if it wasn't used
|
||||
function PLUGIN:KeyRelease(client, key)
|
||||
if (client.ixPreReloadAmmoGiven) then
|
||||
client:SetAmmo(client:GetAmmoCount(client.ixPreReloadAmmoGiven) - 1, client.ixPreReloadAmmoGiven)
|
||||
client.ixPreReloadAmmoGiven = nil
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:PlayerSwitchWeapon(client, oldWeapon, newWeapon)
|
||||
if (client.ixPreReloadAmmoGiven) then
|
||||
client:SetAmmo(client:GetAmmoCount(client.ixPreReloadAmmoGiven) - 1, client.ixPreReloadAmmoGiven)
|
||||
client.ixPreReloadAmmoGiven = nil
|
||||
end
|
||||
end
|
||||
|
||||
local sortFunc = function(a, b)
|
||||
local aAmmo, bAmmo = a:GetAmmo(), b:GetAmmo()
|
||||
if (aAmmo != bAmmo) then
|
||||
return aAmmo > bAmmo
|
||||
else
|
||||
return a:GetID() > b:GetID()
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:Hook_PreReload(weapon)
|
||||
local client = weapon:GetOwner()
|
||||
if (!IsValid(client) or client:IsNPC()) then return end
|
||||
|
||||
-- Take the 1 ammo given to let us get past the 'not zero ammo' check that happens before this hook
|
||||
if (client.ixPreReloadAmmoGiven) then
|
||||
client:SetAmmo(client:GetAmmoCount(client.ixPreReloadAmmoGiven) - 1, client.ixPreReloadAmmoGiven)
|
||||
client.ixPreReloadAmmoGiven = nil
|
||||
end
|
||||
|
||||
local character = client:GetCharacter()
|
||||
if (!character) then return end
|
||||
|
||||
if (weapon:GetNetVar("ixItemID") == nil) then return end
|
||||
|
||||
local itemID = weapon:GetNetVar("ixItemID")
|
||||
local item = ix.item.instances[itemID]
|
||||
if (!item) then return end
|
||||
|
||||
local ammoID = weapon:GetPrimaryAmmoType()
|
||||
local ammoName = string.lower(game.GetAmmoName(ammoID) or "")
|
||||
if (ammoName == "") then return end
|
||||
|
||||
local ammoItems = {}
|
||||
for k, v in ipairs(character:GetInventory():GetItemsByBase("base_arccwmag")) do
|
||||
if (item.magazines and item.magazines[v.uniqueID] and v:GetAmmo() > 0) then
|
||||
ammoItems[#ammoItems + 1] = v
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(ammoItems, sortFunc)
|
||||
|
||||
local ammoItem = ammoItems[1]
|
||||
if (!ammoItem) then return ix.config.Get("forceUseMagazineSystem") end
|
||||
|
||||
local chamber = math.Clamp(weapon:Clip1(), 0, weapon:GetChamberSize())
|
||||
if (SERVER) then
|
||||
if (weapon.ixItem:GetData("reloadMagazineItem")) then
|
||||
self:RefundAmmoItem(weapon, character, weapon.ixItem:GetData("reloadMagazineItem"), weapon:Clip1() + client:GetAmmoCount(ammoID) - chamber, weapon.ixItem:GetData("reloadMagazineInvPos"))
|
||||
weapon:SetClip1(chamber)
|
||||
end
|
||||
weapon.ixItem:SetData("reloadMagazineItem", ammoItem:GetID())
|
||||
weapon.ixItem:SetData("reloadMagazineInvPos", {ammoItem.invID, ammoItem.gridX, ammoItem.gridY})
|
||||
ammoItem:Transfer(nil, nil, nil, client, nil, true)
|
||||
end
|
||||
|
||||
client:SetAmmo(ammoItem:GetAmmo(), ammoID)
|
||||
end
|
||||
|
||||
function PLUGIN:Hook_ModDispersion(weapon, hip)
|
||||
local weaponOwner = weapon:GetOwner()
|
||||
|
||||
if (weaponOwner:IsPlayer()) then
|
||||
weaponOwner = weaponOwner:GetCharacter()
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
local skillLevel = weaponOwner:GetSkillLevel("guns")
|
||||
local minSkillLevel, maxSkillLevel = ix.weapons:GetWeaponSkillRequired(weapon:GetClass())
|
||||
|
||||
if (skillLevel < minSkillLevel) then
|
||||
return hip + math.ceil(hip * self.spreadMaxIncrease) * (1 - skillLevel / minSkillLevel)
|
||||
end
|
||||
|
||||
skillLevel = math.min(skillLevel, maxSkillLevel)
|
||||
return hip - math.floor(hip * self.spreadMaxDecrease) * ((skillLevel - minSkillLevel) / (maxSkillLevel - minSkillLevel))
|
||||
end
|
||||
|
||||
function PLUGIN:Hook_ModifyRecoil(weapon, rec)
|
||||
local weaponOwner = weapon:GetOwner()
|
||||
|
||||
if (weaponOwner:IsPlayer()) then
|
||||
weaponOwner = weaponOwner:GetCharacter()
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
local skillLevel = weaponOwner:GetSkillLevel("guns")
|
||||
local minSkillLevel, maxSkillLevel = ix.weapons:GetWeaponSkillRequired(weapon:GetClass())
|
||||
local modifier
|
||||
|
||||
if (skillLevel < minSkillLevel) then
|
||||
modifier = PLUGIN.recoilMaxIncrease * (1 - skillLevel / minSkillLevel)
|
||||
else
|
||||
skillLevel = math.min(skillLevel, maxSkillLevel)
|
||||
modifier = -(PLUGIN.recoilMaxDecrease * ((skillLevel - minSkillLevel) / (maxSkillLevel - minSkillLevel)))
|
||||
end
|
||||
|
||||
rec.Recoil = rec.Recoil + (rec.Recoil * modifier)
|
||||
rec.RecoilSide = rec.RecoilSide + (rec.RecoilSide * modifier)
|
||||
-- rec.VisualRecoilMul = rec.VisualRecoilMul + (rec.VisualRecoilMul * modifier)
|
||||
|
||||
return rec
|
||||
end
|
||||
|
||||
function PLUGIN:O_Hook_Override_CanBash()
|
||||
return false
|
||||
end
|
||||
Reference in New Issue
Block a user