add sborka
This commit is contained in:
257
garrysmod/addons/tacrp/lua/entities/tacrp_proj_knife.lua
Normal file
257
garrysmod/addons/tacrp/lua/entities/tacrp_proj_knife.lua
Normal file
@@ -0,0 +1,257 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Thrown Knife"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/w_knife.mdl"
|
||||
|
||||
ENT.IsRocket = false
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
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",
|
||||
}
|
||||
|
||||
ENT.Damage = 35
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
if SERVER then
|
||||
self:GetPhysicsObject():SetDragCoefficient(2)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
if self.Impacted then return end
|
||||
self.Impacted = true
|
||||
|
||||
local tgt = data.HitEntity
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
if IsValid(tgt) then
|
||||
local d = data.OurOldVelocity:GetNormalized()
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
dmg:SetDamage(self.Damage)
|
||||
dmg:SetDamageType(self.DamageType or DMG_SLASH)
|
||||
dmg:SetDamageForce(d * 10000)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
|
||||
local tgtpos = data.HitPos
|
||||
if (tgt:IsPlayer() or tgt:IsNPC() or tgt:IsNextBot()) then
|
||||
if (tgt:GetNWFloat("TacRPLastBashed", 0) + 3 >= CurTime()
|
||||
or (tgt:GetNWFloat("TacRPStunStart", 0) + tgt:GetNWFloat("TacRPStunDur", 0) >= CurTime())) then
|
||||
dmg:ScaleDamage(1.5)
|
||||
tgt:EmitSound("weapons/crossbow/bolt_skewer1.wav", 80, 110)
|
||||
end
|
||||
|
||||
-- Check if the knife is a headshot
|
||||
-- Either the head is the closest bodygroup, or the direction is quite on point
|
||||
local headpos = nil
|
||||
local pos = data.HitPos + d * 8
|
||||
local hset = tgt:GetHitboxSet()
|
||||
local hdot, bhg, bdist, hdist = 0, 0, math.huge, math.huge
|
||||
for i = 0, tgt:GetHitBoxCount(hset) or 0 do
|
||||
|
||||
local bone = tgt:GetHitBoxBone(i, hset)
|
||||
local mtx = bone and tgt:GetBoneMatrix(bone)
|
||||
if !mtx then continue end
|
||||
local hpos = mtx:GetTranslation()
|
||||
local dot = (hpos - data.HitPos):GetNormalized():Dot(d)
|
||||
local dist = (hpos - pos):LengthSqr()
|
||||
|
||||
if tgt:GetHitBoxHitGroup(i, hset) == HITGROUP_HEAD then
|
||||
hdot = dot
|
||||
hdist = dist
|
||||
headpos = hpos
|
||||
end
|
||||
if dist < bdist then
|
||||
bdist = dist
|
||||
bhg = tgt:GetHitBoxHitGroup(i, hset)
|
||||
tgtpos = hpos
|
||||
end
|
||||
end
|
||||
|
||||
if bhg == HITGROUP_HEAD or (hdot >= 0.85 and hdist < 2500) then
|
||||
dmg:ScaleDamage(2)
|
||||
tgt:EmitSound("player/headshot" .. math.random(1, 2) .. ".wav", 80, 105)
|
||||
tgtpos = headpos
|
||||
end
|
||||
|
||||
self:EmitSound(istable(self.Sound_MeleeHitBody) and self.Sound_MeleeHitBody[math.random(1, #self.Sound_MeleeHitBody)] or self.Sound_MeleeHitBody, 80, 110, 1)
|
||||
-- self:EmitSound("tacrp/weapons/knife/flesh_hit-" .. math.random(1, 5) .. ".wav", 80, 110, 1)
|
||||
|
||||
-- local ang = data.OurOldVelocity:Angle()
|
||||
-- local fx = EffectData()
|
||||
-- fx:SetStart(data.HitPos - d * 4)
|
||||
-- fx:SetOrigin(data.HitPos)
|
||||
-- fx:SetNormal(d)
|
||||
-- fx:SetAngles(-ang)
|
||||
-- fx:SetEntity(tgt)
|
||||
-- fx:SetDamageType(DMG_SLASH)
|
||||
-- fx:SetSurfaceProp(data.TheirSurfaceProps)
|
||||
-- util.Effect("Impact", fx)
|
||||
|
||||
else
|
||||
dmg:SetDamageForce(d * 30000)
|
||||
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
|
||||
end
|
||||
|
||||
-- tgt:TakeDamageInfo(dmg)
|
||||
|
||||
local atktr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = tgtpos,
|
||||
filter = self
|
||||
})
|
||||
|
||||
TacRP.CancelBodyDamage(tgt, dmg, atktr.HitGroup)
|
||||
tgt:DispatchTraceAttack(dmg, atktr)
|
||||
else
|
||||
-- leave a bullet hole. Also may be able to hit things it can't collide with (like stuck C4)
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
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:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
if tr.HitSky then
|
||||
SafeRemoveEntity(self)
|
||||
else
|
||||
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
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
-- self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
|
||||
if self.DamageType == DMG_SLASH and (tgt:IsWorld() or (IsValid(tgt) and tgt:GetPhysicsObject():IsValid())) then
|
||||
local angles = data.OurOldVelocity:Angle()
|
||||
angles:RotateAroundAxis(self:GetRight(), -90)
|
||||
self:GetPhysicsObject():Sleep()
|
||||
|
||||
timer.Simple(0.01, function()
|
||||
if IsValid(self) and tgt:IsWorld() or (IsValid(tgt) and (!(tgt:IsNPC() or tgt:IsPlayer()) or tgt:Health() > 0)) then
|
||||
if !tgt:IsWorld() then
|
||||
self:SetSolid(SOLID_NONE)
|
||||
end
|
||||
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
|
||||
elseif IsValid(self) then
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(data.OurNewVelocity * 0.5)
|
||||
self:GetPhysicsObject():SetAngleVelocityInstantaneous(data.OurOldAngularVelocity * 0.5)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
timer.Simple(0.01, function()
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
if self.HasAmmo then
|
||||
self:SetTrigger(true)
|
||||
self:SetOwner(NULL)
|
||||
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
|
||||
|
||||
function ENT:Touch(ent)
|
||||
if self.HasAmmo and ent:IsPlayer() and (IsValid(self.Inflictor) and ent == self.Inflictor:GetOwner()) then
|
||||
self.HasAmmo = false
|
||||
ent:GiveAmmo(1, "xbowbolt")
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("PostEntityTakeDamage", "TacRP_KnifeProj", function(ent)
|
||||
if (ent:IsPlayer() or ent:IsNPC()) and ent:Health() < 0 then
|
||||
for _, proj in pairs(ent:GetChildren()) do
|
||||
if proj:GetClass() == "tacrp_proj_knife" then proj:Remove() end
|
||||
end
|
||||
end
|
||||
end)
|
||||
Reference in New Issue
Block a user