Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --Declearations
- local studio = game.JobId == ""
- local PermissionTracking = {}
- local resetgarageinfo = {}
- local garageinfo = {}
- local collisionInformation = {}
- local Players = {}
- local soundLibrary = game.ServerStorage.GameSounds
- game.StarterGui.ResetPlayerGuiOnSpawn = false
- local RCSIC = game.Players.CSConnections
- local market = game:GetService("MarketplaceService")
- local http = game:GetService("HttpService")
- local datastore = game:GetService("DataStoreService")
- local compression = require(game.ServerScriptService.CompressionService)
- local gmod = require(workspace.GlobalModule)
- local IdentifyClass = gmod.identifyClass1
- local IdentifyClass2 = gmod.identifyClass2
- local placeIds = {
- ["Public Server"] = gmod.placeIds.public;
- ["Test Server"] = gmod.placeIds.test;
- ["Player Hub"] = gmod.placeIds.hub;
- ["Exclusive Server"] = gmod.placeIds.pro;
- }
- local garageconnections = { g1 = {}; g2 = {}; g3 = {}; g4 = {}; g5 = {}; g6 = {}; g7 = {}; g8 = {} }
- local PartLimits = gmod.PartSettings
- local DurabilityMultiplier = gmod.DurabilityMultiplier
- local Names = gmod.PartNames
- local serverName
- local servertype
- local user
- local pass
- local PartInfo = gmod.PartInfo
- _G.rotateModel = function(model,center,rotation)
- local parts ={}
- local function scan(parent)
- for _,obj in pairs(parent:GetChildren()) do
- if (obj:IsA("BasePart")) then
- table.insert(parts,obj)
- end
- scan(obj)
- end
- end
- scan(model)
- for _,part in pairs(parts) do
- part.CFrame = (center*rotation*(center:inverse()*part.CFrame))
- end
- end
- _G.Iterate = function(func,start)
- for _,w in pairs(start:GetChildren()) do
- func(w)
- _G.Iterate(func,w)
- end
- end
- _G.Iterate(function(w)
- if w:IsA("BasePart") then
- w.Locked = true
- end
- end,
- workspace.Map) --lock all instances
- --if not studio then serverName = http:JSONDecode(http:GetAsync("http://api.robloxapi.com/Assets/AssetInfo?AssetId="..game.PlaceId)).Name end
- serverName = "Public Server"
- ----------------------------
- -- Private Server Handler --
- ----------------------------
- print([[Running "Private Server Handler"]])
- print("Successful Run:",pcall(function()
- for i,v in pairs(placeIds) do
- if v == game.PlaceId then
- servertype = i
- end
- end
- if not servertype then
- servertype = "Private Server"
- local scope = game:GetService("DataStoreService"):GetDataStore("HUB","PRIVATE_SERVER_METADATA")
- local info = http:JSONDecode(scope:GetAsync(serverName))
- user = serverName
- pass = info.password
- local function update()
- scope:UpdateAsync(serverName,function(oldval)
- oldval = http:JSONDecode(oldval)
- oldval.playerCount = game.Players.NumPlayers
- if game.Players.NumPlayers == 0 then
- oldval.active = false
- else
- oldval.active = true
- end
- return http:JSONEncode(oldval)
- end)
- end
- game.Players.PlayerAdded:connect(update)
- game.Players.PlayerRemoving:connect(update)
- game.ServerScriptService.SaveManager.ServerName.Value = serverName
- end
- end))
- ----------------------------
- --------------------------------
- -- Physical Environment Setup --
- --------------------------------
- print([[Running "Physical Environment Setup"]])
- for i = 1,8 do
- local garage = workspace.Map.Garages.Garages["Garage"..i]
- local size = garage:GetExtentsSize()
- local pos = garage:GetModelCFrame().p
- gmod:refreshSampleParts(i)
- collisionInformation["Garage"..i] = {
- xs = pos.x - size.x/2;
- xf = pos.x + size.x/2;
- ys = pos.y - size.y/2;
- yf = pos.y + size.y/2;
- zs = pos.z - size.z/2;
- zf = pos.z + size.z/2;
- }
- garageinfo["Garage"..i] = {
- size = size;
- pos = garage:GetModelCFrame();
- }
- resetgarageinfo["Garage"..i] = {
- doorinfo = {
- size = garage.Door.Size;
- cframe = garage.Door.CFrame;
- transparency = 0;
- };
- ceilinginfo = {
- cframe = garage.Top.CFrame;
- transparency = 0;
- };
- motordirectory = garage.Motors
- }
- garage.Top.ChildAdded:connect(function(child)
- if child:IsA("Sound") then
- child.TimePosition = .2
- end
- end)
- local floorLight = gmod.new("SurfaceLight",{
- Name = "FloorLight";
- Brightness = 0;
- Face = "Top";
- Range = 0;
- Shadows = true;
- Parent = garage.Bottom
- })
- game.Lighting.Changed:connect(function(prop)
- if prop ~= "TimeOfDay" then return end
- local minutes = game.Lighting:GetMinutesAfterMidnight()
- local exitPhaseStart, exitPhaseEnd = 360, 420
- local enterPhaseStart, enterPhaseEnd = 1080, 1140
- if minutes >= enterPhaseStart or minutes <= exitPhaseEnd then
- floorLight.Enabled = true
- if minutes >= enterPhaseEnd or minutes <= exitPhaseStart then
- floorLight.Brightness = .5
- floorLight.Range = 60
- end
- else
- floorLight.Enabled = false
- end
- if minutes >= enterPhaseStart and minutes <= enterPhaseEnd then
- local scale = (minutes - enterPhaseStart)/(enterPhaseEnd - enterPhaseStart)
- floorLight.Brightness = scale * .5
- floorLight.Range = scale * 60
- elseif minutes >= exitPhaseStart and minutes <= exitPhaseEnd then
- local scale = 1 - (minutes - exitPhaseStart)/(exitPhaseEnd - exitPhaseStart)
- floorLight.Brightness = scale * .5
- floorLight.Range = scale * 60
- end
- end)
- end
- setmetatable(resetgarageinfo,{
- __call = function(igi,number)
- local info = igi["Garage"..number]
- local garage = workspace.Map.Garages.Garages["Garage"..number]
- garage.Door.Size = info.doorinfo.size
- garage.Door.CFrame = info.doorinfo.cframe
- garage.Door.Transparency = info.doorinfo.transparency
- garage.Top.CFrame = info.ceilinginfo.cframe
- garage.Top.Transparency = info.ceilinginfo.transparency
- for _,w in pairs(info.motordirectory:GetChildren()) do
- w.C0 = CFrame.new(w.C0.p)
- end
- end
- })
- game.Lighting:SetMinutesAfterMidnight(os.time()%1440)
- spawn(function() while wait(.25) do game.Lighting:SetMinutesAfterMidnight(game.Lighting:GetMinutesAfterMidnight() + .25) end end)
- spawn(function() while wait(1) do game.ReplicatedStorage.PhysicalData.ServerUpTime.Value = game.ReplicatedStorage.PhysicalData.ServerUpTime.Value + 1 end end)
- local MotorFunctions = {}
- spawn(function()
- for _,w in pairs(workspace.Map.Garages.Garages:GetChildren()) do
- local GarageMotorFunctions = {}
- w.Back:BreakJoints()
- local weld = Instance.new("Motor",w.Motors)
- weld.Name = "Back"
- weld.Part0 = w.Back
- weld.Part1 = w.Bottom
- weld.C1 = CFrame.fromEulerAnglesXYZ(0,0,0) * CFrame.new(0,0,-w.Bottom.Size.Z/2 - w.Back.Size.Z/2)
- weld.C0 = CFrame.new(0,-w.Back.Size.Y/2 + w.Bottom.Size.Y/2,0)
- w.Back.Anchored = false
- GarageMotorFunctions[weld.Name] = { motor = weld , invoked = 0}
- MotorFunctions[w.Name] = GarageMotorFunctions
- local part = w.Back:Clone()
- part.Parent = w
- part:ClearAllChildren()
- part.Name = "BackwardsCollision"
- part.Transparency = 1
- part.Anchored = true
- part.CFrame = weld.C0:toWorldSpace(CFrame.new())
- w.Back.Changed:connect(function() weld.C0:toWorldSpace(CFrame.new()) end)
- end
- end)
- --------------------------------
- -----------------------------
- -- Miscellaneous Functions --
- -----------------------------
- print([[Running "Miscellaneous Functions"]])
- function GetParts(plr,teamfilter,ingarage,class)
- local PartsCollected = {}
- for _,w in pairs(workspace:GetChildren()) do
- if w:IsA("BasePart") then
- local incorrect = false
- if teamfilter then if tonumber(string.sub(w.Name,1,1)) ~= teamfilter then incorrect = true end end
- if ingarage then
- local cInfo = collisionInformation["Garage"..ingarage]
- local pos = w.Position
- if pos.x > cInfo.xs and pos.x < cInfo.xf and pos.y > cInfo.ys and pos.y < cInfo.yf and pos.z > cInfo.zs and pos.z < cInfo.zf then else incorrect = true end
- end
- if class then
- if not IdentifyClass[class](w) then incorrect = true end
- end
- if not incorrect then table.insert(PartsCollected,w) end
- end
- end
- return PartsCollected
- end
- function returnLocationIGUP(pos,critical)
- local garage,numDone = false,0
- for i = 1,8 do
- spawn(function()
- local cInfo = collisionInformation["Garage"..i]
- local direct = workspace.Map.Garages.Garages["Garage"..i]
- if
- pos.x > cInfo.xs + (critical and direct.L.Size.X or 3) and
- pos.x < cInfo.xf - (critical and direct.R.Size.X or 3) and
- pos.y > cInfo.ys + (critical and direct.Bottom.Size.Y or 3) and
- pos.y < cInfo.yf - (critical and direct.Top.Size.Y or 3) and
- pos.z > cInfo.zs + (critical and direct.Door.Size.Z or 3) and
- pos.z < cInfo.zf - (critical and direct.Back.Size.Z + 6 or 3) then
- garage = i
- end
- numDone = numDone + 1
- end)
- end
- repeat wait() until numDone == 8
- return garage
- end
- function getUsernameFromId(ID)
- for _,v in pairs(game:GetService("InsertService"):GetUserSets(ID)) do
- if v.Name == "My Models" then return v.CreatorName end
- end
- end
- function clearConnections(tabl)
- for _,w in pairs(tabl) do
- w:disconnect()
- end
- end
- SpecialFunctions = {
- RequestTeleport = function(sent,plr,reciever)
- local tele = game.ReplicatedStorage.Miscellaneous.Teleport:Clone()
- tele.MouseButton1Click:connect(function()
- sent:remove()
- if reciever.Character then reciever.Character:MoveTo(plr.Character:GetModelCFrame().p) RCSIC.EventFired:FireClient(reciever,"Summoned") end
- end)
- tele.Parent = sent.ButtonSpace
- spawn(function()
- wait(10)
- if sent and sent.Parent then sent:remove() end
- end)
- end
- }
- -----------------------------
- -------------------------------------------------------
- -- Remote Client-Server Interaction Connection Setup --
- -------------------------------------------------------
- print([[Running "Remote Client-Server Interaction Connection Setup"]])
- function IsInGarage(sender,Gnum,plr)
- if not Gnum then return end
- if game.ReplicatedStorage.GarageDetection["Garage"..Gnum]:findFirstChild(plr and plr.Name or sender.Name) then return true else return false end
- end
- function FireMotor(plr,motor,direction,garage)
- local mt = MotorFunctions["Garage"..(garage or plr.PlayerGui.Team.Value)][motor]
- mt.invoked = mt.invoked + 1
- local __invoked = mt.invoked
- local s = Instance.new("Sound",mt.motor.Part0)
- s.SoundId = direction and "rbxassetid://142643714" or "rbxassetid://142643742"
- s.Pitch = 1
- s.Volume = .2
- s:Play()
- local opt = 0
- local algorithm = math.abs((direction and (mt.motor.Part0.Rotation.X - 90) or - mt.motor.Part0.Rotation.X))
- for i = 1,algorithm do
- if mt.invoked ~= __invoked then break end
- opt = opt + 1
- mt.motor.C0 = mt.motor.C0 * CFrame.fromEulerAnglesXYZ(math.rad(direction and 1 or -1),0,0)
- wait()
- end
- if opt == math.floor(algorithm) then mt.motor.C0 = CFrame.new(mt.motor.C0.x,mt.motor.C0.y,mt.motor.C0.z) * CFrame.Angles(math.rad(direction and 90 or 0),0,0) else s:Stop() end
- if opt < 80 then s:Stop() end
- s:remove()
- end
- function GetGarageParts()
- local parts = game.ServerStorage.Parts.Parts:Clone()
- parts.Parent = game.ReplicatedStorage
- return parts
- end
- function SetPermissions(sender,player,tableofpermissions)
- PermissionTracking[sender.PlayerGui.Team.Value][player.PlayerGui.Team.Value] = tableofpermissions
- game.Players.CSConnections.BlockPlayer:FireClient(player,sender.PlayerGui.Team.Value,tableofpermissions.blockplayer and true or false)
- if not tableofpermissions.enableforcefield and game.ReplicatedStorage.GarageDetection["Garage"..sender.PlayerGui.Team.Value]:findFirstChild(player.Name) then
- if player.Character:findFirstChild("ForceField") then player.Character.ForceField:remove() end
- end
- if not tableofpermissions.enablebuildingtools and game.ReplicatedStorage.GarageDetection["Garage"..sender.PlayerGui.Team.Value]:findFirstChild(player.Name) then
- RCSIC.SafteyPlayer:FireClient(player,true)
- end
- if tableofpermissions.blockplayer then
- local gnum = sender.PlayerGui.Team.Value
- if game.ReplicatedStorage.GarageDetection["Garage"..gnum]:findFirstChild(player.Name) then
- player:LoadCharacter()
- end
- garageconnections["g"..gnum][player.Name] = game.ReplicatedStorage.GarageDetection["Garage"..gnum].ChildAdded:connect(function(child)
- if child.Value == player then player:LoadCharacter() end
- end)
- else
- local gnum = sender.PlayerGui.Team.Value
- if garageconnections["g"..gnum][player.Name] then garageconnections["g"..gnum][player.Name]:disconnect() garageconnections["g"..gnum][player.Name] = nil end
- end
- end
- function GetPermissions(sender,player,reverse)
- return reverse and PermissionTracking[player.PlayerGui.Team.Value][sender.PlayerGui.Team.Value] or PermissionTracking[sender.PlayerGui.Team.Value][player.PlayerGui.Team.Value]
- end
- function LoadCharacter(sender,requested)
- if not requested then sender:LoadCharacter() else requested:LoadCharacter() end
- end
- function GetPlayerFromGarage(sender,gnum)
- for _,w in pairs(game.Players:GetPlayers()) do
- if w.PlayerGui.Team.Value == tonumber(gnum) then return w end
- end
- end
- function GetGarageFromPlayer(sender,search)
- if search then
- local find = game.ReplicatedStorage.GarageDetection:findFirstChild(search.Name,true)
- if find then return string.sub(find.Parent.Name,string.len("Garage") + 1) end
- else
- local find = game.ReplicatedStorage.GarageDetection:findFirstChild(sender.Name,true)
- if find then return string.sub(find.Parent.Name,string.len("Garage") + 1) end
- end
- end
- function SendNotification(sender,reciever,desc,special)
- local note = game.ServerStorage.Notification:Clone()
- note.Parent = reciever
- note.Description.Text = desc
- note.SenderImgUrl.Image = "http://www.roblox.com/Thumbs/Avatar.ashx?x=100&y=100&format=png&username="..sender.Name
- note.Exit.MouseButton1Click:connect(function()
- note:remove()
- end)
- RCSIC.SendNotification:FireClient(reciever,note)
- if special then SpecialFunctions[special](note,sender,reciever) end
- end
- function HasPass(plr,id,player)
- return game:GetService("GamePassService"):PlayerHasPass(player or plr, id)
- end
- function PromptOrderInfo(plr,assetId,parent,assetType,tax)
- local gui = game.ServerStorage.TransactionManager:Clone()
- local info = market:GetProductInfo(assetId,assetType == "DevProduct" and "Product" or "Asset")
- gui.ProductInfo.Item.Value.Text = info.Name
- gui.ProductInfo.User.Value.Text = plr.userId
- gui.ProductInfo.Asset.Value.Text = assetType
- gui.ProductInfo.SubTotal.Value.Text = "R$"..(info.PriceInRobux ~= "null" and info.PriceInRobux or "0")..".00"
- gui.ProductInfo.Tax.Value.Text = "R$"..(tax and "2" or "0")..".00"
- gui.ProductInfo.Total.Value.Text = "R$"..((info.PriceInRobux ~= "null" and info.PriceInRobux or 0) + (tax and 2 or 0))..".00"
- local sizeC = gui.Size
- local posC = gui.Position
- gui.Size = UDim2.new(sizeC.X.Scale,0,0,0)
- gui.Position = UDim2.new(posC.X.Scale,0,posC.Y.Scale + sizeC.Y.Scale/2,0)
- gui.Parent = parent or plr.PlayerGui.Interface
- gui:TweenSizeAndPosition(sizeC,posC,"Out","Linear",.2,true)
- return gui
- end
- function PromptSystemWarning(plr,msg)
- local gui = game.ServerStorage.SystemWarning:Clone()
- gui.MsgFrame.Msg.Text = msg
- local fr = gui.MsgFrame
- local bc = fr.Back
- local msgBox = fr.Msg
- local title = fr.Title
- bc.MouseEnter:connect(function() bc.ImageColor3 = Color3.new(.25,.25,.25) end)
- bc.MouseLeave:connect(function() bc.ImageColor3 = Color3.new( 0, 0, 0) end)
- bc.MouseButton1Down:connect(function() bc.ImageColor3 = Color3.new(.25,.25,.25) end)
- bc.MouseButton1Up:connect (function() bc.ImageColor3 = Color3.new( 0, 0, 0) end)
- gui.BackgroundTransparency = 1
- fr.BackgroundTransparency = 1
- bc.ImageTransparency = 1
- msgBox.TextTransparency = 1
- title.TextTransparency = 1
- title.TextStrokeTransparency = 1
- gui.Parent = plr.PlayerGui.Interface
- for i = 1,0,-.1 do
- gui.BackgroundTransparency = .25 + .75 * i
- fr.BackgroundTransparency = i
- bc.ImageTransparency = i
- msgBox.TextTransparency = i
- title.TextTransparency = i
- title.TextStrokeTransparency = i
- wait()
- end
- local removemsg
- removemsg = bc.MouseButton1Click:connect(function()
- removemsg:disconnect()
- for i = 0,1,.1 do
- gui.BackgroundTransparency = .25 + .75 * i
- fr.BackgroundTransparency = i
- bc.ImageTransparency = i
- msgBox.TextTransparency = i
- title.TextTransparency = i
- title.TextStrokeTransparency = i
- wait()
- end
- gui:remove()
- end)
- end
- function SelectModel(plr,parts,color)
- local bound = Instance.new("Model",plr.PlayerGui)
- for _,w in pairs(parts) do
- local sb = Instance.new("SelectionBox",bound)
- sb.Color = color
- sb.Adornee = w
- end
- return bound
- end
- function IdentifyPart(plr,part)
- for _,w in pairs(IdentifyClass2) do
- local n = w(part)
- if n then return n end
- end
- return "P"
- end
- function PerformCSMethod(plr,method,...)
- return require(game.ServerScriptService.CompressionService)[method](require(game.ServerScriptService.CompressionService),...)
- end
- function GetClosestPlayer(plr,vector)
- local closestplayer,mag = nil,math.huge
- if plr.Character then
- for _,w in pairs(game.Players:GetPlayers()) do
- if w ~= plr then
- if w.Character then
- local distance = (w.Character:GetModelCFrame().p - (vector and vector or plr.Character:GetModelCFrame().p)).magnitude
- if distance < mag then closestplayer = w; mag = distance end
- end
- end
- end
- end
- return closestplayer,mag
- end
- function GetClosestEFP(plr,vector)
- local closestefp,mag = nil,math.huge
- if plr.Character then
- for _,w in pairs(workspace:GetChildren()) do
- if string.sub(w.Name,1,1) ~= tostring(plr.PlayerGui.Team.Value) and string.sub(w.Name,2,2) == "F" and w:IsA("BasePart") then
- local distance = (w.Position - (vector and vector or plr.Character:GetModelCFrame().p)).magnitude
- if distance < mag then closestefp = w; mag = distance end
- end
- end
- end
- return closestefp,mag
- end
- function CreateReticle(plr,parts,parent)
- if type(parts) == "userdata" then
- local reticle = game.ServerStorage.Reticle:Clone()
- reticle.Parent = parent
- reticle.Adornee = parts
- spawn(function()
- while reticle and reticle.Parent do
- reticle.Overlay.ROverlay2.Rotation = reticle.Overlay.ROverlay2.Rotation + 5
- wait()
- end
- end)
- return reticle
- elseif type(parts) == "table" then
- local reticles = {}
- for _,w in pairs(parts) do
- spawn(function()
- local reticle = game.ServerStorage.Reticle:Clone()
- reticle.Parent = parent
- reticle.Adornee = w
- table.insert(reticles,reticle)
- while reticle and reticle.Parent do
- reticle.Overlay.ROverlay2.Rotation = reticle.Overlay.ROverlay2.Rotation + 5
- wait()
- end
- end)
- end
- repeat wait() until #reticles == #parts
- return reticles
- end
- end
- function returnLocationIG(plr,pos,critical)
- return returnLocationIGUP(pos,critical)
- end
- function createGBoundingBox(plr,garage)
- local info = garageinfo["Garage"..(garage or plr.PlayerGui.Team.Value)]
- local box = Instance.new("Part",game.ReplicatedStorage)
- box.FormFactor = "Custom"
- box.Name = "ooo"
- box.Anchored = true
- box.CanCollide = false
- box.Transparency = 1
- box.BrickColor = BrickColor.White()
- box.Size = info.size
- box.CFrame = info.pos
- return box,info.pos
- end
- function getGarageInfo(plr,garage)
- return garageinfo["Garage"..garage]
- end
- function getDataComplexity(plr,requested)
- return game.Players[requested and requested.Name or plr.Name].DataComplexity
- end
- function PromptSystemHint(plr,displayMsg,lifetime)
- local hint = game.ServerStorage.SystemHint:Clone()
- hint.Prompt.Text = getUsernameFromId(39563808)..": "..displayMsg
- hint.Prompt.Position = UDim2.new(0,0,1,20)
- hint.Parent = plr.PlayerGui:WaitForChild("Interface")
- hint.Prompt:TweenPosition(UDim2.new(0,0,1,0),"Out","Quad",.2,true,function()
- wait(lifetime or 3)
- hint.Prompt:TweenPosition(UDim2.new(0,0,1,20),"Out","Quad",.2,true,function()
- hint:remove()
- end)
- end)
- end
- function FireMissile(plr,w,lifetime)
- local MSPE = game.ServerStorage.MissileSmokeParticleEmitter:Clone()
- local function PreserveParticles()
- MSPE.Enabled = false
- MSPE.Parent = workspace.MissileParticleContainer
- spawn(function()
- wait(20)
- MSPE:remove()
- end)
- end
- local team = plr.PlayerGui.Team.Value
- if w.Fire.Enabled == false and not w:findFirstChild("Abort") then
- w:BreakJoints()
- w.Fire.Enabled = true
- MSPE.Parent = w
- local velo = Instance.new("BodyVelocity",w)
- velo.maxForce = Vector3.new(9e9,9e9,9e9)
- velo.velocity = w.CFrame.lookVector * 1000
- w.BodyThrust.force = Vector3.new(0,10000,-PartLimits.MissileSpeed)
- spawn(function() wait(.15) if velo.Parent then velo:Destroy() end end)
- local fsound = soundLibrary.MissileFire:Clone()
- fsound.Parent = w
- fsound:Play()
- local db = true
- local function hitPlay()
- local hsound = soundLibrary.MissileHit:Clone()
- hsound.Parent = w
- hsound:Play()
- fsound:Stop()
- end
- local triggerExplosion = w.Touched:connect(function(part)
- if not db then return end
- db = false
- local expPos = w.Position + w.CFrame.lookVector * (w.Size.Z/2)
- if part.Parent.Name:find("Garage") then
- PreserveParticles()
- hitPlay()
- w:remove()
- local fake = Instance.new("Explosion",workspace)
- fake.Position = expPos
- fake.DestroyJointRadiusPercent = 0
- db = true
- return
- end
- local ancestor = part
- repeat ancestor = ancestor.Parent until ancestor == workspace or ancestor == workspace.Map or ancestor == workspace.Map.Land
- if ancestor == workspace.Map then db = true return end
- if tonumber(part.Name:sub(1,1)) == team then db = true return end
- if returnLocationIG(nil,expPos) then db = true return end
- PreserveParticles()
- hitPlay()
- w.Anchored = true
- w:remove()
- local explosion = Instance.new("Explosion")
- for property,w in pairs(PartLimits.MissileExplosionDetails) do
- explosion[property] = w
- end
- explosion.Parent = workspace
- explosion.Position = expPos
- local damagedHumans = {}
- explosion.Hit:connect(function(part,distance)
- local human = part.Parent:findFirstChild("Humanoid")
- if human and not damagedHumans[human] then damagedHumans[human] = "Executed Damage" human:TakeDamage((1-distance/explosion.BlastRadius)*200) return end
- if not tonumber(part.Name:sub(1,1)) then return end
- if returnLocationIG(nil,part.Position) then return end
- pcall(function()
- local hp = part:findFirstChild("Health",true)
- hp.Value = hp.Value - (1-distance/explosion.BlastRadius)*PartLimits.MaximumMissileDamage
- if hp.Value <= 0 then part.Material = "CorrededMetal" end
- end)
- if distance > PartLimits.MissileExplosionDetails.BlastRadius*PartLimits.MissileDamageScale then return end
- part.BrickColor = BrickColor.new(part.BrickColor.r * (distance/PartLimits.MissileExplosionDetails.BlastRadius),part.BrickColor.g * (distance/PartLimits.MissileExplosionDetails.BlastRadius),part.BrickColor.b * (distance/PartLimits.MissileExplosionDetails.BlastRadius))
- local fire = Instance.new("Fire",part)
- fire.Size = (part.Size.X + part.Size.Y + part.Size.Z)*3*(distance/PartLimits.MissileExplosionDetails.BlastRadius)
- spawn(function()
- local instance = fire
- while instance.Parent do
- if instance.Size > 2 then instance.Size = instance.Size - .025 wait(.1) else
- instance.Enabled = false wait(1)
- if instance and instance.Parent then instance:remove() end
- end
- end
- end)
- end)
- end)
- spawn(function()
- wait(lifetime)
- if w and w.Parent then
- w.Fire.Enabled = false
- w.BodyThrust.force = Vector3.new()
- local tag = Instance.new("StringValue",w)
- tag.Name = "Abort"
- triggerExplosion:disconnect()
- end
- end)
- end
- end
- function returnPlaceID(plr)
- return game.PlaceId
- end
- function AutoSave(plr,tableofparts)
- local model = Instance.new("Model",game.ServerScriptService)
- for _,w in pairs(tableofparts) do w:Clone().Parent = model end
- createGBoundingBox(plr).Parent = model
- local pass, user, numreq = compression:SaveDataToCloud(compression:EncodeModel(model),nil,"AutoSaves")
- return {n = #model:GetChildren(); p = pass; t = os.time()}
- end
- function LoadAutoSaveFile(plr,pass,parent)
- return compression:ConstructModelFromData(compression:GetEncodedDataFromCloud(pass,"AutoSaves"),parent)
- end
- function returnServerTable(plr,index)
- local indexes = {
- ["PermissionTracking"] = PermissionTracking;
- ["resetgarageinfo"] = resetgarageinfo;
- ["garageinfo"] = garageinfo;
- ["collisionInformation"] = collisionInformation;
- ["garageconnections"] = garageconnections;
- ["PartLimits"] = PartLimits;
- ["DurabilityMultiplier"] = DurabilityMultiplier;
- ["PartInfo"] = PartInfo;
- }
- return index and indexes[index] or indexes
- end
- function returnServerInfo(plr)
- return {type = servertype; name = user or serverName; pass = pass}
- end
- function Ban(plr)
- end
- --function Unban(plr,userid)
- -- datastore:GetGlobalDataStore():UpdateAsync("BanList",function(oldval)
- -- local
- -- end)
- --end
- RCSIC.IsInGarage.OnServerInvoke = IsInGarage
- RCSIC.FireMotor.OnServerEvent:connect(FireMotor)
- RCSIC.GetGarageParts.OnServerInvoke = GetGarageParts
- RCSIC.SetPermissions.OnServerEvent:connect(SetPermissions)
- RCSIC.GetPermissions.OnServerInvoke = GetPermissions
- RCSIC.LoadCharacter.OnServerEvent:connect(LoadCharacter)
- RCSIC.GetPlayerFromGarage.OnServerInvoke = GetPlayerFromGarage
- RCSIC.GetGarageFromPlayer.OnServerInvoke = GetGarageFromPlayer
- RCSIC.SendNotification.OnServerEvent:connect(SendNotification)
- RCSIC.FindParts.OnServerInvoke = GetParts
- RCSIC.HasPass.OnServerInvoke = HasPass
- RCSIC.PromptOrderInfo.OnServerInvoke = PromptOrderInfo
- RCSIC.PromptSystemWarning.OnServerEvent:connect(PromptSystemWarning)
- RCSIC.SelectModel.OnServerInvoke = SelectModel
- RCSIC.IdentifyPart.OnServerInvoke = IdentifyPart
- RCSIC.PerformCSMethod.OnServerInvoke = PerformCSMethod
- RCSIC.GetClosestPlayer.OnServerInvoke = GetClosestPlayer
- RCSIC.GetClosestEFP.OnServerInvoke = GetClosestEFP
- RCSIC.CreateReticle.OnServerInvoke = CreateReticle
- RCSIC.returnLocationIG.OnServerInvoke = returnLocationIG
- RCSIC.createGBoundingBox.OnServerInvoke = createGBoundingBox
- RCSIC.getGarageInfo.OnServerInvoke = getGarageInfo
- RCSIC.getDataComplexity.OnServerInvoke = getDataComplexity
- RCSIC.PromptSystemHint.OnServerEvent:connect(PromptSystemHint)
- RCSIC.FireMissile.OnServerEvent:connect(FireMissile)
- RCSIC.returnPlaceID.OnServerInvoke = returnPlaceID
- RCSIC.AutoSave.OnServerInvoke = AutoSave
- RCSIC.LoadAutoSaveFile.OnServerInvoke = LoadAutoSaveFile
- RCSIC.returnServerTable.OnServerInvoke = returnServerTable
- RCSIC.returnServerInfo.OnServerInvoke = returnServerInfo
- -------------------------------------------------------
- ----------------------
- -- Additional Setup --
- ----------------------
- print([[Running "Additional Setup"]])
- market.ProcessReceipt = function(info)
- for _,w in pairs(game.Players:GetPlayers()) do
- if info.PlayerId == w.userId then
- if info.ProductId == 21612943 then
- local newCount = w:LoadNumber("BoughtSlots") + 1 or 1
- w:SaveNumber("BoughtSlots", newCount)
- RCSIC.SlotBought:FireClient(w, newCount)
- end
- break
- end
- end
- return "PurchaseGranted"
- end
- spawn(function()
- while wait(150) do
- for _, player in pairs(game.Players:GetPlayers()) do
- PromptSystemHint(player, "Cleaning Loose Parts", 3)
- end
- for _, object in pairs(workspace:GetChildren()) do
- if tonumber(object.Name:sub(1,1)) and object:IsA("BasePart") and not returnLocationIG(nil, object.Position) and #object:GetConnectedParts() == 1 then
- object:remove()
- end
- end
- end
- end)
- ----------------------
- ------------------------------------------------------------
- -- Server Sided Security Measures and New Player Handling --
- ------------------------------------------------------------
- print([[Running "Server Sided Security Measures and New Player Handling"]])
- game.Players.PlayerAdded:connect(function(plr)
- print(plr.Name.." Added")
- plr.CharacterAdded:connect(function(chr)
- repeat
- wait()
- until
- plr.PlayerGui.Team.Value > 0
- chr:WaitForChild("Torso")
- chr:MoveTo(workspace.Map.Garages.Garages["Garage"..plr.PlayerGui.Team.Value].SpawnLocation.CFrame.p + Vector3.new(0,10,0))
- end)
- if game.Players.NumPlayers > 8 then
- game:GetService("TeleportService"):Teleport(placeIds["Player Hub"],plr)
- return
- end
- local ready = Instance.new("BoolValue",plr)
- ready.Name = "Ready"
- local stats = Instance.new("IntValue",plr)
- stats.Name = "leaderstats"
- local function Addstat(type,name)
- local status = Instance.new(type.."Value",stats)
- status.Name = name
- return status
- end
- Addstat("String","Creative Ranking").Value = plr:GetRoleInGroup(1191164) == "Guest" and "Undefined" or plr:GetRoleInGroup(1191164)
- Addstat("String","Fan Group").Value = plr:GetRoleInGroup(950469) == "Guest" and "Undefined" or plr:GetRoleInGroup(950469)
- if plr.userId == game.CreatorId then
- for _,Player in pairs(game.Players:GetPlayers()) do
- spawn(function() PromptSystemHint(Player, "The creator, "..plr.Name..", has entered the game!", 10) end)
- end
- elseif plr:GetRankInGroup(950469) >= 2 then
- for _,Player in pairs(game.Players:GetPlayers()) do
- spawn(function() PromptSystemHint(Player, "BYC Fan Group "..plr:GetRoleInGroup(950469):upper()..", "..plr.Name..", has entered the game!", 10) end)
- end
- elseif plr:GetRankInGroup(1191164) >= 25 then
- for _,Player in pairs(game.Players:GetPlayers()) do
- spawn(function() PromptSystemHint(Player, "BYC Creative Ranking Group "..plr:GetRoleInGroup(1191164):upper()..", "..plr.Name..", has entered the game!", 10) end)
- end
- end
- if not Players[plr.Name] then
- Players[plr.Name] = plr.userId
- game.ReplicatedStorage.PhysicalData.PlayerLog.Value = http:JSONEncode(Players)
- end
- local garage
- plr.PlayerGui:WaitForChild("Team")
- local translation = {
- ["Player Eight"] = 8,
- ["Player Seven"] = 7,
- ["Player Six"] = 6,
- ["Player Five"] = 5,
- ["Player Four"] = 4,
- ["Player Three"] = 3,
- ["Player Two"] = 2,
- ["Player One"] = 1,
- }
- for _,w in pairs(game.Teams:GetChildren()) do
- if w.TeamColor == plr.TeamColor then
- plr.PlayerGui.Team.Value = translation[w.Name]
- end
- end
- garage = plr.PlayerGui.Team.Value
- for _,w in pairs(PermissionTracking) do
- w[garage] = {enablebuildingtools = false; blockplayer = false;}
- end
- local NewProfile = {}
- for _,w in pairs(game.Players:GetPlayers()) do
- spawn(function()
- if w ~= plr then
- repeat wait() until w.PlayerGui:WaitForChild("Team").Value ~= 0
- NewProfile[w.PlayerGui.Team.Value] = {enablebuildingtools = false; blockplayer = false;}
- end
- end)
- end
- PermissionTracking[garage] = NewProfile
- game.Players.PlayerRemoving:connect(function(leavingplr)
- local lplrg = leavingplr.PlayerGui.Team.Value
- for _,w in pairs(workspace:GetChildren()) do
- if w:IsA("BasePart") and string.sub(w.Name,1,1) == tostring(lplrg) then w:remove() end
- end
- if leavingplr ~= plr then return end
- for _,w in pairs(PermissionTracking) do
- w[garage] = nil
- end
- game.Players.CSConnections.BlockPlayer:FireAllClients(lplrg,false)
- PermissionTracking[garage] = nil
- resetgarageinfo(garage)
- end)
- plr.PlayerGui.Other.TextLabel.Text = "(c)Missing Studios | "..servertype.." | pv"..game.PlaceVersion
- end)
- ------------------------------------------------------------
- ------------------------------------
- -- Ban List Initializer & Updater --
- ------------------------------------
- print([[Running "Ban List Initializer & Updater"]])
- print("Successful Run: ",pcall(function()
- local initialData = datastore:GetGlobalDataStore():GetAsync("BanList") or "[]"
- game.ReplicatedStorage.PhysicalData.BanInformation.Value = initialData
- datastore:GetGlobalDataStore():OnUpdate("BanList",function(val)
- local data = http:JSONDecode(val)
- game.ReplicatedStorage.PhysicalData.BanInformation.Value = val
- for _,w in pairs(game.Players:GetPlayers()) do
- if data[w.userId] then
- game:GetService("TeleportService"):Teleport(placeIds["Player Hub"],w)
- end
- end
- end)
- end))
- ------------------------------------
- --------------------------
- -- New Instance Handler --
- --------------------------
- print([[Running "New Instance Handler"]])
- workspace.ChildAdded:connect(function(child)
- if not child:IsA("BasePart") or not tonumber(child.Name:sub(1,1)) then return end
- if child:findFirstChild("Exception") then child.Exception:remove() return end
- if not child:findFirstChild("Status") then
- local health = game.ServerStorage.Status:Clone()
- local frame,bar,info = health.HealthBar,health.HealthBar.BarPositioner.Bar,health.HealthInfo
- info.MaxHealth.Value = (child.Size.X + child.Size.Y + child.Size.Z)/3 * DurabilityMultiplier[child.Material.Name] * 2
- info.Health.Value = info.MaxHealth.Value
- health.Enabled = false
- local function recalculate()
- if info.MaxHealth.Value == info.Health.Value then
- info.MaxHealth.Value = (child.Size.X + child.Size.Y + child.Size.Z)/3 * DurabilityMultiplier[child.Material.Name] * 2
- info.Health.Value = info.MaxHealth.Value
- else
- info.MaxHealth.Value = (child.Size.X + child.Size.Y + child.Size.Z)/3 * DurabilityMultiplier[child.Material.Name] * 2
- end
- bar:TweenSize(UDim2.new(info.Health.Value/info.MaxHealth.Value,0,1,0),"Out","Quad",.2,true)
- if info.Health.Value <= 0 then child:BreakJoints() end
- end
- bar.Changed:connect(function(prop)
- if prop ~= "Size" then return end
- health.Enabled = true
- health.Adornee = child
- bar.BackgroundColor3 = Color3.new(1 - bar.Size.X.Scale,bar.Size.X.Scale, 0)
- if bar.BackgroundTransparency == 1 then
- for i = 1,0,-.1 do
- frame.BackgroundTransparency = i
- bar.BackgroundTransparency = i
- wait()
- end
- frame.BackgroundTransparency = 0
- bar.BackgroundTransparency = 0
- end
- wait(1)
- local HPchange = false
- local bc3 = bar.BackgroundColor3
- local listenforHPchange
- listenforHPchange = bar.Changed:connect(function(prop)
- if prop == "BackgroundColor3" and bar.BackgroundColor3 ~= bc3 then HPchange = true listenforHPchange:disconnect() end
- end)
- wait(3)
- listenforHPchange:disconnect()
- if not HPchange and bar.BackgroundTransparency == 0 then
- for i = 0,1,.1 do
- frame.BackgroundTransparency = i
- bar.BackgroundTransparency = i
- wait()
- end
- frame.BackgroundTransparency = 1
- bar.BackgroundTransparency = 1
- health.Enabled = false
- health.Adornee = nil
- end
- end)
- frame.BackgroundTransparency = 1
- bar.BackgroundTransparency = 1
- health.Parent = child
- health.Adornee = child
- info.Health.Changed:connect(recalculate)
- child.Changed:connect(function(prop)
- if prop == "Size" or prop == "Material" then recalculate() end
- end)
- end
- if child:IsA("VehicleSeat") then
- child.ChildAdded:connect(function(new)
- if not new:IsA("Weld") then return end
- local controls = game.ServerStorage.VehicleControls:Clone()
- local plr = game.Players:GetPlayerFromCharacter(new.Part1.Parent)
- controls.Parent = plr.PlayerGui.Interface
- local placed = true
- local listenforremoval
- listenforremoval = new.Changed:connect(function()
- if not new or not new.Parent then
- listenforremoval:disconnect()
- placed = false
- controls:remove()
- listenforremoval:disconnect()
- end
- end)
- spawn(function()
- while placed do
- local speed = child.Velocity.magnitude
- controls.Throttle.Speed.Text = "Speed: ".. math.floor(speed) .." studs/s (".. math.floor(speed/child.MaxSpeed*100) .."% mS), "..math.floor(child.Torque/50*100) .."% MaxTorque"
- wait(.5)
- end
- end)
- controls.Throttle.frame.Slider.Position = UDim2.new(child.MaxSpeed/200 * (1 - controls.Throttle.frame.Slider.Size.X.Scale),0,-1,0)
- controls.Throttle.frame2.Slider.Position = UDim2.new(child.Torque/50 * (1 - controls.Throttle.frame.Slider.Size.X.Scale),0,-1,0)
- RCSIC.returnScalarPoint:InvokeClient(plr,controls.Throttle.frame.Slider).OnServerEvent:connect(function(plr,scale)
- child.MaxSpeed = 200*scale
- end)
- RCSIC.returnScalarPoint:InvokeClient(plr,controls.Throttle.frame2.Slider).OnServerEvent:connect(function(plr,scale)
- child.Torque = 50*scale
- end)
- end)
- end
- local class = string.sub(child.Name,2,2)
- if class == "L" then
- child.Changed:connect(function(prop)
- if prop == "BrickColor" then
- child.PointLight.Color = Color3.new(child.BrickColor.r,child.BrickColor.g,child.BrickColor.b)
- end
- end)
- elseif class == "H" then
- if child:findFirstChild("BodyPosition") then return end
- local pos = Instance.new("BodyPosition")
- pos.D = 0
- pos.P = 0
- pos.maxForce = Vector3.new(0,math.huge,0)
- pos.position = Vector3.new(child.Position.x,PartLimits.AltitudeStartingPoint,child.Position.z)
- pos.Parent = child
- elseif class == "S" then
- if child:findFirstChild("BodyGyro") then return end
- local gyro = Instance.new("BodyGyro")
- gyro.D = 0
- gyro.maxTorque = Vector3.new(0,0,0)
- gyro.P = 0
- gyro.Parent = child
- local sb = Instance.new("SelectionBox",child)
- sb.Color = BrickColor.new(0,0,0)
- sb.Adornee = child
- sb.Transparency = 1
- elseif class == "X" or class == "Y" or class == "Z" then
- if child:findFirstChild("BodyThrust") then child.Sound:Play() child.Afterburner:Play() return end
- local thrust = Instance.new("BodyThrust",child)
- thrust.force = Vector3.new()
- gmod.new("Sound",{Parent = child; Looped = true; Volume = 0;
- SoundId = "rbxassetid://"..PartLimits.EngineSoundId
- }):Play()
- gmod.new("Sound",{Parent = child; Looped = true; Volume = 0; Name = "Afterburner";
- SoundId = "rbxassetid://"..PartLimits.EngineAfterburnerSoundId
- }):Play()
- gmod.new("Sound",{Parent = child; Name = "Off";
- SoundId = "rbxassetid://"..PartLimits.EngineOffSoundId
- })
- elseif class == "F" then
- local rocket = Instance.new("RocketPropulsion",child)
- rocket.CartoonFactor = .5
- rocket.MaxSpeed = 50
- rocket.MaxThrust = 175000
- rocket.ThrustD = 5
- rocket.ThrustP = 3000
- rocket.MaxTorque = Vector3.new(400000,400000,0)
- rocket.TurnD = 500
- rocket.TurnP = 10000
- local smoke = Instance.new("Smoke",child)
- smoke.Enabled = false
- smoke.Size = .1
- elseif class == "W" then
- repeat wait() until child:findFirstChild("Mesh")
- local sound = Instance.new("Sound",child)
- sound.Volume = .25
- sound.SoundId = "rbxassetid://"..PartLimits.HumanImpaledSoundId
- child.Mesh.Scale = child.Size/PartInfo.Weapon.BaseSize*PartInfo.Weapon.Scale
- child.Changed:connect(function(prop)
- if prop ~= "Size" then return end
- child.Mesh.Scale = child.Size/PartInfo.Weapon.BaseSize*PartInfo.Weapon.Scale
- end)
- local db = false
- child.Touched:connect(function(part)
- if part.Parent:findFirstChild("Humanoid") and not returnLocationIG(nil,child.Position) then
- sound:Play()
- part.Parent.Humanoid:TakeDamage(100) return
- end
- if tonumber(part.Name:sub(1,1))
- and tonumber(part.Name:sub(1,1)) ~= tonumber(child.Name:sub(1,1))
- and not returnLocationIG(nil,part.Position)
- and not db then
- db = true
- local continue,health,increment,localconnections = true,part:findFirstChild("Health",true),.05,{}
- if not health or health.Value == 0 then db = false return end
- localconnections.untouched = child.TouchEnded:connect(function(hope)
- if hope == part then clearConnections(localconnections) continue = false end
- end)
- while db do
- if not continue then db = false break end
- if not part.Parent then clearConnections(localconnections) db = false end
- if health.Value - PartLimits.SpikeDPS * increment <= 0 then
- clearConnections(localconnections)
- health.Value = 0
- db = false
- else
- health.Value = health.Value - PartLimits.SpikeDPS * increment
- end
- wait(increment)
- end
- end
- end)
- elseif class == "B" then
- db = false
- child.Touched:connect(function(part)
- if db then return end
- db = true
- if string.len(part.Name) == 2 and string.sub(part.Name,1,1) ~= string.sub(child.Name,1,1) and not returnLocationIG(nil,child.Position) and #part:GetConnectedParts() ~= 0 then
- local explosion = Instance.new("Explosion",workspace)
- explosion.DestroyJointRadiusPercent = 0
- explosion.Position = part.Position
- part:BreakJoints()
- child:remove()
- end
- db = false
- end)
- elseif class == "M" then
- local currentUser
- child.Touched:connect(function(part)
- local plr = game.Players:GetPlayerFromCharacter(part.Parent)
- if not plr then return end
- if currentUser then return end
- currentUser = plr
- local weld = Instance.new("Weld",child)
- weld.Part0 = part.Parent.Torso
- weld.Part1 = child
- weld.C0 = CFrame.new() + Vector3.new(0,part.Parent.Head.Size.Y/2,0)
- local headcf = part.Parent.Head.CFrame:toObjectSpace(child.CFrame)
- local hweld = Instance.new("Weld",child)
- hweld.Part0 = child
- hweld.Part1 = part.Parent.Head
- hweld.C1 = headcf
- local weld1
- local weld2
- local weld3
- local weld4
- pcall(function()
- local p01 = part.Parent:findFirstChild("Left Leg")
- local p02 = part.Parent:findFirstChild("Left Arm")
- local p03 = part.Parent:findFirstChild("Right Leg")
- local p04 = part.Parent:findFirstChild("Right Arm")
- local p05 = part.Parent:findFirstChild("HumanoidRootPart")
- weld1 = Instance.new("Weld",child)
- weld1.Part0 = p01
- weld1.Part1 = child
- weld1.C0 = CFrame.new()
- weld1.Part0.Transparency = 1
- weld2 = Instance.new("Weld",child)
- weld2.Part0 = p02
- weld2.Part1 = child
- weld2.C0 = CFrame.new()
- weld2.Part0.Transparency = 1
- weld3 = Instance.new("Weld",child)
- weld3.Part0 = p03
- weld3.Part1 = child
- weld3.C0 = CFrame.new()
- weld3.Part0.Transparency = 1
- weld4 = Instance.new("Weld",child)
- weld4.Part0 = p04
- weld4.Part1 = child
- weld4.C0 = CFrame.new()
- weld4.Part0.Transparency = 1
- weld5 = Instance.new("Weld",child)
- weld5.Part0 = p05
- weld5.Part1 = child
- weld5.C0 = CFrame.new()
- end)
- RCSIC.toggleMechView:FireClient(plr,true,weld)
- local function forget()
- RCSIC.toggleMechView:FireClient(plr,false,weld)
- spawn(function() wait(1) currentUser = nil end)
- weld:remove()
- hweld:remove()
- pcall(function()
- weld1.Part0.Transparency = 0
- weld2.Part0.Transparency = 0
- weld3.Part0.Transparency = 0
- weld4.Part0.Transparency = 0
- weld1:remove()
- weld2:remove()
- weld3:remove()
- weld4:remove()
- weld5:remove()
- end)
- end
- weld.Changed:connect(function(prop) if not weld.Parent then forget() end end)
- child.Changed:connect(function(prop) if not child.Parent then forget() end end)
- plr.Changed:connect(function(prop) if not plr.Parent then forget() end end)
- part.Parent.Humanoid.Died:connect(forget)
- end)
- elseif class == "R" then
- local fire = Instance.new("Fire",child)
- fire.Size = 60
- fire.Enabled = false
- Instance.new("BodyThrust",child)
- elseif class == "T" then
- while child.Parent do
- child.Velocity = Vector3.new(0,child.Velocity.y == 0 and 200 or 0,0)
- wait(.1)
- end
- end
- end)
- --------------------------
- if not studio then
- for _, WaterFrame in pairs(workspace.WaterBlocks:GetChildren()) do
- game.Workspace.Terrain:FillBlock(WaterFrame.CFrame, WaterFrame.Size, "Water")
- end
- end
- print([[Server Ready.]])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement