--[[ | This file was obtained through the combined efforts | of Madbluntz & Plymouth Antiquarian Society. | | Credits: lifestorm, Gregory Wayne Rossel JR., | Maloy, DrPepper10 @ RIP, Atle! | | Visit for more: https://plymouth.thetwilightzone.ru/ --]] local PLUGIN = PLUGIN PLUGIN.Actors = {} PLUGIN.StagingActors = {} local PromptSelectRemoveBag = 1 local PromptSelectUntie = 2 local PromptSelectDrag = 3 local PromptSelectRelease = 4 util.AddNetworkString("WNZipTieExit") util.AddNetworkString("WNZipTieEnter") util.AddNetworkString("WNBagExit") util.AddNetworkString("WNBagEnter") util.AddNetworkString("WNDragOrBagPrompt") util.AddNetworkString("WNDragOrBagResponse") --[[ lua_run functions for debugging things live: ]] function DebugAddHeadBag(client) net.Start("WNBagEnter") net.WriteString(client:SteamID64()) net.Broadcast() client:SetNetVar("WNBagged", true) end function DebugRemoveHeadBag(client) net.Start("WNBagExit") net.WriteString(client:SteamID64()) net.Broadcast() client:SetNetVar("WNBagged", false) end function DebugForceZiptieDraw(client) client:SetRestricted(true) client:SetNetVar("untying") net.Start("WNZipTieEnter") net.WriteString(client:SteamID64()) net.Broadcast() end function DebugForceStopZiptieDraw(client) client:SetRestricted(false) client:SetNetVar("untying") net.Start("WNZipTieExit") net.WriteString(client:SteamID64()) net.Broadcast() end --[[ lots of hooks for both zip ties and head bags: ]] function PLUGIN:PlayerUse(client, entity) if (!client:IsRestricted() and entity:IsPlayer() and entity:IsRestricted() and !entity:GetNetVar("untying")) then local id = client:SteamID64() if (self.StagingActors[id]) then return end local flags = PLUGIN:GetFlags(id, client, entity) if(!flags["bTied"] and !flags["bBagged"] and !flags["bDragging"]) then return -- we have nothing to do. someone just pressed E on some random thing end if (client.ixLastTieUse and client.ixLastTieUse + 1 > CurTime()) then return -- someone is spamming E or holding it for longer than 1 frame end client.ixLastTieUse = CurTime() self.StagingActors[id] = {} self.StagingActors[id]["client"] = client self.StagingActors[id]["target"] = entity net.Start("WNDragOrBagPrompt") net.WriteBool(flags["bBagged"]) net.WriteBool(flags["bTied"]) net.WriteBool(flags["bDragging"]) net.Send(client) end end function PLUGIN:HandleResponse(response, client, target) if (!response) then return end if (response == PromptSelectDrag) then self:EnterDrag(client, target) elseif (response == PromptSelectRelease) then self:ExitDrag(client:SteamID64(), client, target) elseif (response == PromptSelectRemoveBag) then self:RemoveBag(client, target) elseif (response == PromptSelectUntie) then self:Untie(client, target) end end net.Receive("WNDragOrBagResponse", function(len, ply) if (!ply:IsValid() or !ply:IsPlayer()) then return end local id = ply:SteamID64() if (!PLUGIN.StagingActors[id]) then return nil -- whomever sent this response has not been staged end local response = net.ReadInt(4) -- max 7 positions if (response < 1 or response > 4) then PLUGIN:ResetStagedActor(id) return nil end local client = PLUGIN.StagingActors[id]["client"] local target = PLUGIN.StagingActors[id]["target"] local flags = PLUGIN:GetFlags(id, client, target) -- validate their choice given what we know at this point (for sanity reasons or otherwise) if ( (response == PromptSelectRemoveBag and !flags["bBagged"]) -- cannot remove bag if one is not already there or (response == PromptSelectUntie and !flags["bTied"]) -- cannot initiate an untie if character is not tied, or is already being untied or (response == PromptSelectDrag and flags["bDragging"]) -- cannot initiate a drag if character is already being dragged or (response == PromptSelectRelease and !flags["bDragging"]) -- cannot release a player from a drag if they are not actively being dragged ) then PLUGIN:ResetStagedActor(id) return nil end PLUGIN:HandleResponse(response, client, target) PLUGIN:ResetStagedActor(id) end) function PLUGIN:ResetStagedActor(actorId) self.StagingActors[actorId] = nil end function PLUGIN:GetFlags(id, client, target) local flags = {} flags["bTied"] = target:IsRestricted() and !target:GetNetVar("untying") flags["bBagged"] = target:GetNetVar("WNBagged") or false if (id and client) then flags["bDragging"] = self:TargetIsFollowingPlayer(id, client, target) end return flags end function PLUGIN:PlayerLoadedCharacter(client, character, _) if (!character or !client or !client.IsRestricted) then return end local steamid = client:SteamID64() local flags = self:GetFlags(nil, nil, client) -- make sure that the state is correct for everyone if (flags.bBagged) then net.Start("WNBagEnter") net.WriteString(steamid) net.Broadcast() else net.Start("WNBagExit") net.WriteString(steamid) net.Broadcast() end if (flags.bTied) then net.Start("WNZipTieEnter") net.WriteString(steamid) net.Broadcast() else net.Start("WNZipTieExit") net.WriteString(steamid) net.Broadcast() end end function PLUGIN:TargetIsFollowingPlayer(id, player, target) return self.Actors[id] and self.Actors[id]["player"] == player and self.Actors[id]["target"] == target end function PLUGIN:RemoveBag(client, target) target:SetAction("Le sac se retire de votre tête.", 3) target:SetNetVar("unbagging", true) client:SetAction("Vous retirez le sac.", 3) client:DoStaredAction(target, function() target:SetNetVar("unbagging") net.Start("WNBagExit") net.WriteString(target:SteamID64()) net.Broadcast() target:SetNetVar("WNBagged", false) end, 5, function() if (IsValid(target)) then target:SetNetVar("unbagging") target:SetAction() end if (IsValid(client)) then client:SetAction() end end) end function PLUGIN:EnterDrag(client, target) local id = client:SteamID64() self.Actors[id] = {} self.Actors[id]["player"] = client self.Actors[id]["target"] = target client:Notify("Vous traînez maintenant la personne.") timer.Create("WNDragging"..tostring(id), 0.1, 0, function() if (IsValid(client) and IsValid(target) and client:Alive() and target:Alive() and target:IsRestricted()) then local plyVec = client:GetPos() local targetVec = target:GetPos() local plyAng = (plyVec - target:GetShootPos()):Angle() local distanceVec = targetVec:DistToSqr(plyVec) if (distanceVec < 200 * 200 and distanceVec >= 50 * 50) then target:SetEyeAngles(plyAng + Angle(-35,0,0)) target:SetVelocity((plyVec - targetVec) * 5) end else self:ExitDrag(id, client, target) end end) end function PLUGIN:ExitDrag(id, client, target) self.Actors[id] = nil client:Notify("Vous ne traînez plus la personne.") timer.Remove("WNDragging"..tostring(id)) end function PLUGIN:Untie(client, target) target:SetAction("@beingUntied", 5) target:SetNetVar("untying", true) client:SetAction("@unTying", 5) client:DoStaredAction(target, function() target:SetRestricted(false) target:SetNetVar("untying") local id = target:SteamID64() net.Start("WNZipTieExit") net.WriteString(id) net.Broadcast() target:SetWalkSpeed(target:GetWalkSpeed() * 3) if (self:TargetIsFollowingPlayer(client:SteamID64(), client, target)) then self:ExitDrag(client, target) end end, 5, function() if (IsValid(target)) then target:SetNetVar("untying") target:SetAction() end if (IsValid(client)) then client:SetAction() end end) end