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