AddCSLuaFile() ENT.Base = "tacrp_proj_base" ENT.PrintName = "M202 Harpoon" ENT.Spawnable = false ENT.Model = "models/props_junk/harpoon002a.mdl" ENT.IsRocket = false // projectile has a booster and will not drop. ENT.InstantFuse = false // projectile is armed immediately after firing. ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator. ENT.ImpactFuse = true // projectile explodes on impact. ENT.SmokeTrail = false local path = "tacrp/weapons/knife/" ENT.Sound_MeleeHit = { path .. "/scrape_metal-1.wav", path .. "/scrape_metal-2.wav", path .. "/scrape_metal-3.wav", } ENT.Sound_MeleeHitBody = { path .. "/flesh_hit-1.wav", path .. "/flesh_hit-2.wav", path .. "/flesh_hit-3.wav", path .. "/flesh_hit-4.wav", path .. "/flesh_hit-5.wav", } function ENT:OnInitialize() if SERVER then self:GetPhysicsObject():SetMass(25) self:GetPhysicsObject():SetDragCoefficient(10) self:Ignite(30) end end function ENT:Impact(data, collider) local tgt = data.HitEntity local attacker = self.Attacker or self:GetOwner() or self local d = data.OurOldVelocity:GetNormalized() local forward = data.OurOldVelocity:Dot(self:GetAngles():Forward()) if forward <= 100 then return true end if IsValid(tgt) then local ang = data.OurOldVelocity:Angle() local fx = EffectData() fx:SetOrigin(data.HitPos) fx:SetNormal(-ang:Forward()) fx:SetAngles(-ang) util.Effect("ManhackSparks", fx) if IsValid(data.HitEntity) then data.HitEntity:Ignite(math.Rand(5, 10), 128) local dmginfo = DamageInfo() dmginfo:SetAttacker(attacker) dmginfo:SetInflictor(self) dmginfo:SetDamageType(DMG_CLUB) dmginfo:SetDamage(self.NPCDamage and 25 or math.Clamp(forward / 70, 10, 200)) dmginfo:SetDamageForce(data.OurOldVelocity) dmginfo:SetDamagePosition(data.HitPos) data.HitEntity:TakeDamageInfo(dmginfo) end else local ang = data.OurOldVelocity:Angle() local fx = EffectData() fx:SetOrigin(data.HitPos) fx:SetNormal(-ang:Forward()) fx:SetAngles(-ang) util.Effect("ManhackSparks", fx) if SERVER then self:EmitSound(istable(self.Sound_MeleeHit) and self.Sound_MeleeHit[math.random(1, #self.Sound_MeleeHit)] or self.Sound_MeleeHit, 80, 110, 1) end -- leave a bullet hole. Also may be able to hit things it can't collide with (like stuck C4) self:FireBullets({ Attacker = attacker, Damage = self.Damage, Force = 1, Distance = 4, HullSize = 4, Tracer = 0, Dir = ang:Forward(), Src = data.HitPos - ang:Forward(), IgnoreEntity = self, Callback = function(atk, tr, dmginfo) dmginfo:SetDamageType(DMG_SLASH) dmginfo:SetInflictor(attacker) end }) end if tgt:IsWorld() or (IsValid(tgt) and tgt:GetPhysicsObject():IsValid()) then local angles = data.OurOldVelocity:Angle() self:GetPhysicsObject():Sleep() timer.Simple(0, function() if tgt:IsWorld() or (IsValid(tgt) and (!(tgt:IsNPC() or tgt:IsPlayer()) or tgt:Health() > 0)) then self:SetSolid(SOLID_NONE) self:SetMoveType(MOVETYPE_NONE) local f = {self, self:GetOwner()} table.Add(f, tgt:GetChildren()) local tr = util.TraceLine({ start = data.HitPos - data.OurOldVelocity, endpos = data.HitPos + data.OurOldVelocity, filter = f, mask = MASK_SOLID, ignoreworld = true, }) local bone = (tr.Entity == tgt) and tr.PhysicsBone == 0 and tr.Entity:GetHitBoxBone(tr.HitBox, tr.Entity:GetHitboxSet()) or tr.PhysicsBone or -1 local matrix = tgt:GetBoneMatrix(bone) if tr.Entity == tgt and matrix then local bpos = matrix:GetTranslation() local bang = matrix:GetAngles() self:SetPos(data.HitPos) self:FollowBone(tgt, bone) local n_pos, n_ang = WorldToLocal(tr.HitPos + tr.HitNormal * self:GetModelRadius() * 0.5, angles, bpos, bang) self:SetLocalPos(n_pos) self:SetLocalAngles(n_ang) debugoverlay.Cross(pos, 8, 5, Color(255, 0, 255), true) else self:SetAngles(angles) self:SetPos(data.HitPos - data.OurOldVelocity:GetNormalized() * self:GetModelRadius() * 0.5) if !tgt:IsWorld() then self:SetParent(tgt) end end else self:GetPhysicsObject():SetVelocity(data.OurOldVelocity * 0.75) self:GetPhysicsObject():SetAngleVelocity(data.OurOldAngularVelocity) self.Armed = false end end) end timer.Simple(5, function() if IsValid(self) then self:SetRenderMode(RENDERMODE_TRANSALPHA) self:SetRenderFX(kRenderFxFadeFast) end end) SafeRemoveEntityDelayed(self, 7) return true end local g = Vector(0, 0, -9.81) function ENT:PhysicsUpdate(phys) if !self.Armed and phys:IsGravityEnabled() and self:WaterLevel() <= 2 then local v = phys:GetVelocity() self:SetAngles(v:Angle()) phys:SetVelocityInstantaneous(v * 0.985 + g) end -- local v = phys:GetVelocity() -- self:SetAngles(v:Angle() + Angle(2, 0, 0)) -- phys:SetVelocityInstantaneous(self:GetForward() * v:Length()) end ENT.SmokeTrail = true local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"} local function GetSmokeImage() return smokeimages[math.random(#smokeimages)] end function ENT:DoSmokeTrail() if CLIENT and self.SmokeTrail and self:GetVelocity():Length() >= 100 then local pos = self:GetPos() + self:GetUp() * 4 local emitter = ParticleEmitter(pos) local smoke = emitter:Add(GetSmokeImage(), pos) smoke:SetStartAlpha(100) smoke:SetEndAlpha(0) smoke:SetStartSize(2) smoke:SetEndSize(math.Rand(16, 24)) smoke:SetRoll(math.Rand(-180, 180)) smoke:SetRollDelta(math.Rand(-1, 1)) smoke:SetVelocity(VectorRand() * 8 + self:GetUp() * 16) smoke:SetColor(200, 200, 200) smoke:SetLighting(true) smoke:SetDieTime(math.Rand(0.5, 0.75)) smoke:SetGravity(Vector(0, 0, 15)) local fire = emitter:Add("effects/fire_cloud" .. math.random(1, 2), pos) fire:SetStartAlpha(150) fire:SetEndAlpha(0) fire:SetStartSize(math.Rand(2, 4)) fire:SetEndSize(math.Rand(8, 16)) fire:SetRoll(math.Rand(-180, 180)) fire:SetRollDelta(math.Rand(-1, 1)) fire:SetVelocity(VectorRand() * 16 + self:GetUp() * 16) fire:SetLighting(false) fire:SetDieTime(math.Rand(0.1, 0.3)) fire:SetGravity(Vector(0, 0, 50)) emitter:Finish() end end