2018-05-02 06:32:59 +08:00
|
|
|
-- Animations are heavily optimized.
|
|
|
|
|
2014-10-02 08:49:54 +08:00
|
|
|
local TEAM_UNDEAD = TEAM_UNDEAD
|
|
|
|
local ACT_MP_STAND_IDLE = ACT_MP_STAND_IDLE
|
2018-05-02 06:32:59 +08:00
|
|
|
local ACT_MP_RUN = ACT_MP_RUN
|
|
|
|
local ACT_MP_WALK = ACT_MP_WALK
|
|
|
|
local ACT_MP_JUMP = ACT_MP_JUMP
|
|
|
|
local ACT_MP_CROUCHWALK = ACT_MP_CROUCHWALK
|
|
|
|
local ACT_MP_CROUCH_IDLE = ACT_MP_CROUCH_IDLE
|
|
|
|
local GESTURE_SLOT_JUMP = GESTURE_SLOT_JUMP
|
|
|
|
local ACT_LAND = ACT_LAND
|
|
|
|
local MOVETYPE_NOCLIP = MOVETYPE_NOCLIP
|
|
|
|
local math_min = math.min
|
|
|
|
local math_max = math.max
|
|
|
|
local CLIENT = CLIENT
|
|
|
|
local PLAYERANIMEVENT_FLINCH_HEAD = PLAYERANIMEVENT_FLINCH_HEAD
|
|
|
|
local CurTime = CurTime
|
|
|
|
local IsValid = IsValid
|
|
|
|
|
|
|
|
local M_Player = FindMetaTable("Player")
|
|
|
|
local M_Entity = FindMetaTable("Entity")
|
|
|
|
local P_Team = M_Player.Team
|
|
|
|
local P_GetZombieClassTable = M_Player.GetZombieClassTable
|
|
|
|
local P_AnimRestartGesture = M_Player.AnimRestartGesture
|
|
|
|
local P_AnimRestartMainSequence = M_Player.AnimRestartMainSequence
|
|
|
|
local P_Crouching = M_Player.Crouching
|
|
|
|
local P_DoFlinchAnim = M_Player.DoFlinchAnim
|
|
|
|
local P_IsCarrying = M_Player.IsCarrying
|
|
|
|
local P_CallZombieFunction = M_Player.CallZombieFunction
|
|
|
|
local P_Alive = M_Player.Alive
|
|
|
|
local E_OnGround = M_Entity.OnGround
|
|
|
|
local E_GetTable = M_Entity.GetTable
|
|
|
|
local E_WaterLevel = M_Entity.WaterLevel
|
|
|
|
local E_SetPlaybackRate = M_Entity.SetPlaybackRate
|
|
|
|
-- These don't get destroyed by __index like player and entity but why not have them here.
|
|
|
|
local M_Vector = FindMetaTable("Vector")
|
|
|
|
local V_Length2D = M_Vector.Length2D
|
|
|
|
local V_Length2DSqr = M_Vector.Length2DSqr
|
|
|
|
local V_LengthSqr = M_Vector.LengthSqr
|
|
|
|
|
|
|
|
local onground, tab, len2d, waterlevel, ideal, override, pt
|
2014-10-02 08:49:54 +08:00
|
|
|
|
|
|
|
function GM:PlayerShouldTaunt(pl, actid)
|
2018-05-02 06:32:59 +08:00
|
|
|
pt = E_GetTable(pl)
|
|
|
|
|
|
|
|
return P_Alive(pl) and (P_Team(pl) == TEAM_HUMAN or P_Team(pl) == TEAM_UNDEAD and P_GetZombieClassTable(pl).CanTaunt) and not IsValid(pt.Revive) and not IsValid(pt.FeignDeath)
|
2014-10-02 08:49:54 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
function GM:CalcMainActivity(pl, velocity)
|
2018-05-02 06:32:59 +08:00
|
|
|
pt = E_GetTable(pl)
|
|
|
|
|
|
|
|
if P_Team(pl) == TEAM_UNDEAD then
|
|
|
|
tab = P_GetZombieClassTable(pl)
|
|
|
|
if tab.CalcMainActivity then
|
|
|
|
ideal, override = tab:CalcMainActivity(pl, velocity)
|
|
|
|
if ideal then
|
|
|
|
return ideal, override
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Handle landing
|
|
|
|
onground = E_OnGround(pl)
|
|
|
|
if onground and not pt.m_bWasOnGround then
|
|
|
|
P_AnimRestartGesture(pl, GESTURE_SLOT_JUMP, ACT_LAND, true)
|
|
|
|
pt.m_bWasOnGround = true
|
|
|
|
end
|
|
|
|
--
|
|
|
|
|
|
|
|
-- Handle jumping
|
|
|
|
-- airwalk more like hl2mp, we airwalk until we have 0 velocity, then it's the jump animation
|
|
|
|
-- underwater we're alright we airwalking
|
|
|
|
waterlevel = E_WaterLevel(pl)
|
|
|
|
if pt.m_bJumping then
|
|
|
|
if pt.m_bFirstJumpFrame then
|
|
|
|
pt.m_bFirstJumpFrame = false
|
|
|
|
P_AnimRestartMainSequence(pl)
|
|
|
|
end
|
|
|
|
|
|
|
|
if waterlevel >= 2 or CurTime() - pt.m_flJumpStartTime > 0.2 and onground then
|
|
|
|
pt.m_bJumping = false
|
|
|
|
pt.m_fGroundTime = nil
|
|
|
|
P_AnimRestartMainSequence(pl)
|
|
|
|
else
|
|
|
|
return ACT_MP_JUMP, -1
|
|
|
|
end
|
|
|
|
elseif not onground and waterlevel <= 0 then
|
|
|
|
if not pt.m_fGroundTime then
|
|
|
|
pt.m_fGroundTime = CurTime()
|
|
|
|
elseif CurTime() > pt.m_fGroundTime and V_Length2D(velocity) < 0.5 then
|
|
|
|
pt.m_bJumping = true
|
|
|
|
pt.m_bFirstJumpFrame = false
|
|
|
|
pt.m_flJumpStartTime = 0
|
2014-10-02 08:49:54 +08:00
|
|
|
end
|
|
|
|
end
|
2018-05-02 06:32:59 +08:00
|
|
|
--
|
|
|
|
|
|
|
|
-- Handle ducking
|
|
|
|
if P_Crouching(pl) then
|
|
|
|
if V_Length2DSqr(velocity) >= 1 then
|
|
|
|
return ACT_MP_CROUCHWALK, -1
|
|
|
|
end
|
2014-10-02 08:49:54 +08:00
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
return ACT_MP_CROUCH_IDLE, -1
|
|
|
|
end
|
|
|
|
--
|
|
|
|
|
|
|
|
-- Handle swimming
|
|
|
|
if not onground and waterlevel >= 2 then
|
|
|
|
return ACT_MP_SWIM, -1
|
|
|
|
end
|
|
|
|
--
|
|
|
|
|
|
|
|
len2d = V_Length2DSqr(velocity)
|
|
|
|
if len2d >= 22500 then -- 150^2
|
|
|
|
return ACT_MP_RUN, -1
|
|
|
|
end
|
|
|
|
|
|
|
|
if len2d >= 1 then
|
|
|
|
return ACT_MP_WALK, -1
|
|
|
|
end
|
|
|
|
|
|
|
|
return ACT_MP_STAND_IDLE, -1
|
2014-10-02 08:49:54 +08:00
|
|
|
end
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
--local wep
|
|
|
|
local len
|
|
|
|
local rate
|
2014-10-02 08:49:54 +08:00
|
|
|
function GM:UpdateAnimation(pl, velocity, maxseqgroundspeed)
|
2018-05-02 06:32:59 +08:00
|
|
|
if P_CallZombieFunction(pl, "UpdateAnimation", velocity, maxseqgroundspeed) then return end
|
|
|
|
|
|
|
|
len = V_LengthSqr(velocity)
|
2014-10-02 08:49:54 +08:00
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
if len > 1 then
|
|
|
|
rate = math_min(len / maxseqgroundspeed ^ 2, 2)
|
|
|
|
else
|
|
|
|
rate = 1
|
2014-10-02 08:49:54 +08:00
|
|
|
end
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
-- if we're under water we want to constantly be swimming..
|
|
|
|
if E_WaterLevel(pl) >= 2 then
|
|
|
|
rate = math_max(rate, 0.5)
|
|
|
|
end
|
|
|
|
|
|
|
|
E_SetPlaybackRate(pl, rate)
|
|
|
|
|
|
|
|
if CLIENT then
|
|
|
|
GAMEMODE:GrabEarAnimation(pl)
|
|
|
|
--GAMEMODE:MouthMoveAnimation(pl) -- Broken?
|
|
|
|
end
|
2014-10-02 08:49:54 +08:00
|
|
|
end
|
|
|
|
|
2018-05-02 06:32:59 +08:00
|
|
|
local eact
|
2014-10-02 08:49:54 +08:00
|
|
|
function GM:DoAnimationEvent(pl, event, data)
|
2018-05-02 06:32:59 +08:00
|
|
|
eact = P_CallZombieFunction(pl, "DoAnimationEvent", event, data)
|
|
|
|
if eact then return eact end
|
|
|
|
|
|
|
|
if event == PLAYERANIMEVENT_FLINCH_HEAD then
|
|
|
|
return P_DoFlinchAnim(pl, data)
|
|
|
|
end
|
|
|
|
|
|
|
|
return self.BaseClass:DoAnimationEvent(pl, event, data)
|
2014-10-02 08:49:54 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
local CarryingActivityTranslate = {}
|
|
|
|
CarryingActivityTranslate[ACT_MP_STAND_IDLE] = ACT_HL2MP_IDLE_SLAM
|
|
|
|
CarryingActivityTranslate[ACT_MP_WALK] = ACT_HL2MP_IDLE_SLAM + 1
|
|
|
|
CarryingActivityTranslate[ACT_MP_RUN] = ACT_HL2MP_IDLE_SLAM + 2
|
|
|
|
CarryingActivityTranslate[ACT_MP_CROUCH_IDLE] = ACT_HL2MP_IDLE_SLAM + 3
|
|
|
|
CarryingActivityTranslate[ACT_MP_CROUCHWALK] = ACT_HL2MP_IDLE_SLAM + 4
|
|
|
|
CarryingActivityTranslate[ACT_MP_ATTACK_STAND_PRIMARYFIRE] = ACT_HL2MP_IDLE_SLAM + 5
|
|
|
|
CarryingActivityTranslate[ACT_MP_ATTACK_CROUCH_PRIMARYFIRE] = ACT_HL2MP_IDLE_SLAM + 5
|
|
|
|
CarryingActivityTranslate[ACT_MP_RELOAD_STAND] = ACT_HL2MP_IDLE_SLAM + 6
|
|
|
|
CarryingActivityTranslate[ACT_MP_RELOAD_CROUCH] = ACT_HL2MP_IDLE_SLAM + 6
|
|
|
|
CarryingActivityTranslate[ACT_MP_JUMP] = ACT_HL2MP_IDLE_SLAM + 7
|
|
|
|
CarryingActivityTranslate[ACT_RANGE_ATTACK1] = ACT_HL2MP_IDLE_SLAM + 8
|
|
|
|
|
|
|
|
function GM:TranslateActivity(pl, act)
|
2018-05-02 06:32:59 +08:00
|
|
|
if P_IsCarrying(pl) then
|
2014-10-02 08:49:54 +08:00
|
|
|
return CarryingActivityTranslate[act] or act
|
|
|
|
end
|
|
|
|
|
|
|
|
return self.BaseClass:TranslateActivity(pl, act)
|
|
|
|
end
|