298 lines
9.7 KiB
Lua
298 lines
9.7 KiB
Lua
require("mw_utils")
|
|
|
|
--Events we can use:
|
|
-- CL_EVENT_SOUND [sound, vector for spatial] (5004) -> sound (eg: "event 5004 mw19.sound 0,10,10")
|
|
-- CL_EJECT_BRASS1 [attachment name] (6001) -> ejection (eg: event 6001 tag_ejection)
|
|
-- CL_EVENT_DISPATCHEFFECT0 [particle name, attachment name] (9001) -> particles (eg: event 9001 mw_muzzleflash tag_flash)
|
|
-- CL_EVENT_DISPATCHEFFECT1 [0/1] (9011) -> left hand grip pose toggle (eg: event 9011 0 -> event 9011 1)
|
|
-- CL_EVENT_DISPATCHEFFECT2 [0/1] (9021) -> right hand grip pose toggle (eg: event 9021 0 -> event 9021 1)
|
|
-- CL_EVENT_DISPATCHEFFECT3 [name] (9031) -> run attachment function (eg: event 9031 FillBullets)
|
|
|
|
--Animation event codes
|
|
local CL_EVENT_MUZZLEFLASH0 = 5001 -- Muzzleflash on attachment 0
|
|
local CL_EVENT_MUZZLEFLASH1 = 5011 -- Muzzleflash on attachment 1
|
|
local CL_EVENT_MUZZLEFLASH2 = 5021 -- Muzzleflash on attachment 2
|
|
local CL_EVENT_MUZZLEFLASH3 = 5031 -- Muzzleflash on attachment 3
|
|
local CL_EVENT_SPARK0 = 5002 -- Spark on attachment 0
|
|
local CL_EVENT_NPC_MUZZLEFLASH0 = 5003 -- Muzzleflash on attachment 0 for third person views
|
|
local CL_EVENT_NPC_MUZZLEFLASH1 = 5013 -- Muzzleflash on attachment 1 for third person views
|
|
local CL_EVENT_NPC_MUZZLEFLASH2 = 5023 -- Muzzleflash on attachment 2 for third person views
|
|
local CL_EVENT_NPC_MUZZLEFLASH3 = 5033 -- Muzzleflash on attachment 3 for third person views
|
|
local CL_EVENT_SOUND = 5004 -- Emit a sound // NOTE THIS MUST MATCH THE DEFINE AT CBaseEntity::PrecacheModel on the server!!!!!
|
|
local CL_EVENT_EJECTBRASS1 = 6001 -- Eject a brass shell from attachment 1
|
|
local CL_EVENT_DISPATCHEFFECT0 = 9001 -- Hook into a DispatchEffect on attachment 0
|
|
local CL_EVENT_DISPATCHEFFECT1 = 9011 -- Hook into a DispatchEffect on attachment 1
|
|
local CL_EVENT_DISPATCHEFFECT2 = 9021 -- Hook into a DispatchEffect on attachment 2
|
|
local CL_EVENT_DISPATCHEFFECT3 = 9031 -- Hook into a DispatchEffect on attachment 3
|
|
local CL_EVENT_DISPATCHEFFECT4 = 9041 -- Hook into a DispatchEffect on attachment 4
|
|
local CL_EVENT_DISPATCHEFFECT5 = 9051 -- Hook into a DispatchEffect on attachment 5
|
|
local CL_EVENT_DISPATCHEFFECT6 = 9061 -- Hook into a DispatchEffect on attachment 6
|
|
local CL_EVENT_DISPATCHEFFECT7 = 9071 -- Hook into a DispatchEffect on attachment 7
|
|
local CL_EVENT_DISPATCHEFFECT8 = 9081 -- Hook into a DispatchEffect on attachment 8
|
|
local CL_EVENT_DISPATCHEFFECT9 = 9091 -- Hook into a DispatchEffect on attachment 9
|
|
local utilef = util.Effect
|
|
local pef = ParticleEffectAttach
|
|
|
|
local function invalidateBoneCacheForParticles(ent)
|
|
while (IsValid(ent)) do
|
|
if (ent:IsEffectActive(EF_BONEMERGE) || !IsValid(ent:GetParent())) then
|
|
ent:InvalidateBoneCache()
|
|
end
|
|
ent = ent:GetParent()
|
|
end
|
|
end
|
|
|
|
local function findAttachmentInChildren(ent, attName)
|
|
local attId = mw_utils.LookupAttachmentCached(ent, attName)
|
|
|
|
for _, c in pairs(ent:GetChildren()) do
|
|
if (c:GetClass() != "class C_BaseFlex") then
|
|
continue
|
|
end
|
|
|
|
local ce, ca = findAttachmentInChildren(c, attName)
|
|
|
|
if (ca != nil) then
|
|
attId = ca
|
|
ent = ce
|
|
end
|
|
end
|
|
|
|
return ent, attId
|
|
end
|
|
|
|
function ENT:FindAttachment(attName)
|
|
return findAttachmentInChildren(self, attName)
|
|
end
|
|
|
|
local function createEffectDataForShell(owner, attName)
|
|
local data = EffectData()
|
|
data:SetEntity(owner)
|
|
|
|
local attEnt, attId = findAttachmentInChildren(owner, attName)
|
|
|
|
if (attId == nil) then
|
|
mw_utils.ErrorPrint("createEffectDataForShell: "..attName.." does not exist on model!")
|
|
return data
|
|
end
|
|
|
|
local att = attEnt:GetAttachment(attId)
|
|
data:SetOrigin(att.Pos)
|
|
data:SetAngles(att.Ang)
|
|
|
|
owner = owner:GetOwner()
|
|
|
|
while (IsValid(owner) && !owner:IsPlayer()) do
|
|
owner = owner:GetOwner()
|
|
end
|
|
|
|
if (IsValid(owner)) then
|
|
data:SetNormal(owner:GetVelocity():GetNormalized())
|
|
data:SetMagnitude(owner:GetVelocity():Length())
|
|
end
|
|
|
|
return data
|
|
end
|
|
|
|
function ENT:IsFirstPerson()
|
|
local w = self:GetOwner()
|
|
return IsValid(w:GetOwner()) && w:GetOwner():IsPlayer() && !w:GetOwner():ShouldDrawLocalPlayer() && w:IsCarriedByLocalPlayer()
|
|
end
|
|
|
|
function ENT:HandleEjection(attName)
|
|
local w = self:GetOwner()
|
|
|
|
if (w.Shell == "mwb_shelleject" || w.Shell == "mwb_shelleject_comp") then
|
|
mw_utils.ErrorPrint("DoEjection: do not use mwb_shelleject! Use an existing caliber or make your own.")
|
|
return true
|
|
elseif (istable(w.Shell)) then
|
|
mw_utils.DevPrint("DoEjection: still using legacy way! Consider switching to new method.")
|
|
end
|
|
|
|
local eff = isstring(w.Shell) && w.Shell || "mwb_shelleject_comp"
|
|
|
|
if (self:IsFirstPerson()) then
|
|
local data = createEffectDataForShell(self, attName)
|
|
data:SetFlags(1)
|
|
utilef(eff, data)
|
|
else
|
|
local data = createEffectDataForShell(w, attName)
|
|
data:SetFlags(0)
|
|
utilef(eff, data)
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function ENT:HandleParticle(partName, attName)
|
|
local w = self:GetOwner()
|
|
|
|
if (w.ParticleEffects != nil && w.ParticleEffects[partName] != nil) then
|
|
partName = w.ParticleEffects[partName]
|
|
end
|
|
|
|
if (self:IsFirstPerson()) then
|
|
local ent, attId = findAttachmentInChildren(self, attName)
|
|
|
|
if (attId == nil) then
|
|
mw_utils.ErrorPrint("HandleParticle: "..attName.." does not exist on viewmodel!")
|
|
return true
|
|
end
|
|
|
|
if (self.m_Particles[partName] != nil) then
|
|
self.m_Particles[partName]:StopEmissionAndDestroyImmediately()
|
|
end
|
|
|
|
local particleSystem = CreateParticleSystem(ent, partName, PATTACH_POINT_FOLLOW, attId)
|
|
particleSystem:SetIsViewModelEffect(true)
|
|
particleSystem:SetShouldDraw(false)
|
|
self.m_Particles[partName] = particleSystem
|
|
else
|
|
local ent, attId = findAttachmentInChildren(w, attName)
|
|
|
|
if (attId == nil) then
|
|
mw_utils.ErrorPrint("HandleParticle: "..attName.." does not exist on worldmodel!")
|
|
return true
|
|
end
|
|
|
|
ent:StopParticlesNamed(partName)
|
|
pef(partName, PATTACH_POINT_FOLLOW, ent, attId)
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
function ENT:HandleSound(soundName, spatialVector)
|
|
local w = self:GetOwner()
|
|
|
|
if (IsValid(w) && w.SoundOverrides != nil) then
|
|
soundName = w.SoundOverrides[soundName] || soundName
|
|
end
|
|
|
|
if (spatialVector != nil && !spatialVector:IsZero()) then
|
|
if (IsValid(w:GetOwner()) && !w:GetOwner():IsOnGround()) then
|
|
return true
|
|
end
|
|
|
|
local ang = self:GetAngles()
|
|
local pos = self:GetPos()
|
|
pos:Add(ang:Forward() * spatialVector.y)
|
|
pos:Add(ang:Right() * spatialVector.x)
|
|
pos:Add(ang:Up() * spatialVector.z)
|
|
|
|
sound.Play(soundName, pos)
|
|
return true
|
|
end
|
|
|
|
--if (self:GetPlaybackRate() != 1) then
|
|
-- self:EmitSound(soundName, 100, math.Clamp(self:GetPlaybackRate(), 0.95, 1.15) * 100, 1, CHAN_AUTO, SND_CHANGE_PITCH)
|
|
--else
|
|
self:EmitSound(soundName, 0, math.Clamp(self:GetPlaybackRate(), 1, 1.1) * 100, 0, 0, SND_SHOULDPAUSE + SND_CHANGE_PITCH)
|
|
--end
|
|
|
|
return true
|
|
end
|
|
|
|
function ENT:HandleLeftHandGrip(val)
|
|
self.m_LeftHandGripTarget = tonumber(val)
|
|
return true
|
|
end
|
|
|
|
function ENT:HandleRightHandGrip(val)
|
|
self.m_RightHandGripTarget = tonumber(val)
|
|
return true
|
|
end
|
|
|
|
function ENT:HandleAttFunction(name)
|
|
self:GetOwner():AttachmentFunction(name)
|
|
return true
|
|
end
|
|
|
|
local function eventError(event, msg)
|
|
mw_utils.ErrorPrint("FireAnimationEvent ("..event.."): "..msg)
|
|
end
|
|
|
|
function ENT:FireAnimationEvent(pos, ang, event, name)
|
|
if (event == CL_EVENT_DISPATCHEFFECT3) then
|
|
return self:HandleAttFunction(name)
|
|
end
|
|
|
|
if (event == CL_EVENT_DISPATCHEFFECT1) then
|
|
return self:HandleLeftHandGrip(name || 0)
|
|
end
|
|
|
|
if (event == CL_EVENT_DISPATCHEFFECT2) then
|
|
return self:HandleRightHandGrip(name || 0)
|
|
end
|
|
|
|
if (event == CL_EVENT_SOUND) then
|
|
if (name == nil) then
|
|
eventError(event, "Missing sound name!")
|
|
return true
|
|
end
|
|
|
|
local args = string.Explode(" ", name)
|
|
|
|
if (#args <= 0) then
|
|
eventError(event, "Missing arguments!")
|
|
return true
|
|
end
|
|
|
|
local soundName = args[1]
|
|
local spatialVector = Vector()
|
|
|
|
if (args[2] != nil) then
|
|
local components = string.Explode(",", args[2])
|
|
|
|
if (#components <= 1) then
|
|
--jake used spaces like a dumbass
|
|
spatialVector.x = args[2]
|
|
spatialVector.y = args[3]
|
|
spatialVector.z = args[4]
|
|
else
|
|
spatialVector.x = tonumber(components[1]) || 0
|
|
spatialVector.y = tonumber(components[2]) || 0
|
|
spatialVector.z = tonumber(components[3]) || 0
|
|
end
|
|
end
|
|
|
|
return self:HandleSound(soundName, spatialVector)
|
|
end
|
|
|
|
if (event == CL_EVENT_EJECTBRASS1) then
|
|
if (name == nil) then
|
|
eventError(event, "Missing attachment name!")
|
|
return true
|
|
end
|
|
|
|
if (self:GetOwner().HandleEjection != nil) then
|
|
return self:GetOwner():HandleEjection(name)
|
|
end
|
|
|
|
return self:HandleEjection(name)
|
|
end
|
|
|
|
if (event == CL_EVENT_DISPATCHEFFECT0) then
|
|
if (name == nil) then
|
|
eventError(event, "Missing arguments!")
|
|
return true
|
|
end
|
|
|
|
local args = string.Explode(" ", name)
|
|
|
|
if (#args <= 0) then
|
|
eventError(event, "Missing arguments!")
|
|
return true
|
|
end
|
|
|
|
local partName = args[1]
|
|
local attName = args[2]
|
|
|
|
if (attName == nil) then
|
|
eventError(event, "Missing attachment name!")
|
|
return true
|
|
end
|
|
|
|
return self:HandleParticle(partName, attName)
|
|
end
|
|
end |