require("mw_math") ENT.m_AimDeltaLerp = 0 ENT.m_LocomotionDeltaLerp = 0 ENT.m_CustomizationRateLerp = 0 ENT.m_bMoveStopped = true ENT.m_bMoveStarted = false ENT.m_bOnGround = true ENT.m_LeftHandGripPoseParameter = nil ENT.m_LeftHandGripTarget = 0 ENT.m_LeftHandGripLerp = 0 ENT.m_RightHandGripPoseParameter = nil ENT.m_RightHandGripTarget = 0 ENT.m_RightHandGripLerp = 0 ENT.m_LastSprayRounds = 0 local idleIndices = { ["Idle"] = true, ["Jump"] = true, ["Jog_Out"] = true, ["Land"] = true } local uncancellableIndices = { ["Sprint_In"] = true, ["Holster"] = true } local allowAim = { ["Ads_In"] = true, ["Fire_Last"] = true, ["Fire"] = true } local function playIdleAnimation(vm, seqIndex) local ind = vm.m_LastSequenceIndex if ((idleIndices[ind] || (!uncancellableIndices[ind] && vm:GetCycle() >= 0.98)) && (allowAim[ind] != nil || vm:GetOwner():GetAimDelta() <= 0)) then vm:PlayAnimation(seqIndex, true) end end local function locomotion(vm) local w = vm:GetOwner() local p = w:GetOwner() if (!IsValid(p) || !p:IsPlayer()) then return end local vel = p:GetVelocity() vel = Vector(vel.x, vel.y, 0) local len = math.max(vel:Length(), 0.01) if (!p:IsOnGround() || (p.GetSliding != nil && p:GetSliding())) then vm.m_LocomotionDeltaLerp = mw_math.SafeLerp(6 * RealFrameTime(), vm.m_LocomotionDeltaLerp, 0) else vm.m_LocomotionDeltaLerp = mw_math.SafeLerp(4 * RealFrameTime(), vm.m_LocomotionDeltaLerp, len / p:GetWalkSpeed()) end --jogging and walking local slowWalkPoint = p:GetSlowWalkSpeed() / p:GetWalkSpeed() local slowWalkDelta = 1 - math.abs(slowWalkPoint - vm.m_LocomotionDeltaLerp) / slowWalkPoint local jogDelta = vm.m_LocomotionDeltaLerp - slowWalkDelta --when we stop jogging if (jogDelta <= 0.5 && !vm.m_bMoveStopped) then if (p:IsOnGround()) then playIdleAnimation(vm, "Jog_Out") end vm.m_bMoveStopped = true elseif (jogDelta > 0.5) then vm.m_bMoveStopped = false end --when we start moving if (vm.m_LocomotionDeltaLerp > 0.1 && !vm.m_bMoveStarted) then if (p:IsOnGround()) then playIdleAnimation(vm, "Land") end vm.m_bMoveStarted = true elseif (vm.m_LocomotionDeltaLerp <= 0.1) then vm.m_bMoveStarted = false end vm:SetPoseParameter("jog_loop", jogDelta * Lerp(vm.m_AimDeltaLerp, 1, 0.1 * (w.Zoom.MovementMultiplier || 1))) vm:SetPoseParameter("walk_loop", slowWalkDelta * Lerp(vm.m_AimDeltaLerp, 1, 0.2 * (w.Zoom.PoseParameterMultiplier || 1))) --freefall loop local z = math.min(p:GetVelocity().z, 0) local delta = math.min(math.min(z + 500, 0) / -1100, 1) vm:SetPoseParameter("freefall_loop", delta * Lerp(vm.m_AimDeltaLerp, 1, 0.1)) --jumping and landing if (vm.m_bOnGround != p:IsOnGround()) then if (!p:IsOnGround()) then playIdleAnimation(vm, "Jump") else playIdleAnimation(vm, "Land") end vm.m_bOnGround = p:IsOnGround() end --sprint local sprintPoint = p:GetRunSpeed() / p:GetWalkSpeed() local sprintDelta = (vm.m_LocomotionDeltaLerp - 1) / (sprintPoint - 1) vm:SetPoseParameter("sprint_loop", math.min(sprintDelta, math.Clamp((CurTime() - w:GetNextReloadTime()) * 10, 0, 1)) * Lerp(vm.m_AimDeltaLerp, 1, 0.1)) -- not so efficient but very effective sprinting reload bodge --the offset when moving in general local offsetDelta = mw_math.CosineInterp(vm.m_LocomotionDeltaLerp * math.Clamp(1 - sprintDelta, 0, 1), 0, 1) offsetDelta = offsetDelta * (1 - math.Clamp(vm.m_AimDeltaLerp * 2, 0, 1)) vm:SetPoseParameter("jog_offset", offsetDelta) --after fire reshoulder if (vm.m_LastSprayRounds != w:GetSprayRounds() && !w:HasFlag("BipodDeployed")) then if (w:GetSprayRounds() == 0 && vm.m_LastSprayRounds >= 5) then if (!string.find(string.lower(vm.m_LastSequenceIndex), "fire")) then local anim = math.random(1, 2) == 1 && "Land" || "Jog_Out" if (w.Animations.SprayEnd != nil) then anim = "SprayEnd" end playIdleAnimation(vm, anim) vm.m_LastSprayRounds = w:GetSprayRounds() end else vm.m_LastSprayRounds = w:GetSprayRounds() end end end ENT.m_InspectSpeed = 1 local function inspection(vm) local w = vm:GetOwner() local randomness = math.sin(CurTime() * 2) * 0.05 + math.sin(CurTime() * 3) * 0.05 local inspectDelta = w.FreezeInspectDelta || 0.15 if (w:Clip1() <= 0 && w.EmptyFreezeInspectDelta) then inspectDelta = w.EmptyFreezeInspectDelta end local bStop = w:HasFlag("StoppedInspectAnimation") || (w:HasFlag("Customizing") && vm:GetCycle() > inspectDelta) vm.m_InspectSpeed = mw_math.SafeLerp(5 * RealFrameTime(), vm.m_InspectSpeed, Lerp(mw_math.btn(bStop), 1, randomness)) if (string.find(string.lower(vm.m_LastSequenceIndex), "inspect")) then vm:SetPlaybackRate(vm.m_InspectSpeed) end end local function grips(vm) local w = vm:GetOwner() if (w.GripPoseParameters != nil) then for i, pp in pairs(w.GripPoseParameters) do vm:SetPoseParameter(pp, 0) end vm.m_LeftHandGripLerp = math.Approach(vm.m_LeftHandGripLerp, vm.m_LeftHandGripTarget, 10 * RealFrameTime()) if (vm.m_LeftHandGripPoseParameter != nil) then vm:SetPoseParameter(vm.m_LeftHandGripPoseParameter, vm.m_LeftHandGripLerp) end end if (w.GripPoseParameters2 != nil) then for i, pp in pairs(w.GripPoseParameters2) do vm:SetPoseParameter(pp, 0) end vm.m_RightHandGripLerp = math.Approach(vm.m_RightHandGripLerp, vm.m_RightHandGripTarget, 10 * RealFrameTime()) if (vm.m_RightHandGripPoseParameter != nil) then vm:SetPoseParameter(vm.m_RightHandGripPoseParameter, vm.m_RightHandGripLerp) end end end function ENT:SetPoseParameters() local w = self:GetOwner() self:SetPoseParameter("aim_offset", self.m_AimDeltaLerp) self:SetPoseParameter("hybrid_offset", w:GetAimMode()) self:SetPoseParameter("firemode_offset", w:GetFiremode() - 1) self:SetPoseParameter("empty_offset", mw_math.btn(w:Clip1() <= 0 || !w:HasFlag("Rechambered"))) self:SetPoseParameter("bipod", mw_math.btn(w:HasFlag("BipodDeployed"))) end ENT.m_UpdateDelta = 0 function ENT:Think() local w = self:GetOwner() if (!IsValid(w)) then return end self:ReconcileServerAnims() if (!w:IsCarriedByLocalPlayer() || !IsValid(w:GetOwner()) || w != w:GetOwner():GetActiveWeapon()) then return end if (self.m_UpdateDelta <= 0.2) then self:UpdateAnimation(self.m_LastSequenceIndex) self.m_UpdateDelta = self.m_UpdateDelta + FrameTime() --WAKE UP GODDAMN IT end if (self.m_LastSequenceIndex != "INIT") then self.m_AimDeltaLerp = mw_math.SafeLerp(30 * RealFrameTime(), self.m_AimDeltaLerp, w:GetAimDelta()) self:SetPoseParameters() --we play idle a bit earlier if ads in local targetCycle = self.m_LastSequenceIndex == "Ads_In" && 0.5 || 0.98 if (self:GetCycle() >= targetCycle) then playIdleAnimation(self, "Idle") end --states locomotion(self) inspection(self) grips(self) end end function ENT:ReconcileServerAnims() if (self.m_AnimFromServer == nil) then return end local tick = self.m_AnimFromServer.Tick local animId = self.m_AnimFromServer.AnimID local rate = self.m_AnimFromServer.Rate local timeDifference = self.m_AnimFromServer.TimeDifference self.m_AnimFromServer = nil local seqIndex = self:GetSequenceIndexByID(animId) if (tick < self.m_Tick || (tick == self.m_Tick && self.m_LastSequenceIndex == seqIndex)) then return end local sequences = self:GetOwner().Animations[seqIndex].Sequences local seqId = self:LookupSequence(sequences[1]) local length = self:SequenceDuration(seqId) local cycle = timeDifference / length cycle = cycle * rate self:PlaySequence(sequences[math.random(1, #sequences)], rate, cycle) self.m_LastSequenceIndex = seqIndex self.m_Tick = tick end function ENT:VManipPostPlayAnim(name) playIdleAnimation(self, "Jog_Out") end function ENT:VManipHoldQuit() playIdleAnimation(self, "Land") end function ENT:VManipRemove() playIdleAnimation(self, "Jog_Out") end