Rewrite Benny Item System

Stats can now be indexed by indexing the Entity
Also fixes player animations in MP TP
- Animations not being called on other players
- Aim pitch poseparameter
Category names are translated
Handler getting is way better I think.
This commit is contained in:
Fesiug 2024-10-05 17:41:47 -04:00
parent 60c7a15272
commit 3f6f5464b9
Signed by: Fesiug
GPG Key ID: 374BFF45E1EEF243
11 changed files with 517 additions and 1209 deletions

View File

@ -11,14 +11,14 @@ ENT.BennyItem = true
ENT.AutomaticFrameAdvance = true
function ENT:Initialize()
self:SetModel( self.Class.Model or "models/weapons/w_357.mdl" )
self:SetModel( self.Model or "models/weapons/w_357.mdl" )
if SERVER then
self:PhysicsInit( SOLID_VPHYSICS )
self:SetCollisionGroup( COLLISION_GROUP_WEAPON )
self:GetPhysicsObject():Wake()
--self:GetPhysicsObject():Wake()
end
self.Class:Initialize( self )
self:EntInitialize( self )
end
if SERVER then
@ -103,7 +103,7 @@ local function recurse( modify, includer )
end
function ENT:SetupDataTables()
local NWVars = { ["Float"] = { "AnimStartTime", "AnimEndTime" } }
local NWVars = { ["Entity"] = { "Handler" } }
recurse( NWVars, self.ID )
for varname, varlist in pairs(NWVars) do
--local numba = 0

View File

@ -29,22 +29,14 @@ function SWEP:SetupDataTables()
self:NetworkVar( "Entity", "DesireL" )
end
function SWEP:ItemR( run )
function SWEP:ItemR( key )
local active = self:GetActiveR()
if run and active:IsValid() then
return active.Class[run]( active.Class, active, self )
else
return active:IsValid() and active or false
end
return active:IsValid() and active or false
end
function SWEP:ItemL( run )
function SWEP:ItemL( key )
local active = self:GetActiveL()
if run and active:IsValid() then
active.Class[run]( active.Class, active, self )
else
return active:IsValid() and active or false
end
return active:IsValid() and active or false
end
function SWEP:Initialize()
@ -72,9 +64,9 @@ function SWEP:SetActive( ent )
if ent:GetOwner() != p then return false end
--if self:GetActiveR():IsValid() then self:Deactive() end
self:SetActiveR( ent )
if self:ItemR() then
self:ItemR( "Deploy" )
self:ItemR():SetNoDraw( false )
if self:GetActiveR():IsValid() then
self:GetActiveR():Deploy()
self:GetActiveR():SetNoDraw( false )
end
return true
end
@ -84,21 +76,21 @@ end
function SWEP:PrimaryAttack()
local p = self:GetOwner()
if self:ItemR() then
self:ItemR("Attack")
if self:GetActiveR():IsValid() then
self:GetActiveR():Attack()
end
end
function SWEP:Reload()
if self:ItemR() then
self:ItemR("Reload")
if self:GetActiveR():IsValid() then
self:GetActiveR():Reload()
end
end
function SWEP:SecondaryAttack()
local p = self:GetOwner()
if self:ItemR() then
self:ItemR("AttackAlt")
if self:GetActiveR():IsValid() then
self:GetActiveR():AttackAlt()
end
end
@ -138,6 +130,7 @@ function SWEP:EquipItem( ent )
ent:SetNoDraw( true )
ent:SetParent( p )
ent:SetOwner( p )
ent:SetHandler( self )
ent:SetLocalPos( vector_origin )
ent:SetLocalAngles( angle_zero )
ent:SetAcquisition( CurTime() )
@ -166,6 +159,7 @@ function SWEP:DropItem()
ent:SetParent( NULL )
ent:SetOwner( NULL )
ent:SetHandler( NULL )
ent:RemoveEFlags( EFL_KEEP_ON_RECREATE_ENTITIES )
ent:RemoveEffects( EF_BONEMERGE )
@ -205,7 +199,7 @@ function SWEP:Think()
if DesireR != ActiveR then
if ActiveR_Valid then
if ActiveR:GetHolsterIn() == 0 then
ActiveR.Class.Holster( ActiveR.Class, ActiveR, self )
ActiveR:StartHolster()
else
-- Waiting for holster to finish
end
@ -216,7 +210,7 @@ function SWEP:Think()
end
else
if ActiveR_Valid and ActiveR:GetHolsterIn() != 0 then
ActiveR.Class.UndoHolster( ActiveR.Class, ActiveR, self )
ActiveR:CancelHolster()
end
end
@ -228,7 +222,7 @@ function SWEP:Think()
end
else
if self:GetActiveR() != NULL then
ActiveR.Class.Drop( ActiveR.Class, ActiveR, self )
ActiveR:Drop()
if SERVER then
self:DropItem()
end
@ -243,15 +237,15 @@ function SWEP:Think()
if p:KeyPressed(IN_ALT2) then
end
if p:KeyPressed(IN_GRENADE1) then
if self:ItemR() and self:ItemR().Class.Alt then
self:ItemR("Alt")
if self:GetActiveR():IsValid() and self:GetActiveR().Alt then
self:GetActiveR():Alt()
end
end
if p:KeyPressed(IN_GRENADE2) then
end
if self:ItemR() then
self:ItemR("Think")
if self:GetActiveR():IsValid() then
self:GetActiveR():Think()
end
else
print( self, "Thinking without an owner." )

View File

@ -86,7 +86,7 @@ function GM:CalcView( ply, pos, ang, fov )
ply:SetupBones()
local bm = ply:GetBoneMatrix(ply:LookupBone("DEF-spine.003"))
view.origin = bm:GetTranslation()
view.origin:Add( vector_up*10 )
view.origin:Add( vector_up*8 )
if ply:GetLayerSequence( GESTURE_SLOT_JUMP ) == ply:LookupSequence("dive_end_handgun") then
local progress = ply:GetLayerCycle( GESTURE_SLOT_JUMP )
@ -126,17 +126,20 @@ function GM:CalcView( ply, pos, ang, fov )
ply:ManipulateBoneScale( bid, Vector(1, 1, 1) )
local bid = ply:LookupBone("DEF-spine.005")
ply:ManipulateBoneScale( bid, Vector(1, 1, 1) )
--local bid = ply:LookupBone("Weapon")
--ply:ManipulateBonePosition( bid, vector_origin )
lastfp = fp
-- print("show")
elseif !lastfp and fp then
local bid = ply:LookupBone("DEF-spine.006")
ply:ManipulateBoneScale( bid, vector_origin )
local bid = ply:LookupBone("DEF-spine.005")
ply:ManipulateBoneScale( bid, vector_origin )
--local bid = ply:LookupBone("Weapon")
--ply:ManipulateBonePosition( bid, Vector(-3, 1, 0) )
lastfp = fp
-- print("hide")
end
return view
end
@ -157,7 +160,6 @@ hook.Add( "OnRequestFullUpdate", "Benny_OnRequestFullUpdate_CameraFP", function(
if !bid then return end
ply:ManipulateBoneScale( bid, Vector(1, 1, 1) )
lastfp = fp
-- print("fullupdate: show")
elseif fp then
local bid = ply:LookupBone("DEF-spine.006")
if !bid then return end
@ -166,7 +168,6 @@ hook.Add( "OnRequestFullUpdate", "Benny_OnRequestFullUpdate_CameraFP", function(
if !bid then return end
ply:ManipulateBoneScale( bid, vector_origin )
lastfp = fp
-- print("fullupdate: hide")
end
end)
end

View File

@ -260,7 +260,7 @@ local function OpenDebugMenu()
if !categories[category] then
local cate = opt:Add("DCollapsibleCategory")
cate:Dock(TOP)
cate:SetLabel(category)
cate:SetLabel( l8( "#ItemCategory." .. category .. ".Name" ) )
local plist = vgui.Create("DPanelList")
cate:SetContents(plist)
categories[category] = plist
@ -272,7 +272,7 @@ local function OpenDebugMenu()
if !categories[idata.Category] then
local cate = opt:Add("DCollapsibleCategory")
cate:Dock(TOP)
cate:SetLabel(idata.Category)
cate:SetLabel( l8( "#ItemCategory." .. idata.Category .. ".Name" ) )
local plist = vgui.Create("DPanelList")
cate:SetContents(plist)
categories[idata.Category] = plist

View File

@ -175,11 +175,6 @@ do
end)
end
-- breaks GESTURE_SLOT_ATTACK_AND_RELOAD and I can't fucking have that
hook.Add("DoAnimationEvent", "Benny_DoAnimationEvent_FixAnimations", function( ply, event, data )
return ACT_INVALID
end)
hook.Add( "PlayerSwitchWeapon", "Benny_PlayerSwitchWeapon_Goat", function( ply, old, ent )
if ent.BennyItemHandler then return true end -- what happened?
local wep = ply:HandlerCheck()

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
do -- Base
local ITEM, Base = CreateItem( "base" )
ITEM.PrintName = "Item Base"
ITEM.Description = "Testing testing"
ITEM.Category = "base"
ITEM.Model = bModel("weapons/test_g18")
ITEM.DefaultBodygroups = {}
ITEM.HoldType = "handgun"
ITEM.Vars = {
["Float"] = {
"Acquisition",
"HolsterIn",
},
}
ITEM.DeploySound = bSound("dev/magpouch.ogg")
ITEM.StartHolsterSound = bSound("dev/magpouch_replace_small.ogg")
ITEM.FinishHolsterSound = bSound("dev/holster.ogg")
ITEM.CancelHolsterSound = bSound("dev/grab.ogg")
function ITEM:EntInitialize()
print( self )
for k, v in ipairs(self.DefaultBodygroups) do
if v then
self:SetBodygroup( k-1, v )
end
end
end
function ITEM:Sound( soundName, soundLevel, pitchPercent, volume, channel, soundFlags, dsp, filter )
local emiton = self
if self:GetHandler():IsValid() then
emiton = self:GetHandler()
end
emiton:EmitSound( soundName, soundLevel, pitchPercent, volume, channel, soundFlags, dsp )
end
function ITEM:Attack() end
function ITEM:AttackAlt() end
function ITEM:Think()
if self:GetHolsterIn() != 0 and self:GetHolsterIn() <= CurTime() then
self:FinishHolster()
self:SetHolsterIn( 0 )
end
end
function ITEM:PlayerAnimation( seqname )
local p = self:GetOwner()
p:DoAnimationEvent( p:LookupSequence( seqname ) )
end
function ITEM:EntThink() end
function ITEM:EntPhysicsCollide() end
function ITEM:Reload() end
function ITEM:Drop() end
function ITEM:Deploy()
self:Sound( self.DeploySound, 70, 100, 0.4 )
end
function ITEM:StartHolster()
self:Sound( self.StartHolsterSound, 70, 100, 0.4 )
self:SetHolsterIn( CurTime() + 0.25 )
end
function ITEM:FinishHolster()
self:Sound( self.FinishHolsterSound, 70, 100, 0.4, CHAN_STATIC )
self:GetHandler():SetActiveR( NULL )
self:SetNoDraw( true )
end
function ITEM:CancelHolster()
self:SetHolsterIn( 0 )
self:Sound( self.CancelHolsterSound, 70, 100, 0.4 )
end
end

View File

@ -0,0 +1,268 @@
do -- Base Firearm
local AnimationLookup = {
["fire"] = {
["handgun"] = "handgun_fire",
["rifle"] = "rifle_fire",
},
["reload"] = {
["handgun"] = "handgun_reload",
["rifle"] = "rifle_reload",
},
["reload_rack"] = {
["handgun"] = "handgun_reload_rack",
["rifle"] = "rifle_reload_rack",
},
["reload_insert"] = {
["handgun"] = "handgun_reload_insert",
["rifle"] = "rifle_reload_insert",
},
["deploy"] = {
["handgun"] = "handgun_deploy",
["rifle"] = "rifle_deploy",
},
["holster"] = {
["handgun"] = "handgun_holster",
["rifle"] = "handgun_holster",
},
}
local ITEM, Base = CreateItem( "base_firearm", "base" )
ITEM.PrintName = "Firearm Base"
ITEM.Description = "Testing testing"
ITEM.Category = "base"
ITEM.Vars = {
["Bool"] = {
"Loaded",
},
["Int"] = {
"Clip",
"BurstCount",
"Firemode",
"ReloadStage",
},
["Float"] = {
"Delay",
"DelayBurst",
"RefillTime",
"Accuracy_Reset",
"Accuracy_Amount",
"DelayReload",
},
}
ITEM.Delay = 0.2
ITEM.Pellets = 1
ITEM.Accuracy = 1
ITEM.ClipSize = 15
ITEM.BurstCount = math.huge
ITEM.BurstRunaway = false
ITEM.BurstAuto = false
ITEM.BurstDelay = 0
ITEM.FireSound = bSound("weapons/m16a2/01.ogg") -- can be an iterative table
ITEM.MagOutSound = bSound("weapons/m16a2/magout.ogg")
ITEM.MagInSound = bSound("weapons/m16a2/magin.ogg")
ITEM.BoltDropSound = bSound("weapons/m16a2/cock.ogg")
ITEM.BoltPullSound = bSound("weapons/fnc/cock.ogg")
function ITEM:EntInitialize()
Base.EntInitialize( self )
end
function ITEM:Attack()
if self:GetClip() <= 0 then return end
if self:GetDelay() > CurTime() then return end
if self:GetDelayBurst() > CurTime() then return end
if self:GetBurstCount() >= self.BurstCount then return end
if self:GetHolsterIn() != 0 then return end
self:SetDelay( CurTime() + self.Delay )
self:SetClip( self:GetClip() - 1 )
self:SetBurstCount( self:GetBurstCount() + 1 )
self:Sound( istable(self.FireSound) and TSelShared(self.FireSound, "FireSound") or self.FireSound )
local p = self:GetOwner()
local h = self:GetHandler()
if p:IsValid() then
self:PlayerAnimation( AnimationLookup["fire"][self.HoldType] )
end
self:PlayAnimation( self:LookupSequence("fire") )
p:LagCompensation(true)
h:FireBullets( {
Attacker = p,
Damage = 1,
Force = 5,
Tracer = 0,
Num = self.Pellets,
Dir = p:GetAimVector(),
Src = p:GetShootPos(),
Spread = Vector( acc, acc, 0 ),
} )
p:LagCompensation(false)
end
function ITEM:AttackAlt() end
function ITEM:Think()
local InProcess = self:GetBurstCount() > 0
local Topped = self:GetBurstCount() == self.BurstCount
local Runaway = self.BurstRunaway
local BAuto = self.BurstAuto
local Firedown = false
local p = self:GetOwner()
if IsValid(p) then
Firedown = p:KeyDown( IN_ATTACK )
end
if Runaway and InProcess and !Topped then
self:Attack()
else
if !Firedown then
if !Topped and InProcess then
self:SetDelayBurst( CurTime() + self.BurstDelay )
end
self:SetBurstCount( 0 )
end
if Topped and BAuto then
self:SetBurstCount( 0 )
self:SetDelayBurst( CurTime() + self.BurstDelay )
end
end
if self:GetRefillTime() != 0 and self:GetRefillTime() <= CurTime() then
self:SetClip( class.ClipSize )
self:SetRefillTime( 0 )
end
Base.Think( self )
end
function ITEM:Deploy()
self:SetDelay( CurTime() + 0.5 )
self:PlayerAnimation( AnimationLookup["deploy"][self.HoldType] )
Base.Deploy( self )
end
function ITEM:Reload()
if self:GetDelay() > CurTime() then return end
if self:GetHolsterIn() != 0 then return end
local p = self:GetOwner()
local time = 0.4
if self:GetReloadStage() == 0 then -- Mag loaded
-- Unload the mag
self:SetReloadStage(1)
self:SetClip( 0 )
self:Sound( self.MagOutSound, 70, 100, 0.4 )
self:PlayerAnimation( AnimationLookup["reload"][self.HoldType] )
self:PlayAnimation( self:LookupSequence( "magout" ) )
time = 0.4
else
-- Load it
self:SetReloadStage(0)
self:SetClip( self.ClipSize )
self:Sound( self.MagInSound, 70, 100, 0.4 )
self:PlayerAnimation( AnimationLookup["reload_insert"][self.HoldType] )
self:PlayAnimation( self:LookupSequence( "magin" ) )
time = 0.8
end
self:SetDelay( CurTime() + time )
end
function ITEM:StartHolster()
self:SetDelay( CurTime() + 0.25 )
self:PlayerAnimation( AnimationLookup["holster"][self.HoldType] )
Base.StartHolster( self )
end
function ITEM:FinishHolster()
Base.FinishHolster( self )
end
function ITEM:CancelHolster()
self:PlayerAnimation( AnimationLookup["deploy"][self.HoldType] )
Base.CancelHolster( self )
end
do -- Handguns
do -- G18
local ITEM, Base = CreateItem( "g18", "base_firearm" )
ITEM.PrintName = "#Item.g18.Name"
ITEM.Description = "#Item.g18.Description"
ITEM.Category = "pistol"
ITEM.Model = bModel("weapons/test_g18")
ITEM.HoldType = "handgun"
ITEM.BurstCount = math.huge
ITEM.Delay = (60/1000)
ITEM.ClipSize = 33
ITEM.FireSound = {
bSound("weapons/glock/01.ogg"),
bSound("weapons/glock/02.ogg"),
bSound("weapons/glock/03.ogg"),
}
ITEM.MagOutSound = bSound("weapons/glock/magout.ogg")
ITEM.MagInSound = bSound("weapons/glock/magin.ogg")
ITEM.BoltDropSound = bSound("weapons/glock/cock.ogg")
ITEM.BoltPullSound = bSound("weapons/glock/cock.ogg")
end
do -- MK23
local ITEM, Base = CreateItem( "mk23", "base_firearm" )
ITEM.PrintName = "#Item.mk23.Name"
ITEM.Description = "#Item.mk23.Description"
ITEM.Category = "pistol"
ITEM.Model = bModel("weapons/test_mk23")
ITEM.DefaultBodygroups = { false, false, 1 }
ITEM.HoldType = "handgun"
ITEM.BurstCount = 1
ITEM.Delay = (60/320)
ITEM.ClipSize = 12
ITEM.FireSound = {
bSound("weapons/usp/sup_01.ogg"),
bSound("weapons/usp/sup_02.ogg"),
bSound("weapons/usp/sup_03.ogg"),
}
ITEM.MagOutSound = bSound("weapons/usp/magout.ogg")
ITEM.MagInSound = bSound("weapons/usp/magin.ogg")
ITEM.BoltDropSound = bSound("weapons/usp/slidedrop.ogg")
ITEM.BoltPullSound = bSound("weapons/glock/cock.ogg")
end
end
do -- Rifles
do -- M16A2
local ITEM, Base = CreateItem( "m16a2", "base_firearm" )
ITEM.PrintName = "#Item.m16a2.Name"
ITEM.Description = "#Item.m16a2.Description"
ITEM.Category = "assaultrifle"
ITEM.Model = bModel("weapons/test_m16a2")
ITEM.DefaultBodygroups = { false, false, 1 }
ITEM.HoldType = "rifle"
ITEM.BurstCount = 3
ITEM.BurstRunaway = true
ITEM.BurstAuto = true
ITEM.BurstDelay = 0.2
ITEM.Delay = (60/1050)
ITEM.ClipSize = 30
ITEM.FireSound = {
bSound("weapons/m16a2/01.ogg"),
bSound("weapons/m16a2/02.ogg"),
bSound("weapons/m16a2/03.ogg"),
}
ITEM.MagOutSound = bSound("weapons/m16a2/magout.ogg")
ITEM.MagInSound = bSound("weapons/m16a2/magin.ogg")
ITEM.BoltDropSound = bSound("weapons/m16a2/cock.ogg")
ITEM.BoltPullSound = bSound("weapons/fnc/cock.ogg")
end
end
end

View File

@ -134,6 +134,25 @@ L["Gamemode.dem.Description"] = "One half tries to destroy the other halves o
L["Gamemode.hp.Name"] = "Hardpoint"
L["Gamemode.hp.Description"] = "Several teams fight to hold a singular capture point for the longest amount of time."
-- Categories
L["ItemCategory.pistol.Name"] = "Handgun"
L["ItemCategory.pistol.Description"] = "Lightweight sidearm. Drawn and reloaded quickly."
L["ItemCategory.smg.Name"] = "Sub-machine Gun"
L["ItemCategory.smg.Description"] = "Lightweight automatic weapon. Fires pistol cartridges."
L["ItemCategory.assaultrifle.Name"] = "Assault Rifle"
L["ItemCategory.assaultrifle.Description"] = "High stopping power, but poor maneuverability."
L["ItemCategory.machinegun.Name"] = "Machine Gun"
L["ItemCategory.machinegun.Description"] = "Automatic weapon designed for sustained fire."
L["ItemCategory.shotgun.Name"] = "Shotgun"
L["ItemCategory.shotgun.Description"] = "Great in close-quarters combat."
L["ItemCategory.utility.Name"] = "Utility"
L["ItemCategory.utility.Description"] = "Throwables and deployables."
-- Teams
L["Team.cia.Name"] = "CIA"
L["Team.cia.Description"] = "CIA black ops, coverup crew"

View File

@ -189,7 +189,13 @@ function PT:HandlerCheck()
return ( wep:IsValid() and wep:GetClass() == "itemhandler" and wep.GetActiveR ) and wep or false
end
-- Temporary
-- breaks GESTURE_SLOT_ATTACK_AND_RELOAD and I can't fucking have that
hook.Add("DoAnimationEvent", "Benny_DoAnimationEvent_FixAnimations", function( p, event, data )
if event == PLAYERANIMEVENT_CUSTOM_GESTURE then
p:AddVCDSequenceToGestureSlot( GESTURE_SLOT_ATTACK_AND_RELOAD, data, 0, true )
end
return ACT_INVALID
end)
function GM:UpdateAnimation( ply, vel, maxseqgroundspeed )
ply:SetPlaybackRate( 1 )
@ -230,7 +236,10 @@ function GM:UpdateAnimation( ply, vel, maxseqgroundspeed )
magic = magic * 0.75
ply:SetPoseParameter( "aim_p", -ply:EyeAngles().p/90 )
local ea = ply:EyeAngles()
ea:Normalize()
ply:SetPoseParameter( "aim_p", -ea.p/90 )
ply:SetPoseParameter( "aim_y", 0 )--magic/90 )

View File

@ -42,6 +42,18 @@ function TSelShared( tbl, seed )
return tbl[math.Round( util.SharedRandom( seed, 1, #tbl ) )]
end
function bModel( input )
local str = "models/benny/" .. input .. ".mdl"
util.PrecacheModel( str )
return str
end
function bSound( input )
local str = "benny/" .. input
util.PrecacheSound( str )
return str
end
-- Language might want to be loaded first
-- Otherwise things will fail to call 'l8'
AC("language.lua")