mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-18 06:03:47 +03:00
Upload
This commit is contained in:
385
lua/pac3/core/client/parts/animation.lua
Normal file
385
lua/pac3/core/client/parts/animation.lua
Normal file
@@ -0,0 +1,385 @@
|
||||
--[[
|
||||
| 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 FrameTime = FrameTime
|
||||
|
||||
local BUILDER, PART = pac.PartTemplate("base")
|
||||
|
||||
local AnimStack
|
||||
AnimStack = {
|
||||
__index = {
|
||||
push = function(self, part)
|
||||
local stack = self.stack
|
||||
|
||||
if #stack == 0 then
|
||||
-- Empty stack
|
||||
table.insert(stack, part)
|
||||
else
|
||||
-- Stop the current animation if it's not self
|
||||
local top = self:getTop()
|
||||
if top ~= part then
|
||||
if top then top:OnStackStop() end
|
||||
|
||||
-- Remove self from stack to move to end and also prevent things from breaking because table.RemoveByValue() only removes the first instance
|
||||
table.RemoveByValue(stack, part)
|
||||
table.insert(stack, part)
|
||||
end
|
||||
end
|
||||
|
||||
part:OnStackStart()
|
||||
end,
|
||||
pop = function(self, part)
|
||||
part:OnStackStop()
|
||||
local stack = self.stack
|
||||
|
||||
-- Remove self from animation stack
|
||||
if table.RemoveByValue(stack, part) == #stack + 1 then
|
||||
-- This was the current animation so play the next in the stack
|
||||
local top = self:getTop()
|
||||
if top then top:OnStackStart() end
|
||||
end
|
||||
end,
|
||||
getTop = function(self)
|
||||
local stack = self.stack
|
||||
local top = stack[#stack]
|
||||
-- Remove invalid parts
|
||||
while top and not top:IsValid() do
|
||||
table.remove(stack)
|
||||
top = stack[#stack]
|
||||
end
|
||||
return top
|
||||
end
|
||||
},
|
||||
__call = function(meta)
|
||||
return setmetatable({
|
||||
stack = {}
|
||||
}, meta)
|
||||
end,
|
||||
get = function(ent)
|
||||
local animStack = ent.pac_animation_stack
|
||||
if not animStack then
|
||||
animStack = AnimStack()
|
||||
ent.pac_animation_stack = animStack
|
||||
end
|
||||
return animStack
|
||||
end
|
||||
}
|
||||
setmetatable(AnimStack, AnimStack)
|
||||
|
||||
PART.ClassName = "animation"
|
||||
PART.ThinkTime = 0
|
||||
PART.Groups = {'entity', 'model', 'modifiers'}
|
||||
PART.Icon = 'icon16/eye.png'
|
||||
|
||||
PART.frame = 0
|
||||
|
||||
BUILDER
|
||||
:StartStorableVars()
|
||||
:GetSet("Loop", true)
|
||||
:GetSet("PingPongLoop", false)
|
||||
:GetSet("SequenceName", "", {enums = function(part) local tbl = {} for k,v in pairs(part:GetSequenceList()) do tbl[v] = v end return tbl end})
|
||||
:GetSet("Rate", 1, {editor_sensitivity = 0.1})
|
||||
:GetSet("Offset", 0)
|
||||
:GetSet("Min", 0)
|
||||
:GetSet("Max", 1)
|
||||
:GetSet("WeaponHoldType", "none", {enums = function(part) return part.ValidHoldTypes end})
|
||||
:GetSet("OwnerCycle", false)
|
||||
:GetSet("InvertFrames", false)
|
||||
:GetSet("ResetOnHide", true)
|
||||
:EndStorableVars()
|
||||
|
||||
local tonumber = tonumber
|
||||
|
||||
PART.ValidHoldTypes =
|
||||
{
|
||||
pistol = ACT_HL2MP_IDLE_PISTOL,
|
||||
smg = ACT_HL2MP_IDLE_SMG1,
|
||||
grenade = ACT_HL2MP_IDLE_GRENADE,
|
||||
ar2 = ACT_HL2MP_IDLE_AR2,
|
||||
shotgun = ACT_HL2MP_IDLE_SHOTGUN,
|
||||
rpg = ACT_HL2MP_IDLE_RPG,
|
||||
physgun = ACT_HL2MP_IDLE_PHYSGUN,
|
||||
crossbow = ACT_HL2MP_IDLE_CROSSBOW,
|
||||
melee = ACT_HL2MP_IDLE_MELEE,
|
||||
slam = ACT_HL2MP_IDLE_SLAM,
|
||||
normal = ACT_HL2MP_IDLE,
|
||||
fist = ACT_HL2MP_IDLE_FIST,
|
||||
melee2 = ACT_HL2MP_IDLE_MELEE2,
|
||||
passive = ACT_HL2MP_IDLE_PASSIVE,
|
||||
knife = ACT_HL2MP_IDLE_KNIFE,
|
||||
duel = ACT_HL2MP_IDLE_DUEL,
|
||||
camera = ACT_HL2MP_IDLE_CAMERA,
|
||||
revolver = ACT_HL2MP_IDLE_REVOLVER,
|
||||
|
||||
zombie = ACT_HL2MP_IDLE_ZOMBIE,
|
||||
magic = ACT_HL2MP_IDLE_MAGIC,
|
||||
meleeangry = ACT_HL2MP_IDLE_MELEE_ANGRY,
|
||||
angry = ACT_HL2MP_IDLE_ANGRY,
|
||||
suitcase = ACT_HL2MP_IDLE_SUITCASE,
|
||||
scared = ACT_HL2MP_IDLE_SCARED,
|
||||
}
|
||||
|
||||
function PART:GetNiceName()
|
||||
local str = self:GetSequenceName()
|
||||
|
||||
if str == "" and self:GetWeaponHoldType() ~= "none" then
|
||||
str = self:GetWeaponHoldType()
|
||||
end
|
||||
|
||||
return pac.PrettifyName(str)
|
||||
end
|
||||
|
||||
function PART:GetSequenceList()
|
||||
local ent = self:GetOwner()
|
||||
|
||||
if ent:IsValid() then
|
||||
return ent:GetSequenceList()
|
||||
end
|
||||
|
||||
return {"none"}
|
||||
end
|
||||
|
||||
PART.GetSequenceNameList = PART.GetSequenceList
|
||||
|
||||
function PART:OnStackStop()
|
||||
-- Move code from PART:OnHide() to here
|
||||
local ent = self:GetOwner()
|
||||
|
||||
if ent:IsValid() then
|
||||
if not self:GetResetOnHide() then
|
||||
self.SequenceCycle = ent:GetCycle()
|
||||
self.storeFrame = self.frame
|
||||
else
|
||||
self.SequenceCycle = nil
|
||||
self.frame = 0
|
||||
end
|
||||
|
||||
if ent.pac_animation_sequences then
|
||||
ent.pac_animation_sequences[self] = nil
|
||||
end
|
||||
|
||||
if ent.pac_animation_holdtypes then
|
||||
ent.pac_animation_holdtypes[self] = nil
|
||||
end
|
||||
|
||||
if not ent:IsPlayer() and self.prevSequence then
|
||||
ent:ResetSequence(self.prevSequence)
|
||||
self.prevSequence = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Stop animation and remove from animation stack
|
||||
function PART:OnHide()
|
||||
local ent = self:GetOwner()
|
||||
if not ent:IsValid() then return end
|
||||
AnimStack.get(ent):pop(self)
|
||||
end
|
||||
|
||||
PART.random_seqname = ""
|
||||
|
||||
function PART:SetSequenceName(name)
|
||||
self.SequenceName = name
|
||||
self.random_seqname = table.Random(name:Split(";"))
|
||||
|
||||
if not self:IsHidden() then
|
||||
self:OnShow()
|
||||
end
|
||||
end
|
||||
|
||||
function PART:OnStackStart()
|
||||
-- Moved code from PART:OnShow() to here
|
||||
self.PlayingSequenceFrom = RealTime()
|
||||
local ent = self:GetOwner()
|
||||
|
||||
if ent:IsValid() then
|
||||
self.prevSequence = ent:GetSequence()
|
||||
self.random_seqname = table.Random(self.SequenceName:Split(";"))
|
||||
|
||||
if self.random_seqname ~= "" then
|
||||
local seq = ent:LookupSequence(self.random_seqname) or 0
|
||||
local count = ent:GetSequenceCount() or 0
|
||||
|
||||
if seq < 0 or seq > count or count < 0 then
|
||||
return
|
||||
end
|
||||
|
||||
ent.pac_animation_sequences = ent.pac_animation_sequences or {}
|
||||
ent.pac_animation_sequences[self] = ent.pac_animation_sequences[self] or {}
|
||||
|
||||
local tbl = ent.pac_animation_sequences[self]
|
||||
|
||||
tbl.part = self
|
||||
|
||||
if seq ~= -1 then
|
||||
tbl.seq = seq
|
||||
else
|
||||
seq = tonumber(self.random_seqname) or -1
|
||||
|
||||
if seq ~= -1 then
|
||||
tbl.seq = seq
|
||||
else
|
||||
ent.pac_animation_sequences[self] = nil
|
||||
end
|
||||
end
|
||||
|
||||
if seq ~= -1 then
|
||||
ent:ResetSequence(seq)
|
||||
ent:SetSequence(seq)
|
||||
if not self:GetResetOnHide() then
|
||||
ent:ResetSequenceInfo()
|
||||
|
||||
for i = 1, 10 do
|
||||
ent:FrameAdvance(1)
|
||||
end
|
||||
|
||||
ent:ResetSequenceInfo()
|
||||
end
|
||||
end
|
||||
|
||||
elseif ent:IsPlayer() then
|
||||
local t = self.WeaponHoldType
|
||||
t = t:lower()
|
||||
|
||||
local index = self.ValidHoldTypes[t]
|
||||
|
||||
ent.pac_animation_holdtypes = ent.pac_animation_holdtypes or {}
|
||||
|
||||
if index == nil then
|
||||
ent.pac_animation_holdtypes[self] = nil
|
||||
else
|
||||
local params = {}
|
||||
params[ACT_MP_STAND_IDLE] = index + 0
|
||||
params[ACT_MP_WALK] = index + 1
|
||||
params[ACT_MP_RUN] = index + 2
|
||||
params[ACT_MP_CROUCH_IDLE] = index + 3
|
||||
params[ACT_MP_CROUCHWALK] = index + 4
|
||||
params[ACT_MP_ATTACK_STAND_PRIMARYFIRE] = index + 5
|
||||
params[ACT_MP_ATTACK_CROUCH_PRIMARYFIRE] = index + 5
|
||||
params[ACT_MP_RELOAD_STAND] = index + 6
|
||||
params[ACT_MP_RELOAD_CROUCH] = index + 7
|
||||
params[ACT_MP_JUMP] = index + 8
|
||||
params[ACT_RANGE_ATTACK1] = index + 9
|
||||
params[ACT_MP_SWIM_IDLE] = index + 10
|
||||
params[ACT_MP_SWIM] = index + 11
|
||||
|
||||
-- "normal" jump animation doesn't exist
|
||||
if t == "normal" then
|
||||
params[ACT_MP_JUMP] = ACT_HL2MP_JUMP_SLAM
|
||||
end
|
||||
|
||||
-- these two aren't defined in ACTs for whatever reason
|
||||
if t == "knife" or t == "melee2" then
|
||||
params[ACT_MP_CROUCH_IDLE] = nil
|
||||
end
|
||||
|
||||
params.part = self
|
||||
|
||||
ent.pac_animation_holdtypes[self] = params
|
||||
end
|
||||
end
|
||||
|
||||
if not self:GetResetOnHide() and self.SequenceCycle then
|
||||
ent:SetCycle(self.SequenceCycle)
|
||||
self.SequenceCycle = nil
|
||||
|
||||
if self.storeFrame then
|
||||
self.frame = self.storeFrame
|
||||
self.storeFrame = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Play animation and move to top of animation stack
|
||||
function PART:OnShow()
|
||||
local ent = self:GetOwner()
|
||||
if not ent:IsValid() then return end
|
||||
AnimStack.get(ent):push(self)
|
||||
end
|
||||
|
||||
|
||||
function PART:OnThink()
|
||||
local ent = self:GetOwner()
|
||||
if not ent:IsPlayer() then
|
||||
self:OnUpdateAnimation(nil)
|
||||
end
|
||||
end
|
||||
|
||||
function PART:OnUpdateAnimation(ply)
|
||||
if self:IsHiddenCached() then return end
|
||||
|
||||
local ent = self:GetOwner()
|
||||
if not ent:IsValid() or not ent.pac_animation_stack or ent.pac_animation_stack.stack[#ent.pac_animation_stack.stack] ~= self then return end
|
||||
|
||||
-- from UpdateAnimation hook
|
||||
if ply and ent ~= ply then return end
|
||||
|
||||
if not self.random_seqname then return end
|
||||
|
||||
local seq, duration = ent:LookupSequence(self.random_seqname)
|
||||
|
||||
local count = ent:GetSequenceCount() or 0
|
||||
if seq < 0 or seq >= count then
|
||||
-- It's an invalid sequence. Don't bother
|
||||
return
|
||||
end
|
||||
|
||||
if self.OwnerCycle then
|
||||
local owner = self:GetRootPart():GetOwner()
|
||||
|
||||
if IsValid(owner) then
|
||||
ent:SetCycle(owner:GetCycle())
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local min = self.Min
|
||||
local max = self.Max
|
||||
local maxmin = max - min
|
||||
|
||||
if min == max then
|
||||
local cycle = min
|
||||
|
||||
if pac.IsNumberValid(cycle) then
|
||||
ent:SetCycle(self.InvertFrames and (1 - cycle) or cycle)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
local rate = (duration == 0) and 0 or (self.Rate / duration / math.abs(maxmin) * FrameTime())
|
||||
|
||||
if self.PingPongLoop then
|
||||
if self.Loop then
|
||||
self.frame = (self.frame + rate) % 2
|
||||
else
|
||||
self.frame = math.max(math.min(self.frame + rate, 2), 0)
|
||||
end
|
||||
local cycle = min + math.abs(1 - (self.frame + 1 + self.Offset) % 2) * maxmin
|
||||
|
||||
if pac.IsNumberValid(cycle) then
|
||||
ent:SetCycle(self.InvertFrames and (1 - cycle) or cycle)
|
||||
end
|
||||
else
|
||||
if self.Loop then
|
||||
self.frame = (self.frame + rate) % 2
|
||||
else
|
||||
self.frame = math.max(math.min(self.frame + rate, 1), 0)
|
||||
end
|
||||
local cycle = min + (self.frame + self.Offset) % 1 * maxmin
|
||||
|
||||
if pac.IsNumberValid(cycle) then
|
||||
ent:SetCycle(self.InvertFrames and (1 - cycle) or cycle)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
BUILDER:Register()
|
||||
Reference in New Issue
Block a user