Untitled
unknown
plain_text
2 years ago
34 kB
3
Indexable
AddCSLuaFile() ENT.Type = "anim" ENT.Base = "base_anim" ENT.Editable = true ENT.PrintName = "Collar" ENT.Category = "Strongest Bonds" ENT.Spawnable = true ENT.AdminSpawnable = true --Gmodstore addon support local PLAYER = FindMetaTable("Player") function PLAYER:IsCuffed() local wep = self:GetActiveWeapon() if IsValid(wep) and wep.Cuffs then return true,wep end return false end ---------------------------------- if(SERVER)then util.AddNetworkString("collar_network_player") util.AddNetworkString("sb_network_master_options") util.AddNetworkString("sb_master_options_closed") util.AddNetworkString("sb_master_options") util.AddNetworkString("sb_pet_customizations") util.AddNetworkString("sb_pet_customizations_READ") util.AddNetworkString("sb_network_master") util.AddNetworkString("sb_network_rope") util.AddNetworkString("SB_NoMoreCollar") util.AddNetworkString("SB_masterAnchor") util.AddNetworkString("SB_forcefulRemove") util.AddNetworkString("SB_notify") util.AddNetworkString("SB_Concommand") end function ENT:Initialize() if(SERVER)then self:SetModel("models/charaplyar/collar/collar.mdl") self:SetMoveType( MOVETYPE_VPHYSICS ) self:SetSolid( SOLID_VPHYSICS ) self:PhysicsInit( SOLID_VPHYSICS ) end if not(self.BoneName)then self.BoneName = "ValveBiped.Bip01_Neck1" end self.Roped = false self.Master = nil self:DrawShadow(false) if not(self.MasterOptions)then self.MasterOptions = { Rope_Length = 100, Rope_Type = "rope", Collar_Col = Color(255,255,255), Collar_Name = "Pet~" } end if not(self.Size)then self.Size = 1 end if not(self.WhiteList)then self.WhiteList = {} if(IsValid(self.Owner))then table.insert(self.WhiteList, tostring(self.Owner)) end end if(SERVER)then self:SetUseType( CONTINUOUS_USE ) end end function VectorRotate(vector, ang) local up = ang:Up() local right = ang:Right() local forward = ang:Forward() return up * vector.z + right * vector.x + forward * vector.y end function ENT:GetPositionsFromUser(ply) local pos = Vector(0,0,0) local ang = Angle(0,0,0) pos = ply:GetPos() ang = ply:GetAngles() local boneName = self.BoneName if not(boneName)then boneName = "ValveBiped.Bip01_Neck1" end if(boneName)then local boneId = (ply:LookupBone(boneName) or 0) pos, ang = ply:GetBonePosition(boneId) if(pos == ply:GetPos())then pos = ply:GetBoneMatrix(boneId):GetTranslation() ang = ply:GetBoneMatrix(boneId):GetAngles() end ang = Angle(0, ply:EyeAngles().y, 0) end pos = pos + (self.PosOffset or Vector(0,0,0)) ang = ang + (self.AngOffset or Angle(0,0,0)) local offseta = VectorRotate(self.RelPosOffset or Vector(0,0,0), ang) pos = pos + (offseta or Vector(0,0,0)) return pos, ang end function NoMoreCollar(self) if(SERVER)then if not(self.EquipingTimr)then self.EquipingTimr = 0 end if(CurTime() - self.EquipingTimr > 1)then if(IsValid(self.User))then --if not((self.User:IsCuffed() or false))then self.User.HasCollar = false self:SetPos(self.User:GetPos() + Vector(0,0,50)) --end end self.Roped = false for i, a in ipairs(player.GetAll())do net.Start("sb_network_rope") net.WriteEntity(self) net.WriteBool(false) net.Send(a) end self.User = nil for i, a in pairs(player.GetAll())do net.Start("collar_network_player") net.WriteEntity(nil) net.WriteEntity(self) net.Send(a) end if(self:GetSolid() != SOLID_VPHYSICS)then self:SetMoveType( MOVETYPE_VPHYSICS ) self:SetSolid( SOLID_VPHYSICS ) self:PhysicsInit( SOLID_VPHYSICS ) local phys = self:GetPhysicsObject() if(IsValid(phys))then phys:Wake() end end self.EquipingTimr = CurTime() end end end function ENT:EquipCollar(ply) if(SERVER)then if not(self.EquipingTimr)then self.EquipingTimr = 0 end if(CurTime() - self.EquipingTimr > 1)then ply.HasCollar = true self.User = ply for i, a in pairs(player.GetAll())do net.Start("collar_network_player") net.WriteEntity(ply) net.WriteEntity(self) net.Send(a) end self:EmitSound("collar/collar_attach.wav") self:SetMoveType( MOVETYPE_VPHYSICS ) self:SetSolid( SOLID_NONE ) self:PhysicsInit( SOLID_NONE ) net.Start("sb_pet_customizations_READ") net.WriteEntity(ply) net.WriteEntity(self) net.Send(ply) self.EquipingTimr = CurTime() end end end function ENT:Save() local data = self:Read(false) if not(data)then data = {} end if(self.User)then local pm = self.User:GetModel() data[pm] = { PosOffset = self.PosOffset, RelPosOffset = self.RelPosOffset, AngOffset = self.AngOffset, Size = self.Size, BoneName = self.BoneName, WhiteList = self.WhiteList } local dataS = util.TableToJSON( data ) file.Write("strongest_bonds_DATA.txt", dataS) end end function ENT:Read(shouldValue) if(shouldValue == nil)then shouldValue = true end local dataS = file.Read("strongest_bonds_DATA.txt", "DATA" ) if(dataS)then local data = util.JSONToTable( dataS ) if(data)then local userData = nil if(self.User)then local pm = self.User:GetModel() if(data[pm])then if(shouldValue)then self.PosOffset = data[pm].PosOffset self.RelPosOffset = data[pm].RelPosOffset self.AngOffset = data[pm].AngOffset self.Size = data[pm].Size self.BoneName = data[pm].BoneName self.WhiteList = data[pm].WhiteList end userData = data[pm] end end return data, userData end else return end end function OptionsMenu(ply) if(CLIENT)then if not(ply.InMenus)then ply.InMenus = true local self = ply.Collar if not(self)then return end local us = ents.FindInSphere(ply:GetPos(), 200) for i, a in pairs(us)do if(IsValid(a))then if(a:GetClass() == "sb_collar")then us = a break end end end local W = ScrW() * 0.5 local H = ScrH() * 0.5 local frame = vgui.Create( "DFrame" ) frame:SetPos( ScrW()/2 - W/2, ScrH()/2 - H/2 ) frame:SetSize( W, H ) frame:SetTitle( "Collar-Customization" ) frame:SetDraggable(true) frame:MakePopup() frame.OnClose = function() ply.InMenus = false self:Save() end local function CreateSliderHere(posMult, sizeMult, text, mina, maxa, default) local slidah = vgui.Create( "DNumSlider", frame ) local xSize = W * 0.25 * (sizeMult[1] or 1) local ySize = H * 0.09 * (sizeMult[2] or 1) slidah:SetPos( W * (posMult[1] or 0.5) - xSize/2, H * (posMult[2] or 0.5) - ySize/2) slidah:SetSize( xSize, ySize) slidah:SetText( text ) slidah:SetMin( mina ) slidah:SetMax( maxa ) slidah:SetDecimals( 1 ) slidah:SetValue(default or 0) return slidah end local maximaRange = 25 local _, loadData = self:Read(true) local posOffset = self.PosOffset or Vector(0,0,0) local posOffsetRel = self.RelPosOffset or Vector(0,0,0) local angleOffset = self.AngOffset or Angle(0,0,0) local size = self.Size or 1 local ourBone = self.BoneName or "ValveBiped.Bip01_Neck1" local whiteList = self.WhiteList or {} if(loadData)then posOffset = loadData.PosOffset or Vector(0,0,0) posOffsetRel = loadData.RelPosOffset or Vector(0,0,0) angleOffset = loadData.AngOffset or Angle(0,0,0) size = loadData.Size or 1 ourBone = loadData.BoneName or "ValveBiped.Bip01_Neck1" whiteList = loadData.WhiteList or {} end local xPosOffset = CreateSliderHere({0.22, 0.2}, {1.5,2}, "X - Pos Offset", -maximaRange, maximaRange, posOffset.x) local yPosOffset = CreateSliderHere({0.22, 0.3}, {1.5,2}, "Y - Pos Offset", -maximaRange, maximaRange, posOffset.y) local zPosOffset = CreateSliderHere({0.22, 0.4}, {1.5,2}, "Z - Pos Offset", -maximaRange, maximaRange, posOffset.z) local xPosOffsetRel = CreateSliderHere({0.22, 0.6}, {1.5,2}, "X - Pos Offset (Relative)", -maximaRange, maximaRange, posOffsetRel.x) local yPosOffsetRel = CreateSliderHere({0.22, 0.7}, {1.5,2}, "Y - Pos Offset (Relative)", -maximaRange, maximaRange, posOffsetRel.y) local zPosOffsetRel = CreateSliderHere({0.22, 0.8}, {1.5,2}, "Z - Pos Offset (Relative)", -maximaRange, maximaRange, posOffsetRel.z) local function AngleGetFunc(position, radius) local num = nil local x, y = input.GetCursorPos() local ourW = ScrW()/2 - W/2 local ourH = ScrH()/2 - H/2 local dif = Vector(ourW + position.x, ourH + position.y, 0) - Vector(x, y, 0) if(dif:Length() <= radius)then local norm = dif:GetNormalized() local xEnd = norm.x local yEnd = norm.y num = ((math.atan2(yEnd, xEnd) * 180/math.pi) + 180) end if(num)then if(input.IsMouseDown(MOUSE_RIGHT))then num = 0 end end return num end local function DrawAngle(data) local xPos = data.X local yPos = data.Y local num = data.Num local radius = data.Radius local col = data.Color surface.DrawCircle(xPos, yPos, radius, col or Color(255, 255, 255, 255) ) local x = math.cos(num * math.pi/180) local y = math.sin(num * math.pi/180) surface.DrawLine(xPos, yPos, xPos + x*radius, yPos + y*radius ) draw.DrawText(math.Round(num), "DermaDefault", xPos + radius + W*0.025, yPos, col, TEXT_ALIGN_CENTER ) end local anglersXPos = 0.6 local sizeSlider = vgui.Create( "DAlphaBar", frame ) local sizW = W * 0.03 local sizH = H * 0.4 local remap = 5 sizeSlider:SetPos( W * 0.8 - sizW/2, H * 0.5 - sizH/2 ) sizeSlider:SetSize( sizW, sizH) sizeSlider:SetValue( size / remap ) sizeSlider.OnChange = function( self, newvalue ) size = math.Round(newvalue * remap, 2) end local boneList = vgui.Create( "DComboBox", frame ) boneList:SetPos( W * 0.25, H * 0.9 ) boneList:SetSize( W * 0.25, H * 0.05 ) boneList:SetValue( "Bone-Parrent" ) local bones = {} for i = 1,100 do local bon = ply:GetBoneName(i) if(bon && bon != "__INVALIDBONE__")then if not(string.find(string.lower(bon), "finger"))then table.insert(bones, bon) end end end for i,a in ipairs(bones)do boneList:AddChoice(a) end boneList.OnSelect = function( self, index, value ) ourBone = value end local masterList = vgui.Create( "DListView", frame ) masterList:SetPos(W * 0.6, H * 0.85) masterList:SetSize(W * 0.3, H * 0.15) masterList:SetMultiSelect( false ) masterList:AddColumn( "Masters" ) masterList:AddColumn( "Unwanted" ) local function PopulateMasterList() for i, a in ipairs(player.GetAll())do if(IsValid(a))then if(a != self.User)then if(table.HasValue(whiteList, tostring(a)))then masterList:AddLine(tostring(a), "click-to-switch") else masterList:AddLine("click-to-switch", tostring(a)) end end end end end PopulateMasterList() masterList.OnRowSelected = function( lst, index, pnl ) local value = pnl:GetColumnText(1) if(value == "click-to-switch")then value = pnl:GetColumnText(2) end if not(table.HasValue(whiteList, value))then table.insert(whiteList, value) else table.RemoveByValue(whiteList, value) end masterList:Clear() PopulateMasterList() end frame.Think = function() if(input.IsMouseDown(MOUSE_LEFT))then local angl = AngleGetFunc({x = W * anglersXPos, y = H * 0.3}, 50) local angl2 = AngleGetFunc({x = W * anglersXPos, y = H * 0.5}, 50) local angl3 = AngleGetFunc({x = W * anglersXPos, y = H * 0.7}, 50) if(angl)then angleOffset.x = angl end if(angl2)then angleOffset.y = angl2 end if(angl3)then angleOffset.z = angl3 end end posOffset = Vector(xPosOffset:GetValue(),yPosOffset:GetValue(),zPosOffset:GetValue()) posOffsetRel = Vector(xPosOffsetRel:GetValue(),yPosOffsetRel:GetValue(),zPosOffsetRel:GetValue()) if(IsValid(us))then us.PosOffset = posOffset us.RelPosOffset = posOffsetRel us.AngOffset = angleOffset us.Size = size us.BoneName = ourBone us.WhiteList = whiteList local customizations = { pOfset = posOffset, rPOfset = posOffsetRel, angOff = angleOffset, size = size, boneName = ourBone, WhiteList = util.TableToJSON(whiteList) or ""} net.Start("sb_pet_customizations") net.WriteEntity(us) net.WriteTable(customizations) net.WriteEntity(ply) net.SendToServer() end --code from gmod itself: local mousex = math.Clamp( gui.MouseX(), 1, ScrW() - 1 ) local mousey = math.Clamp( gui.MouseY(), 1, ScrH() - 1 ) if ( frame.Dragging ) then local x = mousex - frame.Dragging[1] local y = mousey - frame.Dragging[2] -- Lock to screen bounds if screenlock is enabled if ( frame:GetScreenLock() ) then x = math.Clamp( x, 0, ScrW() - frame:GetWide() ) y = math.Clamp( y, 0, ScrH() - frame:GetTall() ) end frame:SetPos( x, y ) end local screenX, screenY = frame:LocalToScreen( 0, 0 ) if ( frame.Hovered && frame:GetDraggable() && mousey < ( screenY + 24 ) ) then frame:SetCursor( "sizeall" ) return end frame:SetCursor( "arrow" ) -- Don't allow the frame to go higher than 0 if ( frame.y < 0 ) then frame:SetPos( frame.x, 0 ) end ------------------------ end frame.Paint = function( self, w, h ) draw.RoundedBox( 0, 0, 0, w, h, Color( 0, 0, 0, 100 ) ) DrawAngle({ X = W * anglersXPos, Y = H * 0.3, Num = angleOffset.x, Radius = 50, col = Color(0,255,255,255) }) DrawAngle({ X = W * anglersXPos, Y = H * 0.5, Num = angleOffset.y, Radius = 50, col = Color(0,255,255,255) }) DrawAngle({ X = W * anglersXPos, Y = H * 0.7, Num = angleOffset.z, Radius = 50, col = Color(0,255,255,255) }) draw.DrawText("Angle-X", "DermaDefault", W * anglersXPos - W * 0.1, H * 0.3, Color(255,255,255,255), TEXT_ALIGN_CENTER ) draw.DrawText("Angle-Y", "DermaDefault", W * anglersXPos - W * 0.1, H * 0.5, Color(255,255,255,255), TEXT_ALIGN_CENTER ) draw.DrawText("Angle-Z", "DermaDefault", W * anglersXPos - W * 0.1, H * 0.7, Color(255,255,255,255), TEXT_ALIGN_CENTER ) draw.DrawText("Size", "DermaDefault", W * 0.9, H * 0.45, Color(255,255,255,255), TEXT_ALIGN_CENTER ) draw.DrawText(size, "DermaDefault", W * 0.9, H * 0.5, Color(255,255,255,255), TEXT_ALIGN_CENTER ) end end end end net.Receive("sb_network_master_options", function() local self = net.ReadEntity() local tableOpt = net.ReadTable() if(CLIENT)then self.MasterOptions = tableOpt end if(SERVER)then self.MasterOptions = tableOpt for i,a in ipairs(player.GetAll())do net.Start("sb_network_master_options") net.WriteEntity(self) net.WriteTable(tableOpt) net.Send(a) end end end) net.Receive("sb_pet_customizations_READ", function() local ply = net.ReadEntity() local self = net.ReadEntity() self:Read(true) local customizations = { pOfset = self.PosOffset or Vector(0,0,0), rPOfset = self.PosOffsetRel or Vector(0,0,0), angOff = self.AngOffset or Angle(0,0,0), size = self.Size or 1, boneName = self.BoneName or "ValveBiped.Bip01_Neck1", WhiteList = util.TableToJSON(self.WhiteList) or ""} net.Start("sb_pet_customizations") net.WriteEntity(self) net.WriteTable(customizations) net.WriteEntity(ply) net.SendToServer() end) net.Receive("sb_pet_customizations", function() local self = net.ReadEntity() local tableVars = net.ReadTable() local ply = net.ReadEntity() local pOfset = tableVars.pOfset local rPOfset = tableVars.rPOfset local angOff = tableVars.angOff local size = tableVars.size local boneName = tableVars.boneName local whiteList = util.JSONToTable(tableVars.WhiteList or "") if(IsValid(self))then if(CLIENT)then self.PosOffset = pOfset self.RelPosOffset = rPOfset self.AngOffset = angOff self.Size = size self.BoneName = boneName self.WhiteList = whiteList end if(SERVER)then self.PosOffset = pOfset self.RelPosOffset = rPOfset self.AngOffset = angOff self.Size = size self.BoneName = boneName self.WhiteList = whiteList for i,a in ipairs(player.GetAll())do if(a != ply)then net.Start("sb_pet_customizations") net.WriteEntity(self) net.WriteTable(tableVars) net.WriteEntity(ply) net.Send(a) end end end end end) function MasterOptionsMenu(ply) if(CLIENT)then local us = LocalPlayer() if !IsValid(us.Pet) then return end if !IsValid(us.Pet.Collar) then return end us = us.Pet.Collar local W = ScrW() * 0.3 local H = ScrH() * 0.4 local frame = vgui.Create( "DFrame" ) frame:SetPos( ScrW()/2 - W/2, ScrH()/2 - H/2 ) frame:SetSize( W, H ) frame:SetTitle( "Masters~Menu" ) frame:SetDraggable( true ) frame:MakePopup() frame.OnClose = function() net.Start("sb_master_options_closed") net.WriteEntity(ply) net.SendToServer() end local ropeLength = us.MasterOptions.Rope_Length or 100 local ropeWidth = us.MasterOptions.RopeWidth or 1 local ropeType = us.MasterOptions.Rope_Type or "rope" local collarColour = us.MasterOptions.Collar_Col or Color(255,255,255) local collarName = us.MasterOptions.Collar_Name or "Pet~" local bodygroup = us.MasterOptions.HasBodygroups or 0 local lengthSlid = vgui.Create( "DNumSlider", frame ) local xSize = W * 0.5 local ySize = H * 0.09 lengthSlid:SetPos( W * 0.3 - xSize/2, H * 0.16 - ySize/2) lengthSlid:SetSize( xSize, ySize) lengthSlid:SetText( "Rope Length" ) lengthSlid:SetMin( 5 ) lengthSlid:SetMax( 500 ) lengthSlid:SetDecimals(0) lengthSlid:SetValue(ropeLength) local widthSlid = vgui.Create( "DNumSlider", frame ) widthSlid:SetPos( W * 0.3 - xSize/2, H * 0.25 - ySize/2) widthSlid:SetSize( xSize, ySize) widthSlid:SetText( "Rope Width" ) widthSlid:SetMin( 0.1 ) widthSlid:SetMax( 5 ) widthSlid:SetDecimals(2) widthSlid:SetValue(ropeWidth) local ropeTypeB = vgui.Create( "DComboBox", frame ) ropeTypeB:SetPos( W * 0.1, H * 0.3 ) ropeTypeB:SetSize( W * 0.3, H * 0.075 ) ropeTypeB:SetValue( ropeType ) ropeTypeB:AddChoice("rope") ropeTypeB:AddChoice("chain") ropeTypeB:AddChoice("elastic") ropeTypeB.OnSelect = function( self, index, value ) ropeType = value end local colCol = vgui.Create("DColorMixer", frame) colCol:SetPos(W * 0.5, H * 0.3) colCol:SetSize(W * 0.4, H * 0.3) colCol:SetPalette(false) -- Show/hide the palette DEF:true colCol:SetAlphaBar(false) -- Show/hide the alpha bar DEF:true colCol:SetWangs(true) -- Show/hide the R G B A indicators DEF:true colCol:SetColor(collarColour) -- Set the default color colCol.ValueChanged = function(_, col) collarColour = Color(col.r, col.g, col.b) end local cNameEntry = vgui.Create( "DTextEntry", frame ) local sizW = W * 0.5 local sizH = H * 0.08 cNameEntry:SetPos(W * 0.5 - sizW/2, H * 0.8 - sizH/2) cNameEntry:SetSize(sizW, sizH) cNameEntry:SetValue( collarName ) cNameEntry.OnEnter = function( self ) local name = self:GetValue() collarName = name end local bodySlider = vgui.Create( "DNumSlider", frame ) bodySlider:SetPos( W * 0.3 - xSize/2, H * 0.5 - ySize/2) bodySlider:SetSize( xSize, ySize) bodySlider:SetText( "BodyGroup" ) bodySlider:SetMin( 0 ) bodySlider:SetMax( 3 ) bodySlider:SetDecimals(0) bodySlider:SetValue(bodygroup) frame.Think = function() ropeLength = lengthSlid:GetValue() ropeWidth = widthSlid:GetValue() bodygroup = math.Round(bodySlider:GetValue()) if(IsValid(us))then local tableOptions = { Rope_Length = ropeLength, RopeWidth = ropeWidth, Rope_Type = ropeType, Collar_Col = collarColour, Collar_Name = collarName, HasBodygroups = bodygroup } net.Start("sb_network_master_options") net.WriteEntity(us) net.WriteTable(tableOptions) net.SendToServer() end end frame.Paint = function( self, w, h ) draw.RoundedBox( 0, 0, 0, w, h, Color( 0, 0, 0, 200 ) ) end end end function ENT:MaterialFromType() local typee = self.MasterOptions.Rope_Type or "rope" if(typee == "rope")then return "cable/rope" end if(typee == "chain")then return "cable/custom_chains2" end if(typee == "elastic")then return "cable/cable2" end return "cable/rope" end function ENT:RenderRope() if(SERVER)then local function removeOurStuff() if(IsValid(self.TheRope))then self.TheRope:Remove() end if(IsValid(self.TheAnchor))then self.TheAnchor:Remove() end self.TheRope = nil self.TheAnchor = nil end if(IsValid(self.User) && IsValid(self.Master))then if(self.Roped)then if not(self.TheRope)then if not(self.TheAnchor)then self.TheAnchor = constraint.CreateStaticAnchorPoint(self.Master:GetPos()) end self.TheRope = constraint.CreateKeyframeRope(self:GetPos(), 4, self:MaterialFromType(), nil, self, Vector(0,self.Size * 5,0), 0, self.TheAnchor, Vector(0,0,0), 0, {Collide = 1}) self:EmitSound("collar/leash_attach.wav") end if(IsValid(self.TheRope))then self.TheRope:SetMaterial(self:MaterialFromType()) self.TheRope:SetKeyValue("Rope Material", self:MaterialFromType()) self.TheRope:SetKeyValue("Length", self.MasterOptions.Rope_Length) self.TheRope:SetKeyValue("Slack", 25) self.TheRope:SetKeyValue("Width", self.MasterOptions.RopeWidth or 1) self.TheRope:SetKeyValue("Subdivision", 5) end if(IsValid(self.TheAnchor))then if not(self.TheAnchor.WorldPositioning)then local plyBone = (self.Master:LookupBone("ValveBiped.Bip01_R_Hand") or self.Master:LookupBone("ValveBiped.Bip01_R_Wrist") or self.Master:LookupBone("ValveBiped.Anim_Attachment_RH")) or 0 local pos = self.Master:GetBonePosition(plyBone) if(pos == self.Master:GetPos())then pos = self.Master:GetBoneMatrix(plyBone):GetTranslation() end self.TheAnchor:SetPos(pos) else self.TheAnchor:SetPos(self.TheAnchor.WorldPositioning) end end else removeOurStuff() end else removeOurStuff() end end end function ColorMath(col, col1, operation) if not(operation)then return col end if(operation == "minus")then return (Color(col.r - col1.r, col.g - col1.g, col.b - col1.b)) end if(operation == "plus")then return (Color(col.r + col1.r, col.g + col1.g, col.b + col1.b)) end if(operation == "multiply")then return (Color(col.r * col1.r, col.g * col1.g, col.b * col1.b)) end if(operation == "divide")then return (Color(col.r / col1.r, col.g / col1.g, col.b / col1.b)) end end function DoConcommand(conc, ply, args) if(CLIENT)then if(conc == "SB_Master_GetPets")then for i,a in ipairs(player.GetAll())do if(IsValid(a))then if(a != ply)then if(a.Collar)then if(IsValid(a.Collar))then if(a.Collar.Master == ply)then print(a:Nick()) end end end end end end end if(conc == "SB_ForceRemoveMaster")then if(IsValid(ply))then if(ply.Collar)then if(IsValid(ply.Collar))then if not(ply.Collar.Roped)then net.Start("SB_forcefulRemove") net.WriteEntity(ply.Collar) net.SendToServer() end end end end end if(conc == "SB_Collar_MasterAnchor")then if(IsValid(ply))then net.Start("SB_masterAnchor") net.WriteEntity(ply) net.SendToServer() end end if(conc == "SB_Collar_Options")then OptionsMenu(ply) end if(conc == "SB_Collar_MasterOptions")then MasterOptionsMenu(ply) end if(conc == "SB_Collar_Remove")then local us = ply.Collar if(IsValid(us))then net.Start("SB_NoMoreCollar") net.WriteEntity(us) net.SendToServer() end end else net.Start("SB_Concommand") net.WriteString(conc) net.WriteEntity(ply) net.Send(ply) end end net.Receive("SB_Concommand", function() local conc = net.ReadString() local ply = net.ReadEntity() print(ply) DoConcommand(conc, ply) end) concommand.Add("SB_Master_GetPets", function(ply) DoConcommand("SB_Master_GetPets", ply) end) concommand.Add("SB_ForceRemoveMaster", function(ply) DoConcommand("SB_ForceRemoveMaster", ply) end) net.Receive("SB_forcefulRemove", function() local self = net.ReadEntity() self.Master = nil for i, a in ipairs(player.GetAll())do net.Start("sb_network_master") net.WriteEntity(self) net.WriteEntity(nil) net.Send(a) end end) concommand.Add("SB_Collar_MasterAnchor", function( ply, cmd, nyah, args ) DoConcommand("SB_Collar_MasterAnchor", ply) end) net.Receive("SB_masterAnchor", function() local ply = net.ReadEntity() local pet = ply.Pet if(IsValid(pet))then local self = pet.Collar if(IsValid(self))then if(self.TheAnchor)then if not(self.TheAnchor.WorldPositioning)then if(ply:GetEyeTrace().Entity:IsWorld())then local thePos = ply:GetEyeTrace().HitPos if((ply:GetPos() - thePos):Length() < 200)then self.TheAnchor.WorldPositioning = thePos end end end end end end end) concommand.Add("SB_Collar_MasterOptions", function( ply, cmd, nyah, args ) DoConcommand("SB_Collar_MasterOptions", ply) end) concommand.Add("SB_Collar_Options", function( ply, cmd, nyah, args ) DoConcommand("SB_Collar_Options", ply) end) concommand.Add("SB_Collar_Remove", function( ply, cmd, nyah, args ) DoConcommand("SB_Collar_Remove", ply) end) net.Receive("SB_NoMoreCollar", function() local us = net.ReadEntity() if(IsValid(us))then NoMoreCollar(us) end end) net.Receive("SB_notify", function() local stringi = net.ReadString() notification.AddLegacy(stringi, NOTIFY_HINT, 2) end) function ENT:Think() if(IsValid(self.User) && self.User:Alive())then if(CLIENT)then local pos, ang = self:GetPositionsFromUser(self.User) self:SetPos(pos) self:SetAngles(ang) end if not(self.RustleSound)then self.RustleSound = CurTime() end if not(self.RustleDelay)then self.RustleDelay = math.random(1,3) end if(CurTime() - self.RustleSound > self.RustleDelay)then if(self.User:GetVelocity():Length() > 50)then self:EmitSound("collar/chain/chains_move.wav", 70, math.random(90,110)) self.RustleSound = CurTime() self.RustleDelay = math.random(1,3) end end self:SetColor(ColorMath(self.MasterOptions.Collar_Col, Color(255/2,255/2,255/2), "plus")) self.User.Collar = self local bNum = self.MasterOptions.HasBodygroups or 0 if(bNum == 0)then self:SetBodygroup(1, 0) self:SetBodygroup(2, 0) elseif(bNum == 1)then self:SetBodygroup(1, 0) self:SetBodygroup(2, 1) elseif(bNum == 2)then self:SetBodygroup(1, 1) self:SetBodygroup(2, 0) else self:SetBodygroup(1, 1) self:SetBodygroup(2, 1) end if not(self.PetUseTimr)then self.PetUseTimr = 0 end if(IsValid(self.Master))then self.Master.Pet = self.User if(SERVER)then if not(self.Master:Alive())then self.Roped = false for i, a in ipairs(player.GetAll())do net.Start("sb_network_rope") net.WriteEntity(self) net.WriteBool(false) net.Send(a) end end if(self.Roped)then --leash code here local leashPosition = self.Master:GetPos() if(self.TheAnchor)then if(self.TheAnchor.WorldPositioning)then leashPosition = self.TheAnchor.WorldPositioning end end local dif = leashPosition - self.User:GetPos() local difNum = dif:Length() local ropeLength = self.MasterOptions.Rope_Length if(difNum > ropeLength)then local dir = (ropeLength - difNum) local velo = dif:GetNormalized() * -dir self.User:SetVelocity(velo) if not(self.RopeSqueek)then self.RopeSqueek = CurTime() end if(CurTime() - self.RopeSqueek > 1)then self:EmitSound("collar/rope_squeek.wav", 60, math.random(80,120)) self.RopeSqueek = CurTime() end if not(self.TheAnchor && self.TheAnchor.WorldPositioning)then self.Master:SetVelocity(velo / -5) end end end end end else NoMoreCollar(self) end self:SetModelScale(self.Size or 1) self:RenderRope() if(SERVER)then for i, ply in ipairs(player.GetAll())do if(IsValid(self.Master))then if(ply == self.Master)then if not(table.HasValue(self.WhiteList, tostring(ply)))then --no longer allowed self.Master = nil for i, a in ipairs(player.GetAll())do net.Start("sb_network_master") net.WriteEntity(self) net.WriteEntity(nil) net.Send(a) end end end end if not(ply.MasterUsageDelay)then ply.MasterUsageDelay = CurTime() end if(CurTime() - ply.MasterUsageDelay > 0.5)then if(ply:KeyDown(IN_USE))then local looking = ply:GetEyeTrace().Entity if(IsValid(looking))then if(looking:IsPlayer())then if(looking == self.User)then local diff = looking:GetPos() - ply:GetPos() if(diff:Length() < 700)then if(IsValid(self.Master))then if(self.Master == ply)then self:DoMasterUsage(ply, looking) end else if(table.HasValue(self.WhiteList, tostring(ply)))then --is even a master~? self.Master = ply for i, a in ipairs(player.GetAll())do net.Start("sb_network_master") net.WriteEntity(self) net.WriteEntity(ply) net.Send(a) end net.Start("SB_notify") net.WriteString( "You became Master of " .. looking:Nick() .. "~") net.Send(ply) net.Start("SB_notify") net.WriteString(ply:Nick() .. " is now your Master~") net.Send(looking) sound.Play("garrysmod/content_downloaded.wav", ply:GetPos(), 75, 100, 1) end end end end end end ply.MasterUsageDelay = CurTime() end end end end self:NextThink( CurTime() ) -- Set the next think to run as soon as possible, i.e. the next frame. return true -- Apply NextThink call end function ENT:DoMasterUsage(ply, otherPly) if(ply:KeyDown(IN_WALK))then self.Master = nil for i, a in ipairs(player.GetAll())do net.Start("sb_network_master") net.WriteEntity(self) net.WriteEntity(nil) net.Send(a) end net.Start("SB_notify") net.WriteString( "You are no longer Master of " .. self.User:Nick() .. ".") net.Send(ply) net.Start("SB_notify") net.WriteString(ply:Nick() .. " is no longer your Master.") net.Send(self.User) sound.Play("garrysmod/content_downloaded.wav", ply:GetPos(), 75, 70, 1) else if(self.Roped)then self:EmitSound("collar/leash_attach.wav", 75, 70) self.Roped = false for i, a in ipairs(player.GetAll())do net.Start("sb_network_rope") net.WriteEntity(self) net.WriteBool(false) net.Send(a) end else self.Roped = true for i, a in ipairs(player.GetAll())do net.Start("sb_network_rope") net.WriteEntity(self) net.WriteBool(true) net.Send(a) end end end end net.Receive("collar_network_player", function() local ply = net.ReadEntity() local self = net.ReadEntity() self.User = ply end) net.Receive("sb_master_options_closed", function() local ply = net.ReadEntity() ply.InMenus = false end) net.Receive("sb_master_options", function() local self = net.ReadEntity() local master = net.ReadEntity() MasterOptionsMenu(self) end) net.Receive("sb_network_master", function() local self = net.ReadEntity() local master = net.ReadEntity() self.Master = master end) net.Receive("sb_network_rope", function() local self = net.ReadEntity() local rope = net.ReadBool() self.Roped = rope end) function ENT:Use(ply) if(IsValid(ply))then if not(IsValid(self.User))then if not(ply.HasCollar)then self:EquipCollar(ply) end end end end function ENT:OnRemove() if(IsValid(self.User))then self.User.HasCollar = false end end function ENT:Draw() if((not(LocalPlayer() == self.User && LocalPlayer() == LocalPlayer():GetViewEntity())) || LocalPlayer():ShouldDrawLocalPlayer())then self:DrawModel() end end
Editor is loading...