diff options
Diffstat (limited to 'ftp_gmstranded/entities/weapons/bobs_gun_base/shared.lua')
| -rw-r--r-- | ftp_gmstranded/entities/weapons/bobs_gun_base/shared.lua | 1359 |
1 files changed, 1359 insertions, 0 deletions
diff --git a/ftp_gmstranded/entities/weapons/bobs_gun_base/shared.lua b/ftp_gmstranded/entities/weapons/bobs_gun_base/shared.lua new file mode 100644 index 0000000..6e182de --- /dev/null +++ b/ftp_gmstranded/entities/weapons/bobs_gun_base/shared.lua @@ -0,0 +1,1359 @@ +-- //Variables that are used on both client and server +SWEP.Category = "" +SWEP.Gun = "" +SWEP.Author = "Generic Default, Worshipper, Clavus, and Bob" +SWEP.Contact = "" +SWEP.Purpose = "" +SWEP.Instructions = "" +SWEP.MuzzleAttachment = "1" -- Should be "1" for CSS models or "muzzle" for hl2 models +SWEP.DrawCrosshair = true -- Hell no, crosshairs r 4 nubz! +SWEP.ViewModelFOV = 65 -- How big the gun will look +SWEP.ViewModelFlip = true -- True for CSS models, False for HL2 models + +SWEP.Spawnable = false +SWEP.AdminSpawnable = false + +SWEP.Primary.Sound = Sound("") -- Sound of the gun +SWEP.Primary.Round = ("") -- What kind of bullet? +SWEP.Primary.Cone = 0.2 -- Accuracy of NPCs +SWEP.Primary.Recoil = 10 +SWEP.Primary.Damage = 10 +SWEP.Primary.Spread = .01 --define from-the-hip accuracy (1 is terrible, .0001 is exact) +SWEP.Primary.NumShots = 1 +SWEP.Primary.RPM = 0 -- This is in Rounds Per Minute +SWEP.Primary.ClipSize = 0 -- Size of a clip +SWEP.Primary.DefaultClip = 0 -- Default number of bullets in a clip +SWEP.Primary.KickUp = 0 -- Maximum up recoil (rise) +SWEP.Primary.KickDown = 0 -- Maximum down recoil (skeet) +SWEP.Primary.KickHorizontal = 0 -- Maximum side recoil (koolaid) +SWEP.Primary.Automatic = true -- Automatic/Semi Auto +SWEP.Primary.Ammo = "none" -- What kind of ammo + +-- SWEP.Secondary.ClipSize = 0 -- Size of a clip +-- SWEP.Secondary.DefaultClip = 0 -- Default number of bullets in a clip +-- SWEP.Secondary.Automatic = false -- Automatic/Semi Auto +SWEP.Secondary.Ammo = "" +--//HAHA! GOTCHA, YA BASTARD! + +-- SWEP.Secondary.IronFOV = 0 -- How much you 'zoom' in. Less is more! + +SWEP.Penetration = true +SWEP.Ricochet = true +SWEP.MaxRicochet = 1 +SWEP.RicochetCoin = 1 +SWEP.BoltAction = false +SWEP.Scoped = false +SWEP.ShellTime = .35 +SWEP.Tracer = 0 +SWEP.CanBeSilenced = false +SWEP.Silenced = false +SWEP.NextSilence = 0 +SWEP.SelectiveFire = false +SWEP.NextFireSelect = 0 +SWEP.OrigCrossHair = true + +local PainMulti = 1 + +if GetConVar("M9KDamageMultiplier") == nil then + PainMulti = 1 + print("M9KDamageMultiplier is missing! You may have hit the lua limit! Reverting multiplier to 1.") +else + PainMulti = GetConVar("M9KDamageMultiplier"):GetFloat() + if PainMulti < 0 then + PainMulti = PainMulti * -1 + print("Your damage multiplier was in the negatives. It has been reverted to a positive number. Your damage multiplier is now "..PainMulti) + end +end + +function NewM9KDamageMultiplier(cvar, previous, new) + print("multiplier has been changed ") + if GetConVar("M9KDamageMultiplier") == nil then + PainMulti = 1 + print("M9KDamageMultiplier is missing! You may have hit the lua limit! Reverting multiplier to 1, you will notice no changes.") + else + PainMulti = GetConVar("M9KDamageMultiplier"):GetFloat() + if PainMulti < 0 then + PainMulti = PainMulti * -1 + print("Your damage multiplier was in the negatives. It has been reverted to a positive number. Your damage multiplier is now "..PainMulti) + end + end +end +cvars.AddChangeCallback("M9KDamageMultiplier", NewM9KDamageMultiplier) + +function NewDefClips(cvar, previous, new) + print("Default clip multiplier has changed. A server restart will be required for these changes to take effect.") +end +cvars.AddChangeCallback("M9KDefaultClip", NewDefClips) + +if GetConVar("M9KDefaultClip") == nil then + print("M9KDefaultClip is missing! You may have hit the lua limit!") +else + if GetConVar("M9KDefaultClip"):GetInt() >= 0 then + print("M9K Weapons will now spawn with "..GetConVar("M9KDefaultClip"):GetFloat().." clips.") + else + print("Default clips will be not be modified") + end +end + +SWEP.IronSightsPos = Vector (2.4537, 1.0923, 0.2696) +SWEP.IronSightsAng = Vector (0.0186, -0.0547, 0) + +SWEP.VElements = {} +SWEP.WElements = {} + +function SWEP:Initialize() + self.Reloadaftershoot = 0 -- Can't reload when firing + self:SetHoldType(self.HoldType) + self.OrigCrossHair = self.DrawCrosshair + if SERVER and self.Owner:IsNPC() then + self:SetNPCMinBurst(3) + self:SetNPCMaxBurst(10) -- None of this really matters but you need it here anyway + self:SetNPCFireRate(1/(self.Primary.RPM/60)) + -- //self:SetCurrentWeaponProficiency( WEAPON_PROFICIENCY_VERY_GOOD ) + end + + if CLIENT then + + -- // Create a new table for every weapon instance + self.VElements = table.FullCopy( self.VElements ) + self.WElements = table.FullCopy( self.WElements ) + self.ViewModelBoneMods = table.FullCopy( self.ViewModelBoneMods ) + + self:CreateModels(self.VElements) -- create viewmodels + self:CreateModels(self.WElements) -- create worldmodels + + -- // init view model bone build function + if IsValid(self.Owner) and self.Owner:IsPlayer() then + if self.Owner:Alive() then + local vm = self.Owner:GetViewModel() + if IsValid(vm) then + self:ResetBonePositions(vm) + -- // Init viewmodel visibility + if (self.ShowViewModel == nil or self.ShowViewModel) then + vm:SetColor(Color(255,255,255,255)) + else + -- // however for some reason the view model resets to render mode 0 every frame so we just apply a debug material to prevent it from drawing + vm:SetMaterial("Debug/hsv") + end + end + + end + end + + end + + if CLIENT then + local oldpath = "vgui/hud/name" -- the path goes here + local newpath = string.gsub(oldpath, "name", self.Gun) + self.WepSelectIcon = surface.GetTextureID(newpath) + end + +end + +function SWEP:Equip() + self:SetHoldType(self.HoldType) +end + +function SWEP:Deploy() + self:SetIronsights(false, self.Owner) -- Set the ironsight false + self:SetHoldType(self.HoldType) + + if self.Silenced then + self.Weapon:SendWeaponAnim( ACT_VM_DRAW_SILENCED ) + else + self.Weapon:SendWeaponAnim( ACT_VM_DRAW ) + end + + self.Weapon:SetNWBool("Reloading", false) + + if !self.Owner:IsNPC() and self.Owner != nil then + if self.ResetSights and self.Owner:GetViewModel() != nil then + self.ResetSights = CurTime() + self.Owner:GetViewModel():SequenceDuration() + end + end + return true +end + +function SWEP:Holster() + + if CLIENT and IsValid(self.Owner) and not self.Owner:IsNPC() then + local vm = self.Owner:GetViewModel() + if IsValid(vm) then + self:ResetBonePositions(vm) + end + end + + return true +end + +function SWEP:OnRemove() + + if CLIENT and IsValid(self.Owner) and not self.Owner:IsNPC() then + local vm = self.Owner:GetViewModel() + if IsValid(vm) then + self:ResetBonePositions(vm) + end + end + +end + +function SWEP:GetCapabilities() + return CAP_WEAPON_RANGE_ATTACK1, CAP_INNATE_RANGE_ATTACK1 +end + +function SWEP:Precache() + util.PrecacheSound(self.Primary.Sound) + util.PrecacheModel(self.ViewModel) + util.PrecacheModel(self.WorldModel) +end + +function SWEP:PrimaryAttack() + OkaySoFar = true + if not IsValid(self) then + OkaySoFar = false + else if not IsValid(self.Weapon) then + OkaySoFar = false + else if not IsValid(self.Owner) then + OkaySoFar = false + end end end + + if not OkaySoFar then return end + + if self:CanPrimaryAttack() and self.Owner:IsPlayer() then + if !self.Owner:KeyDown(IN_SPEED) and !self.Owner:KeyDown(IN_RELOAD) then + self:ShootBulletInformation() + self.Weapon:TakePrimaryAmmo(1) + + if self.Silenced then + self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK_SILENCED ) + self.Weapon:EmitSound(self.Primary.SilencedSound) + else + self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + self.Weapon:EmitSound(self.Primary.Sound) + end + + local fx = EffectData() + fx:SetEntity(self.Weapon) + fx:SetOrigin(self.Owner:GetShootPos()) + fx:SetNormal(self.Owner:GetAimVector()) + fx:SetAttachment(self.MuzzleAttachment) + if GetConVar("M9KGasEffect") != nil then + if GetConVar("M9KGasEffect"):GetBool() then + util.Effect("m9k_rg_muzzle_rifle",fx) + end + end + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + self.Owner:MuzzleFlash() + self.Weapon:SetNextPrimaryFire(CurTime()+1/(self.Primary.RPM/60)) + self:CheckWeaponsAndAmmo() + self.RicochetCoin = (math.random(1,4)) + if self.BoltAction then self:BoltBack() end + end + elseif self:CanPrimaryAttack() and self.Owner:IsNPC() then + self:ShootBulletInformation() + self.Weapon:TakePrimaryAmmo(1) + self.Weapon:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) + self.Weapon:EmitSound(self.Primary.Sound) + self.Owner:SetAnimation( PLAYER_ATTACK1 ) + self.Owner:MuzzleFlash() + self.Weapon:SetNextPrimaryFire(CurTime()+1/(self.Primary.RPM/60)) + self.RicochetCoin = (math.random(1,4)) + end +end + +function SWEP:CheckWeaponsAndAmmo() + if SERVER and self.Weapon != nil and (GetConVar("M9KWeaponStrip"):GetBool()) then + if self.Weapon:Clip1() == 0 && self.Owner:GetAmmoCount( self.Weapon:GetPrimaryAmmoType() ) == 0 then + timer.Simple(.1, function() if SERVER then if not IsValid(self) then return end + if self.Owner == nil then return end + self.Owner:StripWeapon(self.Gun) + end end) + end + end +end + + +/*--------------------------------------------------------- + Name: SWEP:ShootBulletInformation() + Desc: This func add the damage, the recoil, the number of shots and the cone on the bullet. +-----------------------------------------------------*/ +function SWEP:ShootBulletInformation() + + local CurrentDamage + local CurrentRecoil + local CurrentCone + local basedamage + + if (self:GetIronsights() == true) and self.Owner:KeyDown(IN_ATTACK2) then + CurrentCone = self.Primary.IronAccuracy + else + CurrentCone = self.Primary.Spread + end + local damagedice = math.Rand(.85,1.3) + + basedamage = PainMulti * self.Primary.Damage + CurrentDamage = basedamage * damagedice + CurrentRecoil = self.Primary.Recoil + + -- //Player is aiming + if (self:GetIronsights() == true) and self.Owner:KeyDown(IN_ATTACK2) then + self:ShootBullet(CurrentDamage, CurrentRecoil / 6, self.Primary.NumShots, CurrentCone) + -- //Player is not aiming + else + if IsValid(self) then + if IsValid(self.Weapon) then + if IsValid(self.Owner) then + self:ShootBullet(CurrentDamage, CurrentRecoil, self.Primary.NumShots, CurrentCone) + end + end + end + end + +end + +/*--------------------------------------------------------- + Name: SWEP:ShootBullet() + Desc: A convenience func to shoot bullets. +-----------------------------------------------------*/ +local TracerName = "Tracer" + +function SWEP:ShootBullet(damage, recoil, num_bullets, aimcone) + + num_bullets = num_bullets or 1 + aimcone = aimcone or 0 + + self:ShootEffects() + + if self.Tracer == 1 then + TracerName = "Ar2Tracer" + elseif self.Tracer == 2 then + TracerName = "AirboatGunHeavyTracer" + else + TracerName = "Tracer" + end + + local bullet = {} + bullet.Num = num_bullets + bullet.Src = self.Owner:GetShootPos() -- Source + bullet.Dir = self.Owner:GetAimVector() -- Dir of bullet + bullet.Spread = Vector(aimcone, aimcone, 0) -- Aim Cone + bullet.Tracer = 3 -- Show a tracer on every x bullets + bullet.TracerName = TracerName + bullet.Force = damage * 0.25 -- Amount of force to give to phys objects + bullet.Damage = damage + bullet.Callback = function(attacker, tracedata, dmginfo) + return self:RicochetCallback(0, attacker, tracedata, dmginfo) + end + if IsValid(self) then + if IsValid(self.Weapon) then + if IsValid(self.Owner) then + self.Owner:FireBullets(bullet) + end + end + end + -- //if SERVER and !self.Owner:IsNPC() then + -- // local anglo = Angle(math.Rand(-self.Primary.KickDown,-self.Primary.KickUp), math.Rand(-self.Primary.KickHorizontal,self.Primary.KickHorizontal), 0) + -- // self.Owner:ViewPunch(anglo) + + -- // local eyes = self.Owner:EyeAngles() + -- // eyes.pitch = eyes.pitch + anglo.pitch + -- // eyes.yaw = eyes.yaw + anglo.yaw + -- // if game.SinglePlayer() then self.Owner:SetEyeAngles(eyes) end + -- //end + + local anglo1 = Angle(math.Rand(-self.Primary.KickDown,-self.Primary.KickUp), math.Rand(-self.Primary.KickHorizontal,self.Primary.KickHorizontal), 0) + self.Owner:ViewPunch(anglo1) + + if SERVER and game.SinglePlayer() and !self.Owner:IsNPC() then + local offlineeyes = self.Owner:EyeAngles() + offlineeyes.pitch = offlineeyes.pitch + anglo1.pitch + offlineeyes.yaw = offlineeyes.yaw + anglo1.yaw + if GetConVar("M9KDynamicRecoil"):GetBool() then + self.Owner:SetEyeAngles(offlineeyes) + end + end + + if CLIENT and !game.SinglePlayer() and !self.Owner:IsNPC() then + local anglo = Angle(math.Rand(-self.Primary.KickDown,-self.Primary.KickUp), math.Rand(-self.Primary.KickHorizontal,self.Primary.KickHorizontal), 0) + + local eyes = self.Owner:EyeAngles() + eyes.pitch = eyes.pitch + (anglo.pitch/3) + eyes.yaw = eyes.yaw + (anglo.yaw/3) + if GetConVar("M9KDynamicRecoil"):GetBool() then + self.Owner:SetEyeAngles(eyes) + end + end + +end + +/*--------------------------------------------------------- + Name: SWEP:RicochetCallback() +-----------------------------------------------------*/ + +function SWEP:RicochetCallback(bouncenum, attacker, tr, dmginfo) + + if not IsFirstTimePredicted() then + return {damage = false, effects = false} + end + + local PenetrationChecker = false + + if GetConVar("M9KDisablePenetration") == nil then + PenetrationChecker = false + else + PenetrationChecker = GetConVar("M9KDisablePenetration"):GetBool() + end + + if PenetrationChecker then return {damage = true, effects = DoDefaultEffect} end + + bulletmiss = {} + bulletmiss[1]=Sound("weapons/fx/nearmiss/bulletLtoR03.wav") + bulletmiss[2]=Sound("weapons/fx/nearmiss/bulletLtoR04.wav") + bulletmiss[3]=Sound("weapons/fx/nearmiss/bulletLtoR06.wav") + bulletmiss[4]=Sound("weapons/fx/nearmiss/bulletLtoR07.wav") + bulletmiss[5]=Sound("weapons/fx/nearmiss/bulletLtoR09.wav") + bulletmiss[6]=Sound("weapons/fx/nearmiss/bulletLtoR10.wav") + bulletmiss[7]=Sound("weapons/fx/nearmiss/bulletLtoR13.wav") + bulletmiss[8]=Sound("weapons/fx/nearmiss/bulletLtoR14.wav") + + local DoDefaultEffect = true + if (tr.HitSky) then return end + + // -- Can we go through whatever we hit? + if (self.Penetration) and (self:BulletPenetrate(bouncenum, attacker, tr, dmginfo)) then + return {damage = true, effects = DoDefaultEffect} + end + + // -- Your screen will shake and you'll hear the savage hiss of an approaching bullet which passing if someone is shooting at you. + if (tr.MatType != MAT_METAL) then + if (SERVER) then + util.ScreenShake(tr.HitPos, 5, 0.1, 0.5, 64) + sound.Play(table.Random(bulletmiss), tr.HitPos, 75, math.random(75,150), 1) + end + + if self.Tracer == 0 or self.Tracer == 1 or self.Tracer == 2 then + local effectdata = EffectData() + effectdata:SetOrigin(tr.HitPos) + effectdata:SetNormal(tr.HitNormal) + effectdata:SetScale(20) + util.Effect("AR2Impact", effectdata) + elseif self.Tracer == 3 then + local effectdata = EffectData() + effectdata:SetOrigin(tr.HitPos) + effectdata:SetNormal(tr.HitNormal) + effectdata:SetScale(20) + util.Effect("StunstickImpact", effectdata) + end + + return + end + + if (self.Ricochet == false) then return {damage = true, effects = DoDefaultEffect} end + + if self.Primary.Ammo == "SniperPenetratedRound" then -- .50 Ammo + self.MaxRicochet = 12 + elseif self.Primary.Ammo == "pistol" then -- pistols + self.MaxRicochet = 2 + elseif self.Primary.Ammo == "357" then -- revolvers with big ass bullets + self.MaxRicochet = 4 + elseif self.Primary.Ammo == "smg1" then -- smgs + self.MaxRicochet = 5 + elseif self.Primary.Ammo == "ar2" then -- assault rifles + self.MaxRicochet = 8 + elseif self.Primary.Ammo == "buckshot" then -- shotguns + self.MaxRicochet = 1 + elseif self.Primary.Ammo == "slam" then -- secondary shotguns + self.MaxRicochet = 1 + elseif self.Primary.Ammo == "AirboatGun" then -- metal piercing shotgun pellet + self.MaxRicochet = 8 + end + + if (bouncenum > self.MaxRicochet) then return end + + // -- Bounce vector + local trace = {} + trace.start = tr.HitPos + trace.endpos = trace.start + (tr.HitNormal * 16384) + + local trace = util.TraceLine(trace) + + local DotProduct = tr.HitNormal:Dot(tr.Normal * -1) + + local ricochetbullet = {} + ricochetbullet.Num = 1 + ricochetbullet.Src = tr.HitPos + (tr.HitNormal * 5) + ricochetbullet.Dir = ((2 * tr.HitNormal * DotProduct) + tr.Normal) + (VectorRand() * 0.05) + ricochetbullet.Spread = Vector(0, 0, 0) + ricochetbullet.Tracer = 1 + ricochetbullet.TracerName = "m9k_effect_mad_ricochet_trace" + ricochetbullet.Force = dmginfo:GetDamage() * 0.15 + ricochetbullet.Damage = dmginfo:GetDamage() * 0.5 + ricochetbullet.Callback = function(a, b, c) + if (self.Ricochet) then + local impactnum + if tr.MatType == MAT_GLASS then impactnum = 0 else impactnum = 1 end + return self:RicochetCallback(bouncenum + impactnum, a, b, c) end + end + + timer.Simple(0, function() attacker:FireBullets(ricochetbullet) end) + + return {damage = true, effects = DoDefaultEffect} +end + + +/*--------------------------------------------------------- + Name: SWEP:BulletPenetrate() +-----------------------------------------------------*/ +function SWEP:BulletPenetrate(bouncenum, attacker, tr, paininfo) + + local MaxPenetration + + if self.Primary.Ammo == "SniperPenetratedRound" then -- .50 Ammo + MaxPenetration = 20 + elseif self.Primary.Ammo == "pistol" then -- pistols + MaxPenetration = 9 + elseif self.Primary.Ammo == "357" then -- revolvers with big ass bullets + MaxPenetration = 12 + elseif self.Primary.Ammo == "smg1" then -- smgs + MaxPenetration = 14 + elseif self.Primary.Ammo == "ar2" then -- assault rifles + MaxPenetration = 16 + elseif self.Primary.Ammo == "buckshot" then -- shotguns + MaxPenetration = 5 + elseif self.Primary.Ammo == "slam" then -- secondary shotguns + MaxPenetration = 5 + elseif self.Primary.Ammo == "AirboatGun" then -- metal piercing shotgun pellet + MaxPenetration = 17 + else + MaxPenetration = 14 + end + + local DoDefaultEffect = true + // -- Don't go through metal, sand or player + + if self.Primary.Ammo == "pistol" or + self.Primary.Ammo == "buckshot" or + self.Primary.Ammo == "slam" then self.Ricochet = true + else + if self.RicochetCoin == 1 then + self.Ricochet = true + elseif self.RicochetCoin >= 2 then + self.Ricochet = false + end + end + + if self.Primary.Ammo == "SniperPenetratedRound" then self.Ricochet = true end + + if self.Primary.Ammo == "SniperPenetratedRound" then -- .50 Ammo + self.MaxRicochet = 10 + elseif self.Primary.Ammo == "pistol" then -- pistols + self.MaxRicochet = 2 + elseif self.Primary.Ammo == "357" then -- revolvers with big ass bullets + self.MaxRicochet = 5 + elseif self.Primary.Ammo == "smg1" then -- smgs + self.MaxRicochet = 4 + elseif self.Primary.Ammo == "ar2" then -- assault rifles + self.MaxRicochet = 5 + elseif self.Primary.Ammo == "buckshot" then -- shotguns + self.MaxRicochet = 0 + elseif self.Primary.Ammo == "slam" then -- secondary shotguns + self.MaxRicochet = 0 + elseif self.Primary.Ammo == "AirboatGun" then -- metal piercing shotgun pellet + self.MaxRicochet = 8 + end + + if (tr.MatType == MAT_METAL and self.Ricochet == true and self.Primary.Ammo != "SniperPenetratedRound" ) then return false end + + // -- Don't go through more than 3 times + if (bouncenum > self.MaxRicochet) then return false end + + // -- Direction (and length) that we are going to penetrate + local PenetrationDirection = tr.Normal * MaxPenetration + + if (tr.MatType == MAT_GLASS or tr.MatType == MAT_PLASTIC or tr.MatType == MAT_WOOD or tr.MatType == MAT_FLESH or tr.MatType == MAT_ALIENFLESH) then + PenetrationDirection = tr.Normal * (MaxPenetration * 2) + end + + local trace = {} + trace.endpos = tr.HitPos + trace.start = tr.HitPos + PenetrationDirection + trace.mask = MASK_SHOT + trace.filter = {self.Owner} + + local trace = util.TraceLine(trace) + + // -- Bullet didn't penetrate. + if (trace.StartSolid or trace.Fraction >= 1.0 or tr.Fraction <= 0.0) then return false end + + // -- Damage multiplier depending on surface + local fDamageMulti = 0.5 + + if self.Primary.Ammo == "SniperPenetratedRound" then + fDamageMulti = 1 + elseif(tr.MatType == MAT_CONCRETE or tr.MatType == MAT_METAL) then + fDamageMulti = 0.3 + elseif (tr.MatType == MAT_WOOD or tr.MatType == MAT_PLASTIC or tr.MatType == MAT_GLASS) then + fDamageMulti = 0.8 + elseif (tr.MatType == MAT_FLESH or tr.MatType == MAT_ALIENFLESH) then + fDamageMulti = 0.9 + end + + local damagedice = math.Rand(.85,1.3) + local newdamage = self.Primary.Damage * damagedice + + // -- Fire bullet from the exit point using the original trajectory + local penetratedbullet = {} + penetratedbullet.Num = 1 + penetratedbullet.Src = trace.HitPos + penetratedbullet.Dir = tr.Normal + penetratedbullet.Spread = Vector(0, 0, 0) + penetratedbullet.Tracer = 2 + penetratedbullet.TracerName = "m9k_effect_mad_penetration_trace" + penetratedbullet.Force = 5 + penetratedbullet.Damage = paininfo:GetDamage() * fDamageMulti + penetratedbullet.Callback = function(a, b, c) if (self.Ricochet) then + local impactnum + if tr.MatType == MAT_GLASS then impactnum = 0 else impactnum = 1 end + return self:RicochetCallback(bouncenum + impactnum, a,b,c) end end + + timer.Simple(0, function() if attacker != nil then attacker:FireBullets(penetratedbullet) end end) + + return true +end + + +function SWEP:SecondaryAttack() + return false +end + +function SWEP:Reload() + if not IsValid(self) then return end if not IsValid(self.Owner) then return end + + if self.Owner:IsNPC() then + self.Weapon:DefaultReload(ACT_VM_RELOAD) + return end + + if self.Owner:KeyDown(IN_USE) then return end + + if self.Silenced then + self.Weapon:DefaultReload(ACT_VM_RELOAD_SILENCED) + else + self.Weapon:DefaultReload(ACT_VM_RELOAD) + end + + if !self.Owner:IsNPC() then + if self.Owner:GetViewModel() == nil then self.ResetSights = CurTime() + 3 else + self.ResetSights = CurTime() + self.Owner:GetViewModel():SequenceDuration() + end + end + + if SERVER and self.Weapon != nil then + if ( self.Weapon:Clip1() < self.Primary.ClipSize ) and !self.Owner:IsNPC() then + -- //When the current clip < full clip and the rest of your ammo > 0, then + self.Owner:SetFOV( 0, 0.3 ) + -- //Zoom = 0 + self:SetIronsights(false) + -- //Set the ironsight to false + self.Weapon:SetNWBool("Reloading", true) + end + local waitdammit = (self.Owner:GetViewModel():SequenceDuration()) + timer.Simple(waitdammit + .1, + function() + if self.Weapon == nil then return end + self.Weapon:SetNWBool("Reloading", false) + if self.Owner:KeyDown(IN_ATTACK2) and self.Weapon:GetClass() == self.Gun then + if CLIENT then return end + if self.Scoped == false then + self.Owner:SetFOV( self.Secondary.IronFOV, 0.3 ) + self.IronSightsPos = self.SightsPos -- Bring it up + self.IronSightsAng = self.SightsAng -- Bring it up + self:SetIronsights(true, self.Owner) + self.DrawCrosshair = false + else return end + elseif self.Owner:KeyDown(IN_SPEED) and self.Weapon:GetClass() == self.Gun then + if self.Weapon:GetNextPrimaryFire() <= (CurTime() + .03) then + self.Weapon:SetNextPrimaryFire(CurTime()+0.3) -- Make it so you can't shoot for another quarter second + end + self.IronSightsPos = self.RunSightsPos -- Hold it down + self.IronSightsAng = self.RunSightsAng -- Hold it down + self:SetIronsights(true, self.Owner) -- Set the ironsight true + self.Owner:SetFOV( 0, 0.3 ) + else return end + end) + end +end + +function SWEP:PostReloadScopeCheck() + if self.Weapon == nil then return end + self.Weapon:SetNWBool("Reloading", false) + if self.Owner:KeyDown(IN_ATTACK2) and self.Weapon:GetClass() == self.Gun then + if CLIENT then return end + if self.Scoped == false then + self.Owner:SetFOV( self.Secondary.IronFOV, 0.3 ) + self.IronSightsPos = self.SightsPos -- Bring it up + self.IronSightsAng = self.SightsAng -- Bring it up + self:SetIronsights(true, self.Owner) + self.DrawCrosshair = false + else return end + elseif self.Owner:KeyDown(IN_SPEED) and self.Weapon:GetClass() == self.Gun then + if self.Weapon:GetNextPrimaryFire() <= (CurTime() + .03) then + self.Weapon:SetNextPrimaryFire(CurTime()+0.3) -- Make it so you can't shoot for another quarter second + end + self.IronSightsPos = self.RunSightsPos -- Hold it down + self.IronSightsAng = self.RunSightsAng -- Hold it down + self:SetIronsights(true, self.Owner) -- Set the ironsight true + self.Owner:SetFOV( 0, 0.3 ) + else return end +end + +function SWEP:Silencer() + + if self.NextSilence > CurTime() then return end + + if self.Weapon != nil then + self.Owner:SetFOV( 0, 0.3 ) + self:SetIronsights(false) + self.Weapon:SetNWBool("Reloading", true) -- i know we're not reloading but it works + end + + if self.Silenced then + self:SendWeaponAnim(ACT_VM_DETACH_SILENCER) + self.Silenced = false + elseif not self.Silenced then + self:SendWeaponAnim(ACT_VM_ATTACH_SILENCER) + self.Silenced = true + end + + siltimer = CurTime() + (self.Owner:GetViewModel():SequenceDuration()) + 0.1 + if self.Weapon:GetNextPrimaryFire() <= siltimer then + self.Weapon:SetNextPrimaryFire(siltimer) + end + self.NextSilence = siltimer + + timer.Simple( ((self.Owner:GetViewModel():SequenceDuration()) + 0.1), + function() + if self.Weapon != nil then + self.Weapon:SetNWBool("Reloading", false) + if self.Owner:KeyDown(IN_ATTACK2) and self.Weapon:GetClass() == self.Gun then + if CLIENT then return end + if self.Scoped == false then + self.Owner:SetFOV( self.Secondary.IronFOV, 0.3 ) + self.IronSightsPos = self.SightsPos -- Bring it up + self.IronSightsAng = self.SightsAng -- Bring it up + self:SetIronsights(true, self.Owner) + self.DrawCrosshair = false + else return end + elseif self.Owner:KeyDown(IN_SPEED) and self.Weapon:GetClass() == self.Gun then + if self.Weapon:GetNextPrimaryFire() <= (CurTime()+0.3) then + self.Weapon:SetNextPrimaryFire(CurTime()+0.3) -- Make it so you can't shoot for another quarter second + end + self.IronSightsPos = self.RunSightsPos -- Hold it down + self.IronSightsAng = self.RunSightsAng -- Hold it down + self:SetIronsights(true, self.Owner) -- Set the ironsight true + self.Owner:SetFOV( 0, 0.3 ) + else return end + end + end) + +end + +function SWEP:SelectFireMode() + + if self.Primary.Automatic then + self.Primary.Automatic = false + self.NextFireSelect = CurTime() + .5 + if CLIENT then + self.Owner:PrintMessage(HUD_PRINTTALK, "Semi-automatic selected.") + end + self.Weapon:EmitSound("Weapon_AR2.Empty") + else + self.Primary.Automatic = true + self.NextFireSelect = CurTime() + .5 + if CLIENT then + self.Owner:PrintMessage(HUD_PRINTTALK, "Automatic selected.") + end + self.Weapon:EmitSound("Weapon_AR2.Empty") + end +end + + +/*--------------------------------------------------------- +IronSight +-----------------------------------------------------*/ +function SWEP:IronSight() + + if not IsValid(self) then return end + if not IsValid(self.Owner) then return end + + if !self.Owner:IsNPC() then + if self.ResetSights and CurTime() >= self.ResetSights then + self.ResetSights = nil + + if self.Silenced then + self:SendWeaponAnim(ACT_VM_IDLE_SILENCED) + else + self:SendWeaponAnim(ACT_VM_IDLE) + end + end end + + if self.CanBeSilenced and self.NextSilence < CurTime() then + if self.Owner:KeyDown(IN_USE) and self.Owner:KeyPressed(IN_ATTACK2) then + self:Silencer() + end + end + + if self.SelectiveFire and self.NextFireSelect < CurTime() and not (self.Weapon:GetNWBool("Reloading")) then + if self.Owner:KeyDown(IN_USE) and self.Owner:KeyPressed(IN_RELOAD) then + self:SelectFireMode() + end + end + +-- //copy this... + if self.Owner:KeyPressed(IN_SPEED) and not (self.Weapon:GetNWBool("Reloading")) then -- If you are running + if self.Weapon:GetNextPrimaryFire() <= (CurTime()+0.3) then + self.Weapon:SetNextPrimaryFire(CurTime()+0.3) -- Make it so you can't shoot for another quarter second + end + self.IronSightsPos = self.RunSightsPos -- Hold it down + self.IronSightsAng = self.RunSightsAng -- Hold it down + self:SetIronsights(true, self.Owner) -- Set the ironsight true + self.Owner:SetFOV( 0, 0.3 ) + self.DrawCrosshair = false + end + + if self.Owner:KeyReleased (IN_SPEED) then -- If you release run then + self:SetIronsights(false, self.Owner) -- Set the ironsight true + self.Owner:SetFOV( 0, 0.3 ) + self.DrawCrosshair = self.OrigCrossHair + end -- Shoulder the gun + +-- //down to this + if !self.Owner:KeyDown(IN_USE) and !self.Owner:KeyDown(IN_SPEED) then + -- //If the key E (Use Key) is not pressed, then + + if self.Owner:KeyPressed(IN_ATTACK2) and not (self.Weapon:GetNWBool("Reloading")) then + self.Owner:SetFOV( self.Secondary.IronFOV, 0.3 ) + self.IronSightsPos = self.SightsPos -- Bring it up + self.IronSightsAng = self.SightsAng -- Bring it up + self:SetIronsights(true, self.Owner) + self.DrawCrosshair = false + -- //Set the ironsight true + + if CLIENT then return end + end + end + + if self.Owner:KeyReleased(IN_ATTACK2) and !self.Owner:KeyDown(IN_USE) and !self.Owner:KeyDown(IN_SPEED) then + -- //If the right click is released, then + self.Owner:SetFOV( 0, 0.3 ) + self.DrawCrosshair = self.OrigCrossHair + self:SetIronsights(false, self.Owner) + -- //Set the ironsight false + + if CLIENT then return end + end + + if self.Owner:KeyDown(IN_ATTACK2) and !self.Owner:KeyDown(IN_USE) and !self.Owner:KeyDown(IN_SPEED) then + self.SwayScale = 0.05 + self.BobScale = 0.05 + else + self.SwayScale = 1.0 + self.BobScale = 1.0 + end +end + +/*--------------------------------------------------------- +Think +-----------------------------------------------------*/ +function SWEP:Think() + +self:IronSight() + +end + +/*--------------------------------------------------------- +GetViewModelPosition +-----------------------------------------------------*/ +local IRONSIGHT_TIME = 0.3 +-- //Time to enter in the ironsight mod + +function SWEP:GetViewModelPosition(pos, ang) + + if (not self.IronSightsPos) then return pos, ang end + + local bIron = self.Weapon:GetNWBool("M9K_Ironsights") + + if (bIron != self.bLastIron) then + self.bLastIron = bIron + self.fIronTime = CurTime() + + end + + local fIronTime = self.fIronTime or 0 + + if (not bIron and fIronTime < CurTime() - IRONSIGHT_TIME) then + return pos, ang + end + + local Mul = 1.0 + + if (fIronTime > CurTime() - IRONSIGHT_TIME) then + Mul = math.Clamp((CurTime() - fIronTime) / IRONSIGHT_TIME, 0, 1) + + if not bIron then Mul = 1 - Mul end + end + + local Offset = self.IronSightsPos + + if (self.IronSightsAng) then + ang = ang * 1 + ang:RotateAroundAxis(ang:Right(), self.IronSightsAng.x * Mul) + ang:RotateAroundAxis(ang:Up(), self.IronSightsAng.y * Mul) + ang:RotateAroundAxis(ang:Forward(), self.IronSightsAng.z * Mul) + end + + local Right = ang:Right() + local Up = ang:Up() + local Forward = ang:Forward() + + pos = pos + Offset.x * Right * Mul + pos = pos + Offset.y * Forward * Mul + pos = pos + Offset.z * Up * Mul + + return pos, ang +end + +/*--------------------------------------------------------- +SetIronsights +-----------------------------------------------------*/ +function SWEP:SetIronsights(b) + self.Weapon:SetNWBool("M9K_Ironsights", b) +end + +function SWEP:GetIronsights() + return self.Weapon:GetNWBool("M9K_Ironsights") +end + + +if CLIENT then + + SWEP.vRenderOrder = nil + function SWEP:ViewModelDrawn() + + if not IsValid(self) then return end + if not IsValid(self.Owner) then return end + local vm = self.Owner:GetViewModel() + if !IsValid(vm) then return end + + if (!self.VElements) then return end + + self:UpdateBonePositions(vm) + + if (!self.vRenderOrder) then + + -- // we build a render order because sprites need to be drawn after models + self.vRenderOrder = {} + + for k, v in pairs( self.VElements ) do + if (v.type == "Model") then + table.insert(self.vRenderOrder, 1, k) + elseif (v.type == "Sprite" or v.type == "Quad") then + table.insert(self.vRenderOrder, k) + end + end + + end + + for k, name in ipairs( self.vRenderOrder ) do + + local v = self.VElements[name] + if (!v) then self.vRenderOrder = nil break end + if (v.hide) then continue end + + local model = v.modelEnt + local sprite = v.spriteMaterial + + if (!v.bone) then continue end + + local pos, ang = self:GetBoneOrientation( self.VElements, v, vm ) + + if (!pos) then continue end + + if (v.type == "Model" and IsValid(model)) then + + model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z ) + ang:RotateAroundAxis(ang:Up(), v.angle.y) + ang:RotateAroundAxis(ang:Right(), v.angle.p) + ang:RotateAroundAxis(ang:Forward(), v.angle.r) + + model:SetAngles(ang) + -- //model:SetModelScale(v.size) + local matrix = Matrix() + matrix:Scale(v.size) + model:EnableMatrix( "RenderMultiply", matrix ) + + if (v.material == "") then + model:SetMaterial("") + elseif (model:GetMaterial() != v.material) then + model:SetMaterial( v.material ) + end + + if (v.skin and v.skin != model:GetSkin()) then + model:SetSkin(v.skin) + end + + if (v.bodygroup) then + for k, v in pairs( v.bodygroup ) do + if (model:GetBodygroup(k) != v) then + model:SetBodygroup(k, v) + end + end + end + + if (v.surpresslightning) then + render.SuppressEngineLighting(true) + end + + render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255) + render.SetBlend(v.color.a/255) + model:DrawModel() + render.SetBlend(1) + render.SetColorModulation(1, 1, 1) + + if (v.surpresslightning) then + render.SuppressEngineLighting(false) + end + + elseif (v.type == "Sprite" and sprite) then + + local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z + render.SetMaterial(sprite) + render.DrawSprite(drawpos, v.size.x, v.size.y, v.color) + + elseif (v.type == "Quad" and v.draw_func) then + + local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z + ang:RotateAroundAxis(ang:Up(), v.angle.y) + ang:RotateAroundAxis(ang:Right(), v.angle.p) + ang:RotateAroundAxis(ang:Forward(), v.angle.r) + + cam.Start3D2D(drawpos, ang, v.size) + v.draw_func( self ) + cam.End3D2D() + + end + + end + + end + + SWEP.wRenderOrder = nil + function SWEP:DrawWorldModel() + + if (self.ShowWorldModel == nil or self.ShowWorldModel) then + self:DrawModel() + end + + if (!self.WElements) then return end + + if (!self.wRenderOrder) then + + self.wRenderOrder = {} + + for k, v in pairs( self.WElements ) do + if (v.type == "Model") then + table.insert(self.wRenderOrder, 1, k) + elseif (v.type == "Sprite" or v.type == "Quad") then + table.insert(self.wRenderOrder, k) + end + end + + end + + if (IsValid(self.Owner)) then + bone_ent = self.Owner + else + -- // when the weapon is dropped + bone_ent = self + end + + for k, name in pairs( self.wRenderOrder ) do + + local v = self.WElements[name] + if (!v) then self.wRenderOrder = nil break end + if (v.hide) then continue end + + local pos, ang + + if (v.bone) then + pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent ) + else + pos, ang = self:GetBoneOrientation( self.WElements, v, bone_ent, "ValveBiped.Bip01_R_Hand" ) + end + + if (!pos) then continue end + + local model = v.modelEnt + local sprite = v.spriteMaterial + + if (v.type == "Model" and IsValid(model)) then + + model:SetPos(pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z ) + ang:RotateAroundAxis(ang:Up(), v.angle.y) + ang:RotateAroundAxis(ang:Right(), v.angle.p) + ang:RotateAroundAxis(ang:Forward(), v.angle.r) + + model:SetAngles(ang) + -- //model:SetModelScale(v.size) + local matrix = Matrix() + matrix:Scale(v.size) + model:EnableMatrix( "RenderMultiply", matrix ) + + if (v.material == "") then + model:SetMaterial("") + elseif (model:GetMaterial() != v.material) then + model:SetMaterial( v.material ) + end + + if (v.skin and v.skin != model:GetSkin()) then + model:SetSkin(v.skin) + end + + if (v.bodygroup) then + for k, v in pairs( v.bodygroup ) do + if (model:GetBodygroup(k) != v) then + model:SetBodygroup(k, v) + end + end + end + + if (v.surpresslightning) then + render.SuppressEngineLighting(true) + end + + render.SetColorModulation(v.color.r/255, v.color.g/255, v.color.b/255) + render.SetBlend(v.color.a/255) + model:DrawModel() + render.SetBlend(1) + render.SetColorModulation(1, 1, 1) + + if (v.surpresslightning) then + render.SuppressEngineLighting(false) + end + + elseif (v.type == "Sprite" and sprite) then + + local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z + render.SetMaterial(sprite) + render.DrawSprite(drawpos, v.size.x, v.size.y, v.color) + + elseif (v.type == "Quad" and v.draw_func) then + + local drawpos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z + ang:RotateAroundAxis(ang:Up(), v.angle.y) + ang:RotateAroundAxis(ang:Right(), v.angle.p) + ang:RotateAroundAxis(ang:Forward(), v.angle.r) + + cam.Start3D2D(drawpos, ang, v.size) + v.draw_func( self ) + cam.End3D2D() + + end + + end + + end + + function SWEP:GetBoneOrientation( basetab, tab, ent, bone_override ) + + local bone, pos, ang + if (tab.rel and tab.rel != "") then + + local v = basetab[tab.rel] + + if (!v) then return end + + -- // Technically, if there exists an element with the same name as a bone + -- // you can get in an infinite loop. Let's just hope nobody's that stupid. + pos, ang = self:GetBoneOrientation( basetab, v, ent ) + + if (!pos) then return end + + pos = pos + ang:Forward() * v.pos.x + ang:Right() * v.pos.y + ang:Up() * v.pos.z + ang:RotateAroundAxis(ang:Up(), v.angle.y) + ang:RotateAroundAxis(ang:Right(), v.angle.p) + ang:RotateAroundAxis(ang:Forward(), v.angle.r) + + else + + bone = ent:LookupBone(bone_override or tab.bone) + + if (!bone) then return end + + pos, ang = Vector(0,0,0), Angle(0,0,0) + local m = ent:GetBoneMatrix(bone) + if (m) then + pos, ang = m:GetTranslation(), m:GetAngles() + end + + if (IsValid(self.Owner) and self.Owner:IsPlayer() and + ent == self.Owner:GetViewModel() and self.ViewModelFlip) then + ang.r = -ang.r --// Fixes mirrored models + end + + end + + return pos, ang + end + + function SWEP:CreateModels( tab ) + + if (!tab) then return end + + -- // Create the clientside models here because Garry says we can't do it in the render hook + for k, v in pairs( tab ) do + if (v.type == "Model" and v.model and v.model != "" and (!IsValid(v.modelEnt) or v.createdModel != v.model) and + string.find(v.model, ".mdl") and file.Exists (v.model, "GAME") ) then + + v.modelEnt = ClientsideModel(v.model, RENDER_GROUP_VIEW_MODEL_OPAQUE) + if (IsValid(v.modelEnt)) then + v.modelEnt:SetPos(self:GetPos()) + v.modelEnt:SetAngles(self:GetAngles()) + v.modelEnt:SetParent(self) + v.modelEnt:SetNoDraw(true) + v.createdModel = v.model + else + v.modelEnt = nil + end + + elseif (v.type == "Sprite" and v.sprite and v.sprite != "" and (!v.spriteMaterial or v.createdSprite != v.sprite) + and file.Exists ("materials/"..v.sprite..".vmt", "GAME")) then + + local name = v.sprite.."-" + local params = { ["$basetexture"] = v.sprite } + -- // make sure we create a unique name based on the selected options + local tocheck = { "nocull", "additive", "vertexalpha", "vertexcolor", "ignorez" } + for i, j in pairs( tocheck ) do + if (v[j]) then + params["$"..j] = 1 + name = name.."1" + else + name = name.."0" + end + end + + v.createdSprite = v.sprite + v.spriteMaterial = CreateMaterial(name,"UnlitGeneric",params) + + end + end + + end + + local allbones + local hasGarryFixedBoneScalingYet = false + + function SWEP:UpdateBonePositions(vm) + + if self.ViewModelBoneMods then + + if (!vm:GetBoneCount()) then return end + + -- // !! WORKAROUND !! --// + -- // We need to check all model names :/ + local loopthrough = self.ViewModelBoneMods + if (!hasGarryFixedBoneScalingYet) then + allbones = {} + for i=0, vm:GetBoneCount() do + local bonename = vm:GetBoneName(i) + if (self.ViewModelBoneMods[bonename]) then + allbones[bonename] = self.ViewModelBoneMods[bonename] + else + allbones[bonename] = { + scale = Vector(1,1,1), + pos = Vector(0,0,0), + angle = Angle(0,0,0) + } + end + end + + loopthrough = allbones + end + //!! ----------- !! -- + + for k, v in pairs( loopthrough ) do + local bone = vm:LookupBone(k) + if (!bone) then continue end + + -- // !! WORKAROUND !! --// + local s = Vector(v.scale.x,v.scale.y,v.scale.z) + local p = Vector(v.pos.x,v.pos.y,v.pos.z) + local ms = Vector(1,1,1) + if (!hasGarryFixedBoneScalingYet) then + local cur = vm:GetBoneParent(bone) + while(cur >= 0) do + local pscale = loopthrough[vm:GetBoneName(cur)].scale + ms = ms * pscale + cur = vm:GetBoneParent(cur) + end + end + + s = s * ms + //!! ----------- !! -- + + if vm:GetManipulateBoneScale(bone) != s then + vm:ManipulateBoneScale( bone, s ) + end + if vm:GetManipulateBoneAngles(bone) != v.angle then + vm:ManipulateBoneAngles( bone, v.angle ) + end + if vm:GetManipulateBonePosition(bone) != p then + vm:ManipulateBonePosition( bone, p ) + end + end + else + self:ResetBonePositions(vm) + end + + end + + function SWEP:ResetBonePositions(vm) + + if (!vm:GetBoneCount()) then return end + for i=0, vm:GetBoneCount() do + vm:ManipulateBoneScale( i, Vector(1, 1, 1) ) + vm:ManipulateBoneAngles( i, Angle(0, 0, 0) ) + vm:ManipulateBonePosition( i, Vector(0, 0, 0) ) + end + + end + + /************************** + Global utility code + **************************/ + + -- // Fully copies the table, meaning all tables inside this table are copied too and so on (normal table.Copy copies only their reference). + -- // Does not copy entities of course, only copies their reference. + -- // WARNING: do not use on tables that contain themselves somewhere down the line or you'll get an infinite loop + function table.FullCopy( tab ) + + if (!tab) then return nil end + + local res = {} + for k, v in pairs( tab ) do + if (type(v) == "table") then + res[k] = table.FullCopy(v) --// recursion ho! + elseif (type(v) == "Vector") then + res[k] = Vector(v.x, v.y, v.z) + elseif (type(v) == "Angle") then + res[k] = Angle(v.p, v.y, v.r) + else + res[k] = v + end + end + + return res + + end + +end + |
