Untitled
unknown
plain_text
2 years ago
34 kB
8
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...