Initial commit
This commit is contained in:
252
lua/weapons/weapon_fists.lua
Normal file
252
lua/weapons/weapon_fists.lua
Normal file
@@ -0,0 +1,252 @@
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
SWEP.PrintName = "#weapon_fists"
|
||||
SWEP.Author = "Kilburn, robotboy655, MaxOfS2D & Tenrys"
|
||||
SWEP.Purpose = "Well we sure as hell didn't use guns! We would just wrestle Hunters to the ground with our bare hands! I used to kill ten, twenty a day, just using my fists."
|
||||
|
||||
SWEP.Slot = 0
|
||||
SWEP.SlotPos = 4
|
||||
|
||||
SWEP.Spawnable = true
|
||||
|
||||
SWEP.ViewModel = Model( "models/weapons/c_arms.mdl" )
|
||||
SWEP.WorldModel = ""
|
||||
SWEP.ViewModelFOV = 54
|
||||
SWEP.UseHands = true
|
||||
|
||||
SWEP.Primary.ClipSize = -1
|
||||
SWEP.Primary.DefaultClip = -1
|
||||
SWEP.Primary.Automatic = true
|
||||
SWEP.Primary.Ammo = ""
|
||||
|
||||
SWEP.Secondary.ClipSize = -1
|
||||
SWEP.Secondary.DefaultClip = -1
|
||||
SWEP.Secondary.Automatic = true
|
||||
SWEP.Secondary.Ammo = ""
|
||||
|
||||
SWEP.DrawAmmo = false
|
||||
|
||||
SWEP.SwingSound = Sound( "WeaponFrag.Throw" ) -- Sound of the fists swinging
|
||||
SWEP.HitSound = Sound( "Flesh.ImpactHard" ) -- Sound of the fists hitting an entity
|
||||
|
||||
SWEP.HitDistance = 48 -- Distance of the punch
|
||||
SWEP.HitDelay = 0.2 -- Delay between the punch being thrown and hitting an object
|
||||
SWEP.HitForceScale = 80 -- Scalar force of the punch
|
||||
SWEP.SwingCooldown = 0.9 -- Cooldown between punches
|
||||
SWEP.ComboCount = 2 -- Number of successive punches needed for a combo punch
|
||||
SWEP.ComboResetTime = 0.1 -- Time between the next punch being available and the combo couner resetting
|
||||
|
||||
-- Bounds of the punch's hull trace
|
||||
SWEP.HitSize = {
|
||||
Min = Vector( -10, -10, -8 ),
|
||||
Max = Vector( 10, 10, 8 )
|
||||
}
|
||||
SWEP.HitDamage = { 8, 12 } -- Normal punch damage
|
||||
SWEP.ComboDamage = { 12, 24 } -- Combo punch damage
|
||||
|
||||
function SWEP:Initialize()
|
||||
|
||||
self:SetHoldType( "fist" )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:SetupDataTables()
|
||||
|
||||
self:NetworkVar( "Float", 0, "NextMeleeAttack" )
|
||||
self:NetworkVar( "Float", 1, "NextIdle" )
|
||||
self:NetworkVar( "Int", 2, "Combo" )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:UpdateNextIdle()
|
||||
|
||||
local vm = self:GetOwner():GetViewModel()
|
||||
self:SetNextIdle( CurTime() + vm:SequenceDuration() / vm:GetPlaybackRate() )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:PrimaryAttack( right )
|
||||
|
||||
local owner = self:GetOwner()
|
||||
|
||||
owner:SetAnimation( PLAYER_ATTACK1 )
|
||||
|
||||
local anim = "fists_left"
|
||||
if ( right ) then anim = "fists_right" end
|
||||
if ( self:GetCombo() >= self.ComboCount ) then
|
||||
anim = "fists_uppercut"
|
||||
end
|
||||
|
||||
local vm = owner:GetViewModel()
|
||||
vm:SendViewModelMatchingSequence( vm:LookupSequence( anim ) )
|
||||
|
||||
self:EmitSound( self.SwingSound )
|
||||
|
||||
self:UpdateNextIdle()
|
||||
self:SetNextMeleeAttack( CurTime() + self.HitDelay )
|
||||
|
||||
self:SetNextPrimaryFire( CurTime() + self.SwingCooldown )
|
||||
self:SetNextSecondaryFire( CurTime() + self.SwingCooldown )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
|
||||
self:PrimaryAttack( true )
|
||||
|
||||
end
|
||||
|
||||
local phys_pushscale = GetConVar( "phys_pushscale" )
|
||||
|
||||
function SWEP:DealDamage()
|
||||
|
||||
local owner = self:GetOwner()
|
||||
|
||||
local anim = self:GetSequenceName(owner:GetViewModel():GetSequence())
|
||||
|
||||
owner:LagCompensation( true )
|
||||
|
||||
local tr = util.TraceLine( {
|
||||
start = owner:GetShootPos(),
|
||||
endpos = owner:GetShootPos() + owner:GetAimVector() * self.HitDistance,
|
||||
filter = owner,
|
||||
mask = MASK_SHOT_HULL
|
||||
} )
|
||||
|
||||
if ( !IsValid( tr.Entity ) ) then
|
||||
tr = util.TraceHull( {
|
||||
start = owner:GetShootPos(),
|
||||
endpos = owner:GetShootPos() + owner:GetAimVector() * self.HitDistance,
|
||||
filter = owner,
|
||||
mins = self.HitSize.Min,
|
||||
maxs = self.HitSize.Max,
|
||||
mask = MASK_SHOT_HULL
|
||||
} )
|
||||
end
|
||||
|
||||
-- We need the second part for single player because SWEP:Think is ran shared in SP
|
||||
if ( tr.Hit and !( game.SinglePlayer() and CLIENT ) ) then
|
||||
self:EmitSound( self.HitSound )
|
||||
end
|
||||
|
||||
local hit = false
|
||||
local scale = phys_pushscale:GetFloat()
|
||||
|
||||
if ( SERVER and IsValid( tr.Entity ) and ( tr.Entity:IsNPC() or tr.Entity:IsPlayer() or tr.Entity:Health() > 0 ) ) then
|
||||
local dmginfo = DamageInfo()
|
||||
|
||||
local attacker = owner
|
||||
if ( !IsValid( attacker ) ) then attacker = self end
|
||||
dmginfo:SetAttacker( attacker )
|
||||
|
||||
dmginfo:SetInflictor( self )
|
||||
dmginfo:SetWeapon( self )
|
||||
|
||||
local dmg = self.HitDamage
|
||||
|
||||
if ( anim == "fists_left" ) then
|
||||
dmginfo:SetDamageForce( owner:GetRight() * 4912 * scale + owner:GetForward() * 9998 * scale ) -- Yes we need those specific numbers
|
||||
elseif ( anim == "fists_right" ) then
|
||||
dmginfo:SetDamageForce( owner:GetRight() * -4912 * scale + owner:GetForward() * 9989 * scale )
|
||||
elseif ( anim == "fists_uppercut" ) then
|
||||
dmginfo:SetDamageForce( owner:GetUp() * 5158 * scale + owner:GetForward() * 10012 * scale )
|
||||
dmg = self.ComboDamage
|
||||
end
|
||||
|
||||
dmginfo:SetDamage( istable( dmg ) and math.random( dmg[ 1 ], dmg[ 2 ] ) or dmg )
|
||||
|
||||
SuppressHostEvents( NULL ) -- Let the breakable gibs spawn in multiplayer on client
|
||||
tr.Entity:TakeDamageInfo( dmginfo )
|
||||
SuppressHostEvents( owner )
|
||||
|
||||
hit = true
|
||||
|
||||
end
|
||||
|
||||
if ( IsValid( tr.Entity ) ) then
|
||||
local phys = tr.Entity:GetPhysicsObject()
|
||||
if ( IsValid( phys ) ) then
|
||||
phys:ApplyForceOffset( owner:GetAimVector() * self.HitForceScale * phys:GetMass() * scale, tr.HitPos )
|
||||
end
|
||||
end
|
||||
|
||||
if ( SERVER ) then
|
||||
if ( hit and anim != "fists_uppercut" ) then
|
||||
self:SetCombo( self:GetCombo() + 1 )
|
||||
else
|
||||
self:SetCombo( 0 )
|
||||
end
|
||||
end
|
||||
|
||||
owner:LagCompensation( false )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:OnDrop()
|
||||
|
||||
self:Remove() -- You can't drop fists
|
||||
|
||||
end
|
||||
|
||||
local sv_deployspeed = GetConVar( "sv_defaultdeployspeed" )
|
||||
|
||||
function SWEP:Deploy()
|
||||
|
||||
local speed = sv_deployspeed:GetFloat()
|
||||
|
||||
local vm = self:GetOwner():GetViewModel()
|
||||
vm:SendViewModelMatchingSequence( vm:LookupSequence( "fists_draw" ) )
|
||||
vm:SetPlaybackRate( speed )
|
||||
|
||||
self:SetNextPrimaryFire( CurTime() + vm:SequenceDuration() / speed )
|
||||
self:SetNextSecondaryFire( CurTime() + vm:SequenceDuration() / speed )
|
||||
self:UpdateNextIdle()
|
||||
|
||||
if ( SERVER ) then
|
||||
self:SetCombo( 0 )
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Holster()
|
||||
|
||||
self:SetNextMeleeAttack( 0 )
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Think()
|
||||
|
||||
local vm = self:GetOwner():GetViewModel()
|
||||
local curtime = CurTime()
|
||||
local idletime = self:GetNextIdle()
|
||||
|
||||
if ( idletime > 0 and curtime > idletime ) then
|
||||
|
||||
vm:SendViewModelMatchingSequence( vm:LookupSequence( "fists_idle_0" .. math.random( 1, 2 ) ) )
|
||||
|
||||
self:UpdateNextIdle()
|
||||
|
||||
end
|
||||
|
||||
local meleetime = self:GetNextMeleeAttack()
|
||||
|
||||
if ( meleetime > 0 and curtime > meleetime ) then
|
||||
|
||||
self:DealDamage()
|
||||
|
||||
self:SetNextMeleeAttack( 0 )
|
||||
|
||||
end
|
||||
|
||||
if ( SERVER and curtime > self:GetNextPrimaryFire() + self.ComboResetTime ) then
|
||||
|
||||
self:SetCombo( 0 )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
115
lua/weapons/weapon_flechettegun.lua
Normal file
115
lua/weapons/weapon_flechettegun.lua
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
SWEP.PrintName = "#weapon_flechettegun"
|
||||
SWEP.Author = "garry"
|
||||
SWEP.Purpose = "Shoot flechettes with primary attack."
|
||||
|
||||
SWEP.Slot = 1
|
||||
SWEP.SlotPos = 2
|
||||
|
||||
SWEP.Spawnable = true
|
||||
|
||||
SWEP.ViewModel = Model( "models/weapons/c_smg1.mdl" )
|
||||
SWEP.WorldModel = Model( "models/weapons/w_smg1.mdl" )
|
||||
SWEP.ViewModelFOV = 54
|
||||
SWEP.UseHands = true
|
||||
|
||||
SWEP.Primary.ClipSize = -1
|
||||
SWEP.Primary.DefaultClip = -1
|
||||
SWEP.Primary.Automatic = true
|
||||
SWEP.Primary.Ammo = "none"
|
||||
|
||||
SWEP.Secondary.ClipSize = -1
|
||||
SWEP.Secondary.DefaultClip = -1
|
||||
SWEP.Secondary.Automatic = false
|
||||
SWEP.Secondary.Ammo = "none"
|
||||
|
||||
SWEP.DrawAmmo = false
|
||||
SWEP.AdminOnly = true
|
||||
|
||||
game.AddParticles( "particles/hunter_flechette.pcf" )
|
||||
game.AddParticles( "particles/hunter_projectile.pcf" )
|
||||
|
||||
local ShootSound = Sound( "NPC_Hunter.FlechetteShoot" )
|
||||
|
||||
function SWEP:Initialize()
|
||||
|
||||
self:SetHoldType( "smg" )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Reload()
|
||||
end
|
||||
|
||||
function SWEP:CanBePickedUpByNPCs()
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:PrimaryAttack()
|
||||
|
||||
self:SetNextPrimaryFire( CurTime() + 0.1 )
|
||||
|
||||
self:EmitSound( ShootSound )
|
||||
self:ShootEffects()
|
||||
|
||||
if ( CLIENT ) then return end
|
||||
|
||||
SuppressHostEvents( NULL ) -- Do not suppress the flechette effects
|
||||
|
||||
local ent = ents.Create( "hunter_flechette" )
|
||||
if ( !IsValid( ent ) ) then return end
|
||||
|
||||
local owner = self:GetOwner()
|
||||
|
||||
local Forward = owner:GetAimVector()
|
||||
|
||||
ent:SetPos( owner:GetShootPos() + Forward * 32 )
|
||||
ent:SetAngles( owner:EyeAngles() )
|
||||
ent:SetOwner( owner )
|
||||
ent:Spawn()
|
||||
ent:Activate()
|
||||
|
||||
ent:SetVelocity( Forward * 2000 )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
|
||||
-- TODO: Reimplement the old rollermine secondary attack?
|
||||
|
||||
end
|
||||
|
||||
function SWEP:ShouldDropOnDie()
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
function SWEP:GetNPCRestTimes()
|
||||
|
||||
-- Handles the time between bursts
|
||||
-- Min rest time in seconds, max rest time in seconds
|
||||
|
||||
return 0.3, 0.6
|
||||
|
||||
end
|
||||
|
||||
function SWEP:GetNPCBurstSettings()
|
||||
|
||||
-- Handles the burst settings
|
||||
-- Minimum amount of shots, maximum amount of shots, and the delay between each shot
|
||||
-- The amount of shots can end up lower than specificed
|
||||
|
||||
return 1, 6, 0.1
|
||||
|
||||
end
|
||||
|
||||
function SWEP:GetNPCBulletSpread( proficiency )
|
||||
|
||||
-- Handles the bullet spread based on the given proficiency
|
||||
-- return value is in degrees
|
||||
|
||||
return 1
|
||||
|
||||
end
|
||||
268
lua/weapons/weapon_medkit.lua
Normal file
268
lua/weapons/weapon_medkit.lua
Normal file
@@ -0,0 +1,268 @@
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
SWEP.PrintName = "#weapon_medkit"
|
||||
SWEP.Author = "robotboy655, MaxOfS2D, code_gs"
|
||||
SWEP.Purpose = "Heal other people with primary attack, heal yourself with secondary attack."
|
||||
|
||||
SWEP.Slot = 5
|
||||
SWEP.SlotPos = 3
|
||||
|
||||
SWEP.Spawnable = true
|
||||
|
||||
SWEP.ViewModel = Model( "models/weapons/c_medkit.mdl" )
|
||||
SWEP.WorldModel = Model( "models/weapons/w_medkit.mdl" )
|
||||
SWEP.ViewModelFOV = 54
|
||||
SWEP.UseHands = true
|
||||
|
||||
SWEP.Primary.ClipSize = 100
|
||||
SWEP.Primary.DefaultClip = SWEP.Primary.ClipSize
|
||||
SWEP.Primary.Automatic = false
|
||||
SWEP.Primary.Ammo = ""
|
||||
|
||||
SWEP.Secondary.ClipSize = -1
|
||||
SWEP.Secondary.DefaultClip = -1
|
||||
SWEP.Secondary.Automatic = false
|
||||
SWEP.Secondary.Ammo = ""
|
||||
|
||||
SWEP.HoldType = "slam"
|
||||
|
||||
SWEP.HealSound = Sound( "HealthKit.Touch" )
|
||||
SWEP.DenySound = Sound( "WallHealth.Deny" )
|
||||
|
||||
SWEP.HealCooldown = 0.5 -- Time between successful heals
|
||||
SWEP.DenyCooldown = 1 -- Time between unsuccessful heals
|
||||
|
||||
SWEP.HealAmount = 20 -- Maximum heal amount per use
|
||||
SWEP.HealRange = 64 -- Range in units at which healing works
|
||||
|
||||
SWEP.AmmoRegenRate = 1 -- Number of seconds before each ammo regen
|
||||
SWEP.AmmoRegenAmount = 2 -- Amount of ammo refilled every AmmoRegenRate seconds
|
||||
|
||||
function SWEP:Initialize()
|
||||
|
||||
self:SetHoldType( self.HoldType )
|
||||
|
||||
-- Prevent large ammo jumps on-creation
|
||||
-- if DefaultClip < ClipSize
|
||||
self:SetLastAmmoRegen( CurTime() )
|
||||
|
||||
if ( CLIENT ) then
|
||||
self.AmmoDisplay = {
|
||||
Draw = true,
|
||||
PrimaryClip = 0
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Deploy()
|
||||
|
||||
-- Regen what we've gained since we've holstered
|
||||
-- and realign the timer
|
||||
self:Regen( false )
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function SWEP:SetupDataTables()
|
||||
|
||||
self:NetworkVar( "Float", 0, "LastAmmoRegen" )
|
||||
self:NetworkVar( "Float", 1, "NextIdle" )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:PrimaryAttack()
|
||||
|
||||
local owner = self:GetOwner()
|
||||
local dolagcomp = SERVER and owner:IsPlayer()
|
||||
|
||||
if ( dolagcomp ) then
|
||||
owner:LagCompensation( true )
|
||||
end
|
||||
|
||||
local startpos = owner:GetShootPos()
|
||||
local tr = util.TraceLine( {
|
||||
start = startpos,
|
||||
endpos = startpos + owner:GetAimVector() * self.HealRange,
|
||||
filter = owner
|
||||
} )
|
||||
|
||||
if ( dolagcomp ) then
|
||||
owner:LagCompensation( false )
|
||||
end
|
||||
|
||||
self:DoHeal( tr.Entity )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
|
||||
self:DoHeal( self:GetOwner() )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Reload()
|
||||
end
|
||||
|
||||
local DAMAGE_YES = 2
|
||||
|
||||
-- Basic black/whitelist function
|
||||
-- Checking if the entity's health is below its max is done in SWEP:DoHeal
|
||||
function SWEP:CanHeal( ent )
|
||||
|
||||
-- ent may be NULL here, but these functions return false for it
|
||||
if ( ent:IsPlayer() or ent:IsNPC() ) then
|
||||
local takedamage = ent:GetInternalVariable( "m_takedamage" )
|
||||
|
||||
-- Don't heal turrets and helicopters
|
||||
return takedamage == nil or takedamage == DAMAGE_YES
|
||||
end
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
function SWEP:DoHeal( ent )
|
||||
|
||||
local amount = self.HealAmount
|
||||
|
||||
if ( !self:CanHeal( ent ) ) then self:HealFail( ent ) return false end
|
||||
|
||||
local health, maxhealth = ent:Health(), ent:GetMaxHealth()
|
||||
if ( health >= maxhealth ) then self:HealFail( ent ) return false end
|
||||
|
||||
-- Check regen right before we access the clip
|
||||
-- to make sure we're up to date
|
||||
self:Regen( true )
|
||||
|
||||
local healamount = self.HealAmount
|
||||
|
||||
-- No support for "damage kits"
|
||||
if ( healamount > 0 ) then
|
||||
healamount = math.min( maxhealth - health, healamount )
|
||||
local ammo = self:Clip1()
|
||||
if ( ammo < healamount ) then self:HealFail( ent ) return false end
|
||||
|
||||
-- Heal ent
|
||||
self:SetClip1( ammo - healamount )
|
||||
ent:SetHealth( health + healamount )
|
||||
else
|
||||
healamount = 0
|
||||
end
|
||||
|
||||
self:HealSuccess( ent, healamount )
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function SWEP:HealSuccess( ent, healamount )
|
||||
|
||||
-- Do effects
|
||||
self:EmitSound( self.HealSound )
|
||||
self:SendWeaponAnim( ACT_VM_PRIMARYATTACK )
|
||||
|
||||
local owner = self:GetOwner()
|
||||
|
||||
if ( owner:IsValid() ) then
|
||||
owner:SetAnimation( PLAYER_ATTACK1 )
|
||||
end
|
||||
|
||||
local curtime = CurTime()
|
||||
|
||||
-- Reset regen time
|
||||
self:SetLastAmmoRegen( curtime )
|
||||
|
||||
-- Set next idle time
|
||||
local endtime = curtime + self:SequenceDuration()
|
||||
self:SetNextIdle( endtime )
|
||||
|
||||
-- Set next firing time
|
||||
endtime = endtime + self.HealCooldown
|
||||
self:SetNextPrimaryFire( endtime )
|
||||
self:SetNextSecondaryFire( endtime )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:HealFail( ent )
|
||||
|
||||
-- Do effects
|
||||
self:EmitSound( self.DenySound )
|
||||
|
||||
-- Setup next firing time
|
||||
local endtime = CurTime() + self.DenyCooldown
|
||||
self:SetNextPrimaryFire( endtime )
|
||||
self:SetNextSecondaryFire( endtime )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Think()
|
||||
|
||||
-- Try ammo regen
|
||||
-- but keep it aligned to the last action time
|
||||
self:Regen( true )
|
||||
|
||||
-- Do idle anim
|
||||
self:Idle()
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Regen( keepaligned )
|
||||
|
||||
local curtime = CurTime()
|
||||
local lastregen = self:GetLastAmmoRegen()
|
||||
local timepassed = curtime - lastregen
|
||||
local regenrate = self.AmmoRegenRate
|
||||
|
||||
-- Not ready to regenerate
|
||||
if ( timepassed < regenrate ) then return false end
|
||||
|
||||
local ammo = self:Clip1()
|
||||
local maxammo = self.Primary.ClipSize
|
||||
|
||||
-- Already at/over max ammo
|
||||
if ( ammo >= maxammo ) then return false end
|
||||
|
||||
if ( regenrate > 0 ) then
|
||||
self:SetClip1( math.min( ammo + math.floor( timepassed / regenrate ) * self.AmmoRegenAmount, maxammo ) )
|
||||
|
||||
-- If we are setting the last regen time from the Think function,
|
||||
-- keep it aligned with the last action time to prevent late Thinks from
|
||||
-- creating hiccups in the rate
|
||||
self:SetLastAmmoRegen( keepaligned == true and curtime + timepassed % regenrate or curtime )
|
||||
else
|
||||
self:SetClip1( maxammo )
|
||||
self:SetLastAmmoRegen( curtime )
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Idle()
|
||||
|
||||
-- Update idle anim
|
||||
local curtime = CurTime()
|
||||
|
||||
if ( curtime < self:GetNextIdle() ) then return false end
|
||||
|
||||
self:SendWeaponAnim( ACT_VM_IDLE )
|
||||
self:SetNextIdle( curtime + self:SequenceDuration() )
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
-- The following code does not need to exist on the server, so bail
|
||||
if ( SERVER ) then return end
|
||||
|
||||
function SWEP:CustomAmmoDisplay()
|
||||
|
||||
local display = self.AmmoDisplay
|
||||
display.PrimaryClip = self:Clip1()
|
||||
|
||||
return display
|
||||
|
||||
end
|
||||
275
lua/weapons/weapon_tt_medkit.lua
Normal file
275
lua/weapons/weapon_tt_medkit.lua
Normal file
@@ -0,0 +1,275 @@
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
SWEP.PrintName = "Аптечка"
|
||||
SWEP.Author = "robotboy655, MaxOfS2D, code_gs"
|
||||
SWEP.Purpose = "Heal other people with primary attack, heal yourself with secondary attack."
|
||||
|
||||
SWEP.Slot = 5
|
||||
SWEP.SlotPos = 3
|
||||
|
||||
SWEP.Spawnable = true
|
||||
|
||||
SWEP.ViewModel = Model( "models/weapons/c_medkit.mdl" )
|
||||
SWEP.WorldModel = Model( "models/weapons/w_medkit.mdl" )
|
||||
SWEP.ViewModelFOV = 54
|
||||
SWEP.UseHands = true
|
||||
|
||||
SWEP.Primary.ClipSize = 100
|
||||
SWEP.Primary.DefaultClip = SWEP.Primary.ClipSize
|
||||
SWEP.Primary.Automatic = false
|
||||
SWEP.Primary.Ammo = ""
|
||||
|
||||
SWEP.Secondary.ClipSize = -1
|
||||
SWEP.Secondary.DefaultClip = -1
|
||||
SWEP.Secondary.Automatic = false
|
||||
SWEP.Secondary.Ammo = ""
|
||||
|
||||
SWEP.HoldType = "slam"
|
||||
|
||||
SWEP.HealSound = Sound( "HealthKit.Touch" )
|
||||
SWEP.DenySound = Sound( "WallHealth.Deny" )
|
||||
|
||||
SWEP.HealCooldown = 0.5 -- Time between successful heals
|
||||
SWEP.DenyCooldown = 1 -- Time between unsuccessful heals
|
||||
|
||||
SWEP.HealAmount = 20 -- Maximum heal amount per use
|
||||
SWEP.HealRange = 64 -- Range in units at which healing works
|
||||
|
||||
SWEP.AmmoRegenRate = 1 -- Number of seconds before each ammo regen
|
||||
SWEP.AmmoRegenAmount = 2 -- Amount of ammo refilled every AmmoRegenRate seconds
|
||||
|
||||
function SWEP:Initialize()
|
||||
|
||||
self:SetHoldType( self.HoldType )
|
||||
|
||||
-- Prevent large ammo jumps on-creation
|
||||
-- if DefaultClip < ClipSize
|
||||
self:SetLastAmmoRegen( CurTime() )
|
||||
|
||||
if ( CLIENT ) then
|
||||
self.AmmoDisplay = {
|
||||
Draw = true,
|
||||
PrimaryClip = 0
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Deploy()
|
||||
|
||||
-- Regen what we've gained since we've holstered
|
||||
-- and realign the timer
|
||||
self:Regen( false )
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function SWEP:SetupDataTables()
|
||||
|
||||
self:NetworkVar( "Float", 0, "LastAmmoRegen" )
|
||||
self:NetworkVar( "Float", 1, "NextIdle" )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:PrimaryAttack()
|
||||
|
||||
local owner = self:GetOwner()
|
||||
local dolagcomp = SERVER and owner:IsPlayer()
|
||||
|
||||
if ( dolagcomp ) then
|
||||
owner:LagCompensation( true )
|
||||
end
|
||||
|
||||
local startpos = owner:GetShootPos()
|
||||
local tr = util.TraceLine( {
|
||||
start = startpos,
|
||||
endpos = startpos + owner:GetAimVector() * self.HealRange,
|
||||
filter = owner
|
||||
} )
|
||||
|
||||
if ( dolagcomp ) then
|
||||
owner:LagCompensation( false )
|
||||
end
|
||||
|
||||
self:DoHeal( tr.Entity )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
|
||||
self:DoHeal( self:GetOwner() )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Reload()
|
||||
end
|
||||
|
||||
local DAMAGE_YES = 2
|
||||
|
||||
-- Basic black/whitelist function
|
||||
-- Checking if the entity's health is below its max is done in SWEP:DoHeal
|
||||
function SWEP:CanHeal( ent )
|
||||
|
||||
-- ent may be NULL here, but these functions return false for it
|
||||
if ( ent:IsPlayer() or ent:IsNPC() ) then
|
||||
local takedamage = ent:GetInternalVariable( "m_takedamage" )
|
||||
|
||||
-- Don't heal turrets and helicopters
|
||||
return takedamage == nil or takedamage == DAMAGE_YES
|
||||
end
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
function SWEP:DoHeal( ent )
|
||||
|
||||
local amount = self.HealAmount
|
||||
|
||||
if ( !self:CanHeal( ent ) ) then self:HealFail( ent ) return false end
|
||||
|
||||
local health, maxhealth = ent:Health(), ent:GetMaxHealth()
|
||||
if ( health >= maxhealth ) then self:HealFail( ent ) return false end
|
||||
|
||||
-- Check regen right before we access the clip
|
||||
-- to make sure we're up to date
|
||||
self:Regen( true )
|
||||
|
||||
local healamount = self.HealAmount
|
||||
|
||||
-- No support for "damage kits"
|
||||
if ( healamount > 0 ) then
|
||||
healamount = math.min( maxhealth - health, healamount )
|
||||
local ammo = self:Clip1()
|
||||
if ( ammo < healamount ) then self:HealFail( ent ) return false end
|
||||
|
||||
-- Heal ent
|
||||
self:SetClip1( ammo - healamount )
|
||||
ent:SetHealth( health + healamount )
|
||||
else
|
||||
healamount = 0
|
||||
end
|
||||
|
||||
self:HealSuccess( ent, healamount )
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
local ix_heal_payment = 2
|
||||
|
||||
function SWEP:HealSuccess( ent, healamount )
|
||||
|
||||
-- Do effects
|
||||
self:EmitSound( self.HealSound )
|
||||
self:SendWeaponAnim( ACT_VM_PRIMARYATTACK )
|
||||
|
||||
local owner = self:GetOwner()
|
||||
|
||||
if ( owner:IsValid() ) then
|
||||
owner:SetAnimation( PLAYER_ATTACK1 )
|
||||
|
||||
if owner:GetCharacter() and ent != owner then
|
||||
owner:GetCharacter():GiveMoney(ix_heal_payment)
|
||||
owner:NotifyLocalized("healed_ply",ix.currency.Get(ix_heal_payment))
|
||||
end
|
||||
end
|
||||
|
||||
local curtime = CurTime()
|
||||
|
||||
-- Reset regen time
|
||||
self:SetLastAmmoRegen( curtime )
|
||||
|
||||
-- Set next idle time
|
||||
local endtime = curtime + self:SequenceDuration()
|
||||
self:SetNextIdle( endtime )
|
||||
|
||||
-- Set next firing time
|
||||
endtime = endtime + self.HealCooldown
|
||||
self:SetNextPrimaryFire( endtime )
|
||||
self:SetNextSecondaryFire( endtime )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:HealFail( ent )
|
||||
|
||||
-- Do effects
|
||||
self:EmitSound( self.DenySound )
|
||||
|
||||
-- Setup next firing time
|
||||
local endtime = CurTime() + self.DenyCooldown
|
||||
self:SetNextPrimaryFire( endtime )
|
||||
self:SetNextSecondaryFire( endtime )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Think()
|
||||
|
||||
-- Try ammo regen
|
||||
-- but keep it aligned to the last action time
|
||||
self:Regen( true )
|
||||
|
||||
-- Do idle anim
|
||||
self:Idle()
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Regen( keepaligned )
|
||||
|
||||
local curtime = CurTime()
|
||||
local lastregen = self:GetLastAmmoRegen()
|
||||
local timepassed = curtime - lastregen
|
||||
local regenrate = self.AmmoRegenRate
|
||||
|
||||
-- Not ready to regenerate
|
||||
if ( timepassed < regenrate ) then return false end
|
||||
|
||||
local ammo = self:Clip1()
|
||||
local maxammo = self.Primary.ClipSize
|
||||
|
||||
-- Already at/over max ammo
|
||||
if ( ammo >= maxammo ) then return false end
|
||||
|
||||
if ( regenrate > 0 ) then
|
||||
self:SetClip1( math.min( ammo + math.floor( timepassed / regenrate ) * self.AmmoRegenAmount, maxammo ) )
|
||||
|
||||
-- If we are setting the last regen time from the Think function,
|
||||
-- keep it aligned with the last action time to prevent late Thinks from
|
||||
-- creating hiccups in the rate
|
||||
self:SetLastAmmoRegen( keepaligned == true and curtime + timepassed % regenrate or curtime )
|
||||
else
|
||||
self:SetClip1( maxammo )
|
||||
self:SetLastAmmoRegen( curtime )
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Idle()
|
||||
|
||||
-- Update idle anim
|
||||
local curtime = CurTime()
|
||||
|
||||
if ( curtime < self:GetNextIdle() ) then return false end
|
||||
|
||||
self:SendWeaponAnim( ACT_VM_IDLE )
|
||||
self:SetNextIdle( curtime + self:SequenceDuration() )
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
-- The following code does not need to exist on the server, so bail
|
||||
if ( SERVER ) then return end
|
||||
|
||||
function SWEP:CustomAmmoDisplay()
|
||||
|
||||
local display = self.AmmoDisplay
|
||||
display.PrimaryClip = self:Clip1()
|
||||
|
||||
return display
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user