SHELL_9MM = 1 -- pistol shells
SHELL_57 = 2 -- bigger pistol shells? maybe for desert eagle?
SHELL_556 = 3 -- AK47, etc. shells
SHELL_762NATO = 4 -- M4, etc. shells
SHELL_SHOTGUN = 5 -- all shotguns
SHELL_338MAG = 6 -- AWP/scout shells
SHELL_50CAL = 7 -- this is the default hl2 rifle shell. it looks roughly like a 50
if ( SERVER ) then
AddCSLuaFile( "shared.lua" )
AddCSLuaFile( "cl_viewmodel.lua" )
SWEP.AutoSwitchFrom = false
SWEP.AutoSwitchTo = false
SWEP.Weight = 5
resource.AddFile("materials/gmod/scope.vtf")
resource.AddFile("materials/gmod/scope.vmt")
resource.AddFile("materials/gmod/scope-refract.vtf")
resource.AddFile("materials/gmod/scope-refract.vmt")
end
if ( CLIENT ) then
include( "cl_viewmodel.lua" )
SWEP.BobScale = 1
SWEP.SwayScale = 1
SWEP.BounceWeaponIcon = false
SWEP.DrawAmmo = false
SWEP.DrawCrosshair = false
SWEP.DrawWeaponInfoBox = false
SWEP.UseCustomCrosshair = false
SWEP.AccurateCrosshair = false
SWEP.PrintName = "BlackOps Base"
SWEP.RenderGroup = RENDERGROUP_OPAQUE
SWEP.Slot = 0
SWEP.SlotPos = 0
SWEP.SpeechBubbleLid = surface.GetTextureID( "gui/speech_lid" )
SWEP.WepSelectIcon = surface.GetTextureID( "weapons/swep" )
SWEP.CSMuzzleFlashes = true
surface.CreateFont( "csd", ScreenScale( 60 ), 500, true, true, "CSSelectIcons" )
surface.CreateFont( "csd", ScreenScale( 30 ), 500, true, true, "CSKillIcons" )
surface.CreateFont( "HL2MPTypeDeath", ScreenScale( 60 ), 500, true, true, "HL2MPTypeSelect" )
SWEP.IconLetter = "e"
SWEP.IconSelectFont = "CSSelectIcons"
SWEP.IconFont = "CSKillIcons"
end
SWEP.Category = "BlackOps"
SWEP.Spawnable = false
SWEP.AdminSpawnable = false
SWEP.AnimPrefix = "python"
SWEP.Author = "BlackOps"
--SWEP.Base = "bo_base"
SWEP.Contact = ""
SWEP.Instructions = ""
SWEP.Purpose = ""
SWEP.ViewModel = ""
SWEP.WorldModel = ""
SWEP.ViewModelFlip = false
SWEP.ViewModelFOV = 70
SWEP.HoldType = "ar2"
--SWEP.Folder --returns the folder of the sweps
--SWEP.Owner --returns the owner of the swep
--SWEP.Weapon --returns the weapon entity
SWEP.Primary.Sound = Sound( "Weapon_AK47.Single" )
SWEP.Primary.Recoil = 1.20
SWEP.Primary.Damage = { 8, 14 }
SWEP.Primary.BulletForce = 1
SWEP.Primary.NumShots = 1
SWEP.Primary.Cone = 0.03
SWEP.Primary.ClipSize = 60
SWEP.Primary.Delay = 0.085
SWEP.Primary.DefaultClip = 999
SWEP.Primary.Automatic = true
SWEP.Primary.Ammo = "smg1"
SWEP.Primary.ShellType = SHELL_9MM
SWEP.Secondary.ClipSize = 1
SWEP.Secondary.DefaultClip = 1
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "none"
SWEP.IronSightsPos = Vector(0,0,0)
SWEP.IronSightsAng = Vector(0,0,0)
SWEP.RunArmOffset = Vector(0,0,0)
SWEP.RunArmAngle = Vector(0,0,0)
SWEP.CanSprintAndShoot = false
SWEP.CanIronSight = true
SWEP.SprayTime = 0.2
SWEP.SprayAccuracy = 0.5
SWEP.RunBob = 2.0
SWEP.RunSway = 2.0
SWEP.IronBob = 0.1
SWEP.IronSway = 0.3
function SWEP:Initialize()
if ( SERVER ) then
self:SetWeaponHoldType( self.HoldType )
self:SetNPCMinBurst( 30 )
self:SetNPCMaxBurst( 30 )
self:SetNPCFireRate( 0.01 )
end
self.Weapon:SetNetworkedBool( "Ironsights", false )
end
function SWEP:SetIronsights( b )
self.Weapon:SetNetworkedBool( "Ironsights", b )
if b == true then
self.Owner:SetFOV(65,0.15)
else
self.Owner:SetFOV(0,0.15)
end
end
function SWEP:Reload()
if self.Owner:GetActiveWeapon():Clip1() == self.Primary.ClipSize then return end
if self.Reloading or self.Owner:GetAmmoCount(self.Primary.Ammo) == 0 then return end
if self.Weapon:Clip1() < self.Primary.ClipSize then
self.Weapon:DefaultReload(ACT_VM_RELOAD)
self:SetIronsights( false )
end
end
function SWEP:Deploy()
self:SetIronsights( false )
self.Weapon:SendWeaponAnim(ACT_VM_DRAW)
return true
end
function SWEP:OnRestore()
self.NextSecondaryAttack = 0
self:SetIronsights( false )
end
function SWEP:CanShootWeapon()
if( self.Owner:IsNPC() ) then
return true
end
if( self.CanSprintAndShoot == false ) then
if( self.Owner:KeyDown( IN_SPEED ) ) then return false end
if ( self.LastSprintTime && CurTime() - self.LastSprintTime < 0.1 ) then return false end
end
return true
end
function SWEP:Think()
if ( self.Owner && self.Owner:KeyDown( IN_SPEED ) ) then
self.LastSprintTime = CurTime()
self:SetIronsights( false )
end
self:GetStanceAccuracyBonus()
end
function SWEP:GetStanceAccuracyBonus()
if( self.Owner:IsNPC() ) then
return 0.8;
end
if( self.ConstantAccuracy ) then
return 1.0;
end
local LastAccuracy = self.LastAccuracy or 0;
local Accuracy = 1.0;
local LastShoot = self.Weapon:GetNWFloat( "LastShootTime", 0 );
local speed = self.Owner:GetVelocity():Length()
-- 200 walk, 500 sprint, 705 noclip
local speedperc = math.Clamp( math.abs( speed / 2000 ), 0, 1 );
if( CurTime() <= LastShoot + self.SprayTime ) then
--print ( CurTime() - LastShoot )
Accuracy = Accuracy * self.SprayAccuracy;
--Accuracy = Accuracy * ( CurTime() - LastShoot ) / (self.SprayAccuracy/2)
end
if( speed > 10 ) then -- moving
Accuracy = Accuracy * ( ( ( 1 - speedperc ) + 0.1 ) / 1.5 );
end
if( self.Owner:KeyDown( IN_DUCK ) == true || self.Weapon:GetNetworkedBool( "Ironsights", false ) == true) then -- ducking moving forward
Accuracy = Accuracy * 1.50;
end
if( self.Owner:KeyDown( IN_LEFT ) or self.Owner:KeyDown( IN_RIGHT ) ) then -- just strafing
Accuracy = Accuracy * 0.95;
end
if( !self.Owner:OnGround() ) then
Accuracy = Accuracy * 0.5;
end
if( LastAccuracy != 0 ) then
if( Accuracy > LastAccuracy ) then
Accuracy = math.Approach( self.LastAccuracy, Accuracy, FrameTime() * 2 )
else
Accuracy = math.Approach( self.LastAccuracy, Accuracy, FrameTime() * -2 )
end
end
self.LastAccuracy = Accuracy;
return Accuracy * 2;
end
--bullet stuff
function SWEP:SecondaryAttack()
if ( !self:CanShootWeapon() and !self.CanIronSight) then return end
self.Weapon:SetNextSecondaryFire( CurTime() + 0.3 )
if SERVER then
bIronsights = !self.Weapon:GetNetworkedBool( "Ironsights", false )
self:SetIronsights( bIronsights )
end
if ( CLIENT || SinglePlayer()) then
self.Weapon:EmitSound(Sound("npc/metropolice/gear"..math.random(1,6)..".wav"),30,math.random(75,100)) --Sexy ironsight sound
end
end
function SWEP:PrimaryAttack()
if ( !self:CanShootWeapon() ) then return end
if ( !self:CanPrimaryAttack() ) then return end
self.Weapon:SetNextPrimaryFire( CurTime() + self.Primary.Delay )
self.Weapon:ShootBullet( self.Primary.NumShots, self.Primary.Cone/self:GetStanceAccuracyBonus() )
self.Weapon:TakePrimaryAmmo( 1 )
if IsFirstTimePredicted() and self.Owner:IsValid() then --Predict that motha' fucka'
self.Owner:ViewPunchReset()
self.Weapon:EmitSound( self.Primary.Sound, 100, math.random(95,105) )
local bonus = self:GetStanceAccuracyBonus()
if ( CLIENT || SinglePlayer()) then
local eyeang = self.Owner:EyeAngles()
eyeang.pitch = eyeang.pitch - self.Primary.Recoil/bonus/1.5
eyeang.yaw = eyeang.yaw - math.Rand(-1,1)*self.Primary.Recoil/bonus/1.5
self.Owner:SetEyeAngles( eyeang )
end
if self.Weapon:GetNetworkedBool( "Ironsights", false ) == false then
self.Owner:ViewPunch( Angle( -self.Primary.Recoil/bonus, math.Rand(-1,1)*self.Primary.Recoil, 0))
else
self.Owner:ViewPunch( Angle( -self.Primary.Recoil/bonus/2, math.Rand(-1,1)*self.Primary.Recoil/2, 0))
end
end
if ( (SinglePlayer() && SERVER) || CLIENT ) then
self.Weapon:SetNetworkedFloat( "LastShootTime", CurTime() )
end
end
function SWEP:ShootBullet( num_bullets, aimcone )
if self.Weappon:GetNetworkedBoool( "Ironsights", false ) == false then
self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK )
end
self.Owner:MuzzleFlash()
self.Owner:SetAnimation( PLAYER_ATTACK1 )
if !IsFirstTimePredicted() then return end
local effectdata = EffectData()
effectdata:SetOrigin( self.Owner:GetShootPos() )
effectdata:SetEntity( self.Weapon )
effectdata:SetStart( self.Owner:GetShootPos() )
effectdata:SetNormal( self.Owner:GetAimVector() )
effectdata:SetAttachment( 1 )
util.Effect( "gunsmoke", effectdata ) --Was ugly
if SERVER and self.Primary.ShellType then
local effectdata = EffectData()
effectdata:SetEntity( self.Weapon )
effectdata:SetAttachment( self.Weapon:LookupAttachment( "2" ) ) -- what attachment should the bullet come from?
effectdata:SetScale( self.Primary.ShellType )
util.Effect( "weapon_shell", effectdata, true, true )
end
if self.MuzzleEffect and self.MuzzleEffect != nil then
local effectdata = EffectData()
effectdata:SetOrigin( self.Owner:GetShootPos() )
effectdata:SetEntity( self.Weapon )
effectdata:SetStart( self.Owner:GetShootPos() )
effectdata:SetNormal( self.Owner:GetAimVector() )
effectdata:SetAttachment( 1 )
util.Effect( self.MuzzleEffect, effectdata )
end
local bullet = {}
bullet.Num = num_bullets
bullet.Src = self.Owner:GetShootPos()
bullet.Dir = self.Owner:GetAimVector()
bullet.Spread = Vector( aimcone, aimcone, 0 )
bullet.Tracer = 5
bullet.Force = self.Primary.BulletForce
if type( self.Primary.Damage ) == "table" then
bullet.Damage = math.random( self.Primary.Damage[1], self.Primary.Damage[2] )
else
bullet.Damage = self.Primary.Damage
end
bullet.AmmoType = self.Primary.Ammo
bullet.Callback = function ( attacker, tr, dmginfo )
self.Weapon:BulletCallback( attacker, tr, dmginfo, 0 )
end
self.Owner:FireBullets( bullet )
end
function SWEP:BulletCallback( attacker, tr, dmginfo, bounce )
if( !self or !ValidEntity( self.Weapon ) ) then return end
self.Weapon:BulletPenetration( attacker, tr, dmginfo, bounce + 1 );
return { damage = true, effect = true, effects = true };
end
function SWEP:GetPenetrationDistance( mat_type )
--[[if ( mat_type == MAT_PLASTIC || mat_type == MAT_WOOD || mat_type == MAT_FLESH || mat_type == MAT_ALIENFLESH || mat_type == MAT_GLASS || mat_type == MAT_DIRT || mat_type == MAT_FOLIAGE || mat_type == MAT_VENT ) then
return 128
end]]
if( mat_type == MAT_GLASS || mat_type == MAT_VENT || mat_type == MAT_FOLIAGE ) then
return 32
elseif( mat_type == MAT_PLASTIC || mat_type == MAT_FLESH || mat_type == MAT_ALIENFLESH ) then
return 24
elseif( mat_type == MAT_WOOD || mat_type == MAT_DIRT ) then
return 16
elseif( mat_type == MAT_METAL ) then
return 8
end
return 24
end
function SWEP:GetDecalType( mat_type )
if ( mat_type == MAT_WOOD ) then
return "Impact.Wood"
elseif ( mat_type == MAT_FLESH ) then
return "Impact.BloodyFlesh"
elseif ( mat_type == MAT_ALIENFLESH ) then
return "Impact.Antlion"
elseif ( mat_type == MAT_GLASS ) then
return "Impact.Glass"
elseif ( mat_type == MAT_METAL or mat_type == MAT_VENT ) then
return "Impact.Metal"
elseif ( mat_type == MAT_SAND or mat_type == MAT_FOLIAGE ) then
return "Impact.Sand"
end
return "Impact.Concrete"
end
function SWEP:GetPenetrationDamageLoss( mat_type, distance, damage )
if( mat_type == MAT_GLASS || mat_type == MAT_VENT || mat_type == MAT_FOLIAGE ) then
return damage - ( distance * 0.45 )
elseif( mat_type == MAT_PLASTIC || mat_type == MAT_FLESH || mat_type == MAT_ALIENFLESH || mat_type == 45 ) then
return damage - ( distance * 0.55 )
elseif( mat_type == MAT_WOOD || mat_type == MAT_DIRT ) then
return damage - ( distance * 0.65 )
end
return damage - ( distance * 0.75 )
end
function SWEP:BulletPenetration( attacker, tr, dmginfo, bounce )
if ( !self or !ValidEntity( self.Weapon ) ) then return end
if ( bounce > 5 ) then return false end
local PeneDir = tr.Normal * self:GetPenetrationDistance( tr.MatType )
local PeneTrace = {}
PeneTrace.endpos = tr.HitPos
PeneTrace.start = tr.HitPos + PeneDir
PeneTrace.mask = MASK_SHOT
PeneTrace.filter = { self.Owner }
local PeneTrace = util.TraceLine( PeneTrace )
if ( PeneTrace.StartSolid || PeneTrace.Fraction >= 1.0 || tr.Fraction <= 0.0 ) then return false end
local distance = ( PeneTrace.HitPos - tr.HitPos ):Length();
local new_damage = self:GetPenetrationDamageLoss( tr.MatType, distance, dmginfo:GetDamage() );
--print( "Distance = ", distance, "Original Damage = ", dmginfo:GetDamage(), "New Damage = ",new_damage )
if( new_damage > 0 ) then
local bullet =
{
Num = 1,
Src = PeneTrace.HitPos,
Dir = tr.Normal,
Spread = Vector( 0, 0, 0 ),
Tracer = 0,
Force = 5,
Damage = new_damage,
AmmoType = "Pistol",
}
bullet.Callback = function( a, b, c ) if ( self.BulletCallback ) then return self:BulletCallback( a, b, c, bounce + 1 ) end end
util.Decal(self:GetDecalType( PeneTrace.MatType ), PeneTrace.HitPos + PeneTrace.HitNormal, PeneTrace.HitPos - PeneTrace.HitNormal)
timer.Simple( 0, attacker.FireBullets, attacker, bullet, true )
end
end
function SWEP:DrawHUD( )
local pos = LocalPlayer():GetShootPos()
local ang = LocalPlayer():GetAimVector()
local tracedata = {}
tracedata.start = pos
tracedata.endpos = pos+(ang*99999999)
tracedata.filter = LocalPlayer()
local trace = util.TraceLine(tracedata)
local scrnpos = trace.HitPos:ToScreen()
local x = scrnpos.x
local y = scrnpos.y
// No crosshair when ironsights is on
if ( self.Weapon:GetNetworkedBool( "Ironsights" ) ) then return true end
//local scale = ( 10 + (self.Primary.Cone * ( 260 * (ScrH()/720) ) ) * (1/self:GetStanceAccuracyBonus())) * 0.5;
local scale = 10 * self.Primary.Cone * (1/self:GetStanceAccuracyBonus())
// Scale the size of the crosshair according to how long ago we fired our weapon
local LastShootTime = self.Weapon:GetNetworkedFloat( "LastShootTime", 0 )
--local LastShootTime = self.LastAttack
scale = scale * (2 - math.Clamp( (CurTime() - LastShootTime) * 5, 0.0, 1.0 ))
surface.SetDrawColor( 0, 255, 0, 255 )
// Draw an awesome crosshair
local gap = 40 * scale
local length = gap + 20 * scale
surface.DrawLine( x - length, y, x - gap, y )
surface.DrawLine( x + length, y, x + gap, y )
surface.DrawLine( x, y - length, x, y - gap )
surface.DrawLine( x, y + length, x, y + gap )
end
function SWEP:DrawWeaponSelection( x, y, wide, tall, alpha )
local txt = self.IconLetter or "e"
local font = self.IconSelectFont or "CSSelectIcons"
draw.SimpleText( txt, font, x + wide/2, y + tall*0.2, Color( 255, 210, 0, 255 ), TEXT_ALIGN_CENTER )
draw.SimpleText( txt, font, x + wide/2 + math.Rand(-4, 4), y + tall*0.2+ math.Rand(-14, 14), Color( 255, 210, 0, math.Rand(10, 120) ), TEXT_ALIGN_CENTER )
draw.SimpleText( txt, font, x + wide/2 + math.Rand(-4, 4), y + tall*0.2+ math.Rand(-9, 9), Color( 255, 210, 0, math.Rand(10, 120) ), TEXT_ALIGN_CENTER )
end
function SWEP:DoDrawCrosshair( x, y )
return true
end