642 lines
17 KiB
Lua
642 lines
17 KiB
Lua
|
|
--[[
|
|
Stungun SWEP Created by Donkie (http://steamcommunity.com/id/Donkie/)
|
|
For personal/server usage only, do not resell or distribute!
|
|
]]
|
|
|
|
AddCSLuaFile("shared.lua")
|
|
AddCSLuaFile("config/stungun.lua")
|
|
AddCSLuaFile("cl_init.lua")
|
|
|
|
include("shared.lua")
|
|
|
|
local ragdolls = {}
|
|
|
|
function SWEP:Equip( ply )
|
|
self.BaseClass.Equip(self,ply)
|
|
self.lastowner = ply
|
|
end
|
|
|
|
util.AddNetworkString("tazerondrop")
|
|
function SWEP:OnDrop()
|
|
self.BaseClass.OnDrop(self)
|
|
if IsValid(self.lastowner) then
|
|
net.Start("tazerondrop")
|
|
net.WriteEntity(self)
|
|
net.Send(self.lastowner)
|
|
end
|
|
end
|
|
|
|
|
|
--[[
|
|
Makes a hull trace the size of a player.
|
|
]]
|
|
local hulltrdata = {}
|
|
function STUNGUN.PlayerHullTrace(pos, ply, filter)
|
|
hulltrdata.start = pos
|
|
hulltrdata.endpos = pos
|
|
hulltrdata.filter = filter
|
|
|
|
return util.TraceEntity( hulltrdata, ply )
|
|
end
|
|
|
|
--[[
|
|
Attemps to place the player at this position or as close as possible.
|
|
]]
|
|
-- Directions to check
|
|
local directions = {
|
|
Vector(0,0,0), Vector(0,0,1), -- Center and up
|
|
Vector(1,0,0), Vector(-1,0,0), Vector(0,1,0), Vector(0,-1,0) -- All cardinals
|
|
}
|
|
for deg = 45, 315, 90 do -- Diagonals
|
|
local r = math.rad(deg)
|
|
table.insert(directions, Vector(math.Round(math.cos(r)), math.Round(math.sin(r)), 0))
|
|
end
|
|
|
|
local magn = 15 -- How much increment for each iteration
|
|
local iterations = 2 -- How many iterations
|
|
function STUNGUN.PlayerSetPosNoBlock( ply, pos, filter )
|
|
local tr
|
|
|
|
local dirvec
|
|
local m = magn
|
|
local i = 1
|
|
local its = 1
|
|
repeat
|
|
dirvec = directions[i] * m
|
|
i = i + 1
|
|
if i > #directions then
|
|
its = its + 1
|
|
i = 1
|
|
m = m + magn
|
|
if its > iterations then
|
|
ply:SetPos(pos) -- We've done as many checks as we wanted, lets just force him to get stuck then.
|
|
return false
|
|
end
|
|
end
|
|
|
|
tr = STUNGUN.PlayerHullTrace(dirvec + pos, ply, filter)
|
|
until tr.Hit == false
|
|
|
|
ply:SetPos(pos + dirvec)
|
|
return true
|
|
end
|
|
|
|
--[[
|
|
Sets the player invisible/visible
|
|
]]
|
|
function STUNGUN.PlayerInvis( ply, bool )
|
|
ply:SetNoDraw(bool)
|
|
ply:DrawShadow(not bool)
|
|
ply:SetCollisionGroup(bool and COLLISION_GROUP_IN_VEHICLE or COLLISION_GROUP_PLAYER)
|
|
ply:SetNotSolid(bool)
|
|
ply:DrawWorldModel(not bool)
|
|
ply._stungunfrozen = bool
|
|
|
|
if bool then
|
|
ply:Lock()
|
|
else
|
|
ply:UnLock()
|
|
end
|
|
end
|
|
|
|
octolib.func.loop(function(done)
|
|
octolib.func.throttle(player.GetAll(), 10, 0.2, function(ply)
|
|
if IsValid(ply) and ply._stungunfrozen then
|
|
ply:DrawWorldModel(false)
|
|
end
|
|
end):Then(done)
|
|
end)
|
|
|
|
--[[
|
|
Deploy player ragdoll
|
|
]]
|
|
function STUNGUN.Ragdoll( ply, pushdir )
|
|
local plyphys = ply:GetPhysicsObject()
|
|
local plyvel = Vector(0,0,0)
|
|
if plyphys:IsValid() then
|
|
plyvel = plyphys:GetVelocity()
|
|
end
|
|
|
|
ply.tazedpos = ply:GetPos() -- Store pos incase the ragdoll is missing when we're to unrag him.
|
|
|
|
if IsValid(ply:GetVehicle()) then
|
|
ply:ExitVehicle()
|
|
end
|
|
|
|
local weapon = ply:GetActiveWeapon()
|
|
if IsValid(weapon) and not (GAMEMODE.Config.DisallowDrop[ weapon:GetClass() ] or ply:jobHasWeapon(weapon:GetClass())) then
|
|
ply:dropDRPWeapon( weapon )
|
|
end
|
|
|
|
local mdl, sk, bg = ply:GetModel(), ply:GetSkin(), ply:GetBodyGroups()
|
|
if STUNGUN.BrokenModels[mdl] then
|
|
mdl, sk, bg = STUNGUN.DefaultModel, 0, '0'
|
|
end
|
|
|
|
local rag = ents.Create("prop_ragdoll")
|
|
rag:SetModel(mdl)
|
|
rag:SetSkin(sk)
|
|
rag:SetBodyGroups(bg)
|
|
rag:SetPos(ply:GetPos())
|
|
rag:SetAngles(Angle(0,ply:GetAngles().y,0))
|
|
rag:SetColor(ply:GetColor())
|
|
rag:SetMaterial(ply:GetMaterial())
|
|
rag:Spawn()
|
|
rag:Activate()
|
|
rag:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
|
ragdolls[rag] = true
|
|
|
|
if not IsValid(rag:GetPhysicsObject()) then
|
|
SafeRemoveEntity(rag)
|
|
|
|
if STUNGUN.DefaultModel then
|
|
rag = ents.Create("prop_ragdoll")
|
|
rag:SetModel(STUNGUN.DefaultModel)
|
|
rag:SetPos(ply:GetPos())
|
|
rag:SetAngles(Angle(0,ply:GetAngles().y,0))
|
|
rag:SetColor(ply:GetColor())
|
|
rag:SetMaterial(ply:GetMaterial())
|
|
rag:Spawn()
|
|
rag:Activate()
|
|
else
|
|
MsgN("A tazed player didn't get a valid ragdoll. Model (" .. ply:GetModel() .. ")!")
|
|
return false
|
|
end
|
|
end
|
|
|
|
rag.tazesnd = CreateSound(rag, "stungun/tazer.wav")
|
|
rag.tazesnd:PlayEx(1, 70)
|
|
|
|
-- Lower inertia makes the ragdoll have trouble rolling. Citizens have 1,1,1 as default, while combines have 0.2,0.2,0.2.
|
|
rag:GetPhysicsObject():SetInertia(Vector(1,1,1))
|
|
|
|
-- Set mass of all limbs, forces and shit are weird if mass is not same.
|
|
-- for i = 1, rag:GetPhysicsObjectCount() do
|
|
-- if IsValid(rag:GetPhysicsObject(i-1)) then
|
|
-- rag:GetPhysicsObject(i-1):SetMass(12.7)
|
|
-- end
|
|
-- end
|
|
|
|
-- Push him back abit
|
|
plyvel = plyvel + pushdir * 50
|
|
|
|
-- Code copied from TTT
|
|
local num = rag:GetPhysicsObjectCount() - 1
|
|
for i = 0, num do
|
|
local bone = rag:GetPhysicsObjectNum(i)
|
|
if IsValid(bone) then
|
|
local bp, ba = ply:GetBonePosition(rag:TranslatePhysBoneToBone(i))
|
|
if bp and ba then
|
|
bone:SetPos(bp)
|
|
bone:SetAngles(ba)
|
|
end
|
|
|
|
bone:SetVelocity(plyvel)
|
|
end
|
|
end
|
|
|
|
-- Prevents any kind of pickup if user don't want him to
|
|
rag.CanPickup = STUNGUN.CanPickup
|
|
|
|
-- Handcuff support
|
|
local cuffs = ply:GetWeapon("weapon_cuffed")
|
|
if IsValid(cuffs) then
|
|
-- if cuffs:GetIsLeash() then
|
|
-- rag.isleashed = true
|
|
-- rag.leashowner = cuffs:GetKidnapper()
|
|
-- rag.ropelength = cuffs:GetRopeLength()
|
|
-- else
|
|
rag.iscuffed = true
|
|
-- end
|
|
|
|
-- rag:SetNWBool("cuffs_isleash", rag.isleashed)
|
|
end
|
|
|
|
-- Make him follow the ragdoll, if the player gets away from the ragdoll he won't get stuff rendered properly.
|
|
ply:SetParent(rag)
|
|
|
|
-- Make the player invisible.
|
|
STUNGUN.PlayerInvis(ply, true)
|
|
|
|
ply.tazeragdoll = rag
|
|
rag.tazeplayer = ply
|
|
rag:SetDTEntity(1, ply) -- Used to gain instant access to player on client
|
|
|
|
ply:SetNWEntity("tazerviewrag", rag)
|
|
rag:SetNWEntity("plyowner", ply)
|
|
ply:SetNWBool("tazefrozen", true)
|
|
ply:SetNetVar('DeathRagdoll', rag)
|
|
|
|
return true
|
|
end
|
|
|
|
function STUNGUN.UnRagdoll( ply )
|
|
local ragvalid = IsValid(ply.tazeragdoll)
|
|
local pos
|
|
if ragvalid then -- Sometimes the ragdoll is missing when we want to unrag, not good!
|
|
if ply.tazeragdoll.hasremoved then return end -- It has already been removed.
|
|
|
|
pos = ply.tazeragdoll:GetPos()
|
|
-- ply:SetModel(ply.tazeragdoll:GetModel())
|
|
if ply.tazeragdoll.tazesnd then
|
|
ply.tazeragdoll.tazesnd:Stop()
|
|
ply.tazeragdoll.tazesnd = nil
|
|
end
|
|
ply.tazeragdoll.hasremoved = true
|
|
else
|
|
pos = ply.tazedpos -- Put him at the place he got tazed, works great.
|
|
end
|
|
ply:SetParent()
|
|
|
|
STUNGUN.PlayerSetPosNoBlock(ply, pos, {ply, ply.tazeragdoll})
|
|
|
|
timer.Simple(0,function()
|
|
SafeRemoveEntity(ply.tazeragdoll)
|
|
STUNGUN.PlayerInvis(ply, false)
|
|
end)
|
|
|
|
net.Start("tazeendview")
|
|
net.Send(ply)
|
|
end
|
|
|
|
|
|
util.AddNetworkString("tazestartview")
|
|
util.AddNetworkString("tazeendview")
|
|
|
|
function STUNGUN.Electrolute( ply, pushdir )
|
|
if ply.tazeimmune then return end
|
|
|
|
-- Ragdoll
|
|
STUNGUN.Ragdoll(ply, pushdir)
|
|
|
|
-- Gag
|
|
ply.tazeismuted = true
|
|
|
|
ply:SetNetVar('Tased', true)
|
|
|
|
local id = ply:UserID()
|
|
timer.Create("Unelectrolute" .. id, STUNGUN.ParalyzedTime, 1, function()
|
|
if IsValid(ply) then STUNGUN.UnElectrolute( ply ) end
|
|
end)
|
|
timer.Create("tazeUngag" .. id, STUNGUN.MuteTime, 1, function()
|
|
if IsValid(ply) then STUNGUN.UnMute( ply ) end
|
|
end)
|
|
|
|
timer.Create("HurtingTimer" .. id,2,0,function()
|
|
if not IsValid(ply) or not IsValid(ply.tazeragdoll) then timer.Remove("HurtingTimer" .. id) return end
|
|
ply.tazeragdoll:EmitSound(STUNGUN.PlayHurtSound(ply), 70, 100, 1)
|
|
end)
|
|
|
|
hook.Call("PlayerHasBeenTazed", GAMEMODE, ply, ply.tazeragdoll)
|
|
end
|
|
|
|
function STUNGUN.UnMute( ply )
|
|
ply.tazeismuted = false
|
|
end
|
|
|
|
function STUNGUN.UnElectrolute( ply )
|
|
STUNGUN.UnRagdoll( ply )
|
|
timer.Remove("HurtingTimer" .. ply:UserID())
|
|
|
|
hook.Call("PlayerUnTazed", GAMEMODE, ply)
|
|
|
|
local unfreezef = function()
|
|
ply:SetNWBool("tazefrozen", false)
|
|
|
|
hook.Call("PlayerTazeUnFrozen", GAMEMODE, ply)
|
|
end
|
|
if (STUNGUN.FreezeTime or 0) > 0 then
|
|
timer.Create("StungunPlayerFreeze" .. ply:UserID(), STUNGUN.FreezeTime, 1, unfreezef)
|
|
else
|
|
unfreezef()
|
|
end
|
|
|
|
if STUNGUN.Immunity > 0 then
|
|
ply.tazeimmune = true
|
|
timer.Simple(STUNGUN.Immunity, function()
|
|
if IsValid(ply) then
|
|
ply.tazeimmune = false
|
|
end
|
|
end)
|
|
end
|
|
|
|
ply:SetNetVar('Tased', nil)
|
|
end
|
|
STUNGUN.Unelectrolute = STUNGUN.UnElectrolute
|
|
|
|
hook.Add("PlayerSay", "Tazer", function(ply, str)
|
|
if ply.tazeismuted then return "" end
|
|
end)
|
|
|
|
util.AddNetworkString("tazersendhealth")
|
|
hook.Add("Think", "Tazer", function()
|
|
for ragdoll, _ in pairs(ragdolls) do
|
|
if IsValid(ragdoll) and IsValid(ragdoll.tazeplayer) then
|
|
local v = ragdoll.tazeplayer
|
|
local mode = 0
|
|
if STUNGUN.PhysEffect then
|
|
mode = STUNGUN.PhysEffect
|
|
elseif STUNGUN.ShouldRoll != nil then
|
|
mode = STUNGUN.ShouldRoll and 1 or 0
|
|
end
|
|
|
|
if mode > 0 then
|
|
local rag = ragdoll
|
|
local phys = rag:GetPhysicsObjectNum(0)
|
|
if phys:IsValid() then
|
|
if mode == 1 then
|
|
phys:AddAngleVelocity(Vector(0,math.sin(CurTime()) * 1200 * FrameTime(),0))
|
|
elseif mode == 2 then
|
|
local vel = VectorRand() * 5
|
|
for i = 1, rag:GetPhysicsObjectCount() do
|
|
if IsValid(rag:GetPhysicsObject(i-1)) then
|
|
rag:GetPhysicsObjectNum(i-1):AddVelocity(vel)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Pulls the hands together if he's cuffed
|
|
if rag.iscuffed then
|
|
local lhandbonenum = rag:LookupBone("ValveBiped.Bip01_L_Hand")
|
|
local rhandbonenum = rag:LookupBone("ValveBiped.Bip01_R_Hand")
|
|
if lhandbonenum and rhandbonenum then
|
|
local lhandnum = rag:TranslateBoneToPhysBone(lhandbonenum)
|
|
local rhandnum = rag:TranslateBoneToPhysBone(rhandbonenum)
|
|
|
|
if lhandnum and rhandnum then
|
|
local lhand = rag:GetPhysicsObjectNum(lhandnum)
|
|
local rhand = rag:GetPhysicsObjectNum(rhandnum)
|
|
|
|
if lhand and rhand then
|
|
local vel = (rhand:GetPos() - lhand:GetPos()) * 2
|
|
lhand:AddVelocity(vel)
|
|
rhand:AddVelocity(-vel)
|
|
end
|
|
end
|
|
end
|
|
elseif IsValid(rag.leashowner) then
|
|
local headpos = rag:GetPos()
|
|
local physent = phys
|
|
local bone = rag:LookupBone("ValveBiped.Bip01_Neck1")
|
|
if bone then
|
|
local matrix = rag:GetBoneMatrix(bone)
|
|
if matrix then
|
|
headpos = matrix:GetTranslation()
|
|
end
|
|
|
|
if rag:TranslateBoneToPhysBone(bone) then
|
|
physent = rag:GetPhysicsObjectNum(rag:TranslateBoneToPhysBone(bone))
|
|
end
|
|
end
|
|
|
|
local kidnapper = rag.leashowner
|
|
local TargetPoint = (kidnapper:IsPlayer() and kidnapper:GetShootPos()) or kidnapper:GetPos()
|
|
local MoveDir = (TargetPoint - headpos):GetNormal()
|
|
local Dist = rag.ropelength
|
|
|
|
local distFromTarget = headpos:Distance( TargetPoint )
|
|
if distFromTarget <= Dist + 5 then return end
|
|
|
|
local TargetPos = TargetPoint - (MoveDir * Dist)
|
|
|
|
local vel = (TargetPos - headpos) * 1
|
|
physent:AddVelocity(vel)
|
|
end
|
|
end
|
|
end
|
|
else
|
|
ragdolls[ragdoll] = nil
|
|
end
|
|
end
|
|
end)
|
|
|
|
hook.Add("EntityTakeDamage", "Tazer", function(ent, dmginfo)
|
|
if ent:IsPlayer() and IsValid(ent.tazeragdoll) and not ent.ragdolldamage then -- If we're hitting the player somehow we won't let, the ragdoll should take the damage.
|
|
dmginfo:SetDamage(0)
|
|
return
|
|
end
|
|
|
|
if STUNGUN.AllowDamage and IsValid(ent.tazeplayer) and IsValid(dmginfo:GetAttacker()) and (dmginfo:GetAttacker() != game.GetWorld()) then -- Worldspawn appears to be very eager to damage ragdolls. Don't!
|
|
if STUNGUN.IsDarkRP and dmginfo:GetAttacker():IsPlayer() and IsValid(dmginfo:GetAttacker():GetActiveWeapon()) and dmginfo:GetAttacker():GetActiveWeapon().ClassName == "stunstick" then -- Negate stunstick damage
|
|
return
|
|
end
|
|
|
|
local ply = ent.tazeplayer
|
|
-- To prevent infiniteloop and other trickery, we need to know if it was ragdamage.
|
|
ply.ragdolldamage = true
|
|
ply:TakeDamageInfo(dmginfo) -- Apply all ragdoll damage directly to the player.
|
|
ply.ragdolldamage = false
|
|
|
|
if dmginfo:GetDamage() > 0 and STUNGUN.bLogs then
|
|
local atkrname, atkr
|
|
if dmginfo:GetAttacker():IsPlayer() then
|
|
atkr = dmginfo:GetAttacker()
|
|
atkrname = bLogs.GetName(atkr)
|
|
else
|
|
atkrname = dmginfo:GetAttacker():GetClass()
|
|
end
|
|
|
|
bLogs.Log({
|
|
module = "Stungun",
|
|
log = string.format("%s took %i damage from %s while being ragdolled.", bLogs.GetName(ply), dmginfo:GetDamage(), atkrname),
|
|
involved = {ply, atkr}
|
|
})
|
|
end
|
|
|
|
if dmginfo:GetDamage() > 0 and STUNGUN.pLogs then
|
|
local data = {
|
|
["Name"] = ply:Name(),
|
|
["SteamID"] = ply:SteamID(),
|
|
["Damage"] = dmginfo:GetDamage(),
|
|
}
|
|
|
|
local atkrname
|
|
if dmginfo:GetAttacker():IsPlayer() then
|
|
atkrname = dmginfo:GetAttacker():NameID()
|
|
data["Attacker Name"] = dmginfo:GetAttacker():Name()
|
|
data["Attacker SteamID"] = dmginfo:GetAttacker():SteamID()
|
|
else
|
|
atkrname = dmginfo:GetAttacker():GetClass()
|
|
end
|
|
|
|
plogs.PlayerLog(ply, "Stungun", string.format("%s took %i damage from %s while being ragdolled.", ply:NameID(), dmginfo:GetDamage(), atkrname), data)
|
|
end
|
|
end
|
|
end)
|
|
|
|
function STUNGUN.CleanupParalyze(ply)
|
|
if IsValid(ply.tazeragdoll) then
|
|
if ply.tazeragdoll.tazesnd then
|
|
ply.tazeragdoll.tazesnd:Stop()
|
|
ply.tazeragdoll.tazesnd = nil
|
|
end
|
|
timer.Simple(0,function()
|
|
SafeRemoveEntity(ply.tazeragdoll)
|
|
end)
|
|
|
|
timer.Remove("HurtingTimer" .. ply:UserID())
|
|
timer.Remove("Unelectrolute" .. ply:UserID())
|
|
timer.Remove("tazeUngag" .. ply:UserID())
|
|
timer.Remove("StungunPlayerFreeze" .. ply:UserID())
|
|
net.Start("tazeendview")
|
|
net.Send(ply)
|
|
|
|
ply:SetNWBool("tazefrozen", false)
|
|
|
|
-- While he'll respawn and get this reset, his deadbody won't be visible so we need to reset it here.
|
|
STUNGUN.PlayerInvis(ply, false)
|
|
|
|
-- If he's respawning the immediate un-invisible won't have any effect. We need some delay.
|
|
timer.Simple(.5,function()
|
|
STUNGUN.PlayerInvis(ply, false)
|
|
end)
|
|
end
|
|
|
|
ply.tazeismuted = false
|
|
end
|
|
|
|
-- If someone removes the ragdoll, untaze the player.
|
|
hook.Add("EntityRemoved", "Tazer", function(ent)
|
|
if IsValid(ent.tazeplayer) and not ent.hasremoved then
|
|
STUNGUN.UnRagdoll(ent.tazeplayer)
|
|
end
|
|
end)
|
|
|
|
-- Some code directly respawns the player using :Spawn() without even killing him. We need to remove shit then.
|
|
hook.Add("PlayerSpawn", "Tazer", function(ply)
|
|
STUNGUN.CleanupParalyze(ply)
|
|
end)
|
|
-- If he dies, clean up.
|
|
hook.Add("DoPlayerDeath", "Tazer", function(ply, inf, atk)
|
|
STUNGUN.CleanupParalyze(ply)
|
|
end)
|
|
|
|
hook.Add("PlayerCanSeePlayersChat", "Tazer", function(text, teamOnly, listener, talker)
|
|
if (not STUNGUN.IsTTT or GetRoundState() == ROUND_ACTIVE) and talker.tazeismuted then
|
|
return false
|
|
end
|
|
end)
|
|
|
|
hook.Add("PlayerCanHearPlayersVoice", "Tazer", function(listener, talker)
|
|
if (not STUNGUN.IsTTT or GetRoundState() == ROUND_ACTIVE) and talker.tazeismuted then
|
|
return false,false
|
|
end
|
|
end)
|
|
|
|
hook.Add("CanPlayerSuicide", "Tazer", function(ply)
|
|
if not STUNGUN.ParalyzeAllowSuicide and IsValid(ply.tazeragdoll) then return false end
|
|
if not STUNGUN.MuteAllowSuicide and ply.tazeismuted then return false end
|
|
end)
|
|
|
|
hook.Add("PlayerCanPickupWeapon", "Tazer", function(ply, wep)
|
|
if IsValid(ply.tazeragdoll) then return false end
|
|
end)
|
|
|
|
hook.Add("CuffsCanHandcuff", "Tazer", function(ply, target)
|
|
if IsValid(target.tazeragdoll) then return false end
|
|
end)
|
|
|
|
gameevent.Listen("player_disconnect")
|
|
hook.Add("player_disconnect", "Tazer", function(data)
|
|
local ply = Player(data.userid)
|
|
if not IsValid(ply) then return end
|
|
|
|
-- Taken from CleanupParalyze, slightly simplified though
|
|
if IsValid(ply.tazeragdoll) then
|
|
if ply.tazeragdoll.tazesnd then
|
|
ply.tazeragdoll.tazesnd:Stop()
|
|
ply.tazeragdoll.tazesnd = nil
|
|
end
|
|
|
|
SafeRemoveEntity(ply.tazeragdoll)
|
|
|
|
timer.Remove("HurtingTimer" .. ply:UserID())
|
|
timer.Remove("Unelectrolute" .. ply:UserID())
|
|
timer.Remove("tazeUngag" .. ply:UserID())
|
|
end
|
|
end)
|
|
|
|
local function DoFallDmg(ply, vel, veldir, umph)
|
|
local dmg = math.floor(hook.Call("GetFallDamage", GAMEMODE, ply, vel))
|
|
if dmg != 0 then
|
|
local dmginfo = DamageInfo()
|
|
dmginfo:SetDamageType(DMG_FALL)
|
|
dmginfo:SetDamage(dmg)
|
|
dmginfo:SetDamageForce(vel * veldir)
|
|
dmginfo:SetDamagePosition(ply.tazeragdoll:GetPos())
|
|
dmginfo:SetAttacker(game.GetWorld())
|
|
dmginfo:SetInflictor(game.GetWorld())
|
|
|
|
ply.ragdolldamage = true
|
|
ply:TakeDamageInfo(dmginfo)
|
|
ply.ragdolldamage = false
|
|
end
|
|
end
|
|
|
|
hook.Add("Think", "TazerDoRagDmg", function()
|
|
if not STUNGUN.Falldamage then return end
|
|
|
|
for k,v in pairs(ents.FindByClass("prop_ragdoll")) do
|
|
if IsValid(v.tazeplayer) then
|
|
local phys = v:GetPhysicsObject()
|
|
local vel = phys:GetVelocity():Length()
|
|
|
|
if not v.lastfallvel then
|
|
v.lastfallvel = vel
|
|
end
|
|
|
|
if vel >= v.lastfallvel then
|
|
v.lastfallvel = vel
|
|
else
|
|
local deltavel = (v.lastfallvel - vel)
|
|
local umph = deltavel * FrameTime() -- Retardation
|
|
umph = umph * umph -- More realistic when squared
|
|
if umph > 50 then
|
|
DoFallDmg(v.tazeplayer, deltavel, phys:GetVelocity():GetNormal(), umph)
|
|
v.lastfallvel = 0
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
--[[
|
|
DarkRP specifics
|
|
]]
|
|
-- I'm not sure of the differences between these but one of them lets me put a nice message, while the other takes account in all cases. So I use both.
|
|
hook.Add("canChangeJob", "Tazer", function(ply, job)
|
|
if IsValid(ply.tazeragdoll) then
|
|
return false, "You can't change job while paralyzed!"
|
|
end
|
|
end)
|
|
hook.Add("playerCanChangeTeam", "Tazer", function(ply)
|
|
if IsValid(ply.tazeragdoll) then
|
|
return false
|
|
end
|
|
end)
|
|
|
|
--[[
|
|
TTT Specifics
|
|
]]
|
|
function SWEP:WasBought(buyer)
|
|
if not self.InfiniteAmmo then
|
|
buyer:GiveAmmo(math.max(0, self.Ammo - 1), "ammo_stungun")
|
|
end
|
|
end
|
|
|
|
--[[
|
|
bLogs
|
|
]]
|
|
local function InitbLogs()
|
|
bLogs.DefineLogger("Stungun","Extras")
|
|
|
|
STUNGUN.bLogs = true
|
|
MsgN("[STUNGUN] bLogs detected.")
|
|
end
|
|
|
|
if bLogsInit then
|
|
InitbLogs()
|
|
else
|
|
hook.Add("bLogsInit","stungun_waitforblogs",InitbLogs)
|
|
end
|