Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- ceat_ceat
- -- missing textures and colors LOL
- warn("mineswep by ceat yay")
- if game:GetService("RunService"):IsStudio() then
- require(game.ServerStorage.lsbenv)()
- owner,printf,warnf,LoadLibrary,LoadAssets,NLS=owner,printf,warnf,LoadLibrary,LoadAssets,NLS
- end
- local TweenService = game:GetService("TweenService")
- local Debris = game:GetService("Debris")
- local DEFAULT_TILE_WIDTH = 1.5
- local FIELD_RADIUS = 1
- local RESTART_TIME = 3
- local UNOPENED_TEX = "rbxassetid://15144071117"
- local OPENED_TEX = "rbxassetid://13348346487"
- local MINE_TEX = "rbxassetid://13348250535"
- local FLAG_TEX = "rbxassetid://10720664742"
- local BLANK_TEX = "rbxassetid://12381187927"
- local NUMBER_FONT = Enum.Font.SourceSansBold
- local WIN_MINE_COLOR = Color3.new(0.5, 1, 0.5)
- local DIG_SOUND = "rbxassetid://3498493622"
- local FLAG_SOUND = "rbxassetid://8388724806"
- local CORRECT_SOUND = "rbxassetid://3422389728"
- local YAY_SOUND = "rbxassetid://9068897474"
- local ALARM_SOUND = "rbxassetid://2778386920"
- local EXPLODE_SOUND = "rbxassetid://165969964"
- local COLORS = {
- Color3.fromRGB(0, 0, 255),
- Color3.fromRGB(39, 107, 31),
- Color3.fromRGB(255, 0, 0),
- Color3.fromRGB(0, 0, 130),
- Color3.fromRGB(157, 0, 0),
- Color3.fromRGB(0, 214, 146),
- Color3.fromRGB(98, 0, 168),
- Color3.fromRGB(100, 100, 100),
- }
- local FLASH_TWEENINFO = TweenInfo.new(0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.In)
- local WIN_FLASH_TWEENINFO = TweenInfo.new(0.75, Enum.EasingStyle.Linear, Enum.EasingDirection.In)
- local settings = {
- tileWidth = DEFAULT_TILE_WIDTH,
- use3DFlags = false,
- width = 25,
- height = 25,
- mineCount = 90,
- debug = false
- }
- local currentGame
- local function createTilePart(cf, tileWidth)
- local part = Instance.new("Part")
- part.Anchored = true
- part.CFrame = cf
- part.Size = Vector3.new(tileWidth, 0.5, tileWidth)
- local tileDecal = Instance.new("Decal")
- tileDecal.Name = "TileTexture"
- tileDecal.Texture = UNOPENED_TEX
- tileDecal.Face = Enum.NormalId.Top
- tileDecal.Parent = part
- local clickDetector = Instance.new("ClickDetector")
- clickDetector.Name = "ClickDetector"
- clickDetector.MaxActivationDistance = 30
- clickDetector.Parent = part
- return part
- end
- local function createFlagDecal(part)
- local decal = Instance.new("Decal")
- decal.Name = "FlagDecal"
- decal.Texture = FLAG_TEX
- decal.Face = Enum.NormalId.Top
- decal.ZIndex = 5
- decal.Parent = part
- return decal
- end
- local function displayNumber(tile)
- local surfaceGui = Instance.new("SurfaceGui")
- surfaceGui.Name = "NumberFace"
- surfaceGui.Face = Enum.NormalId.Top
- surfaceGui.SizingMode = Enum.SurfaceGuiSizingMode.PixelsPerStud
- surfaceGui.PixelsPerStud = 25
- local label = Instance.new("TextLabel")
- label.Name = "NumberLabel"
- label.Text = tostring(tile.minesAround)
- label.Font = NUMBER_FONT
- label.TextColor3 = COLORS[tile.minesAround]
- label.TextScaled = true
- label.BackgroundTransparency = 1
- label.AnchorPoint = Vector2.new(0.5, 0.5)
- label.Position = UDim2.fromScale(0.5, 0.5)
- label.Size = UDim2.fromScale(2, 2)
- label.TextTransparency = 1
- label.Rotation = -90
- local flashDecal = Instance.new("Decal")
- flashDecal.Texture = BLANK_TEX
- flashDecal.Face = Enum.NormalId.Top
- flashDecal.ZIndex = 5
- flashDecal.Transparency = 0
- flashDecal.Parent = tile.part
- label.Parent = surfaceGui
- surfaceGui.Parent = tile.part
- TweenService:Create(flashDecal, FLASH_TWEENINFO, { Transparency = 1 }):Play()
- TweenService:Create(label, TweenInfo.new(0.2), {
- TextTransparency = 0
- }):Play()
- TweenService:Create(label, TweenInfo.new(0.2 + math.random()*0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {
- Size = UDim2.fromScale(1, 1)
- }):Play()
- Debris:AddItem(flashDecal, FLASH_TWEENINFO.Time)
- end
- local function iterTiles(tiles)
- local width = #tiles
- local height = #tiles[1]
- local x = 1
- local y = 1
- return function()
- if x > width then
- x = 1
- y += 1
- if y > height then
- return
- end
- end
- local x1 = x
- x += 1
- return x1, y, tiles[x1][y]
- end
- end
- local function disableTile(tile)
- tile.enabled = false
- tile.leftClickConnection:Disconnect()
- tile.rightClickConnection:Disconnect()
- tile.leftClickConnection = nil
- tile.rightClickConnection = nil
- tile.clickDetector:Destroy()
- end
- local function unflagTile(tile)
- if tile.flagInstance then
- tile.flagInstance:Destroy()
- tile.flagInstance = nil
- end
- end
- local function getTilesToFlash(tiles, x, y, offset)
- local flashyGuys = {}
- -- top left -> top right
- for xOff = -offset, offset do
- local tile = tiles[x - xOff] and tiles[x - xOff][y - offset]
- if tile then
- table.insert(flashyGuys, tile)
- end
- end
- -- bottom left -> bottom right
- for xOff = -offset, offset do
- local tile = tiles[x + xOff] and tiles[x + xOff][y + offset]
- if tile and not table.find(flashyGuys, tile) then
- table.insert(flashyGuys, tile)
- end
- end
- -- top left -> bottom left
- if tiles[x - offset] then
- for yOff = -offset, offset do
- local tile = tiles[x - offset][y + yOff]
- if tile and not table.find(flashyGuys, tile) then
- table.insert(flashyGuys, tile)
- end
- end
- end
- -- top right -> bottom right
- if tiles[x + offset] then
- for yOff = -offset, offset do
- local tile = tiles[x + offset][y + yOff]
- if tile and not table.find(flashyGuys, tile) then
- table.insert(flashyGuys, tile)
- end
- end
- end
- return flashyGuys
- end
- local function flashTilesWave(tiles, tile, width, height, winner, color)
- local baseX = tile.x
- local baseY = tile.y
- for i = 0, math.max(width, height) do
- for _, tile in getTilesToFlash(tiles, baseX, baseY, i) do
- if tile.isFlagged then
- tile.isFlagged = false
- unflagTile(tile)
- end
- if winner then
- tile.tileTexture.Texture = OPENED_TEX
- else
- if tile.isMine then
- tile.tileTexture.Texture = MINE_TEX
- end
- end
- tile.tileTexture.Color3 = color
- if not tile.isMine then
- TweenService:Create(tile.tileTexture, WIN_FLASH_TWEENINFO, { Color3 = Color3.new(1, 1, 1) }):Play()
- end
- end
- task.wait()
- end
- end
- local function playSound(part, soundId, pitch)
- local sound = Instance.new("Sound")
- sound.SoundId = soundId
- sound.Pitch = pitch
- sound.Parent = part
- sound:Play()
- Debris:AddItem(sound, 4)
- return sound
- end
- -- debug visuals
- local function highlightTile(tile, color)
- local part = Instance.new("Part")
- part.Anchored = true
- part.CanCollide = false
- part.CanTouch = false
- part.CanQuery = false
- part.Material = Enum.Material.Neon
- part.Color = color
- part.Size = Vector3.new(settings.tileWidth, 0.7, settings.tileWidth)
- part.Transparency = 0.8
- part.CFrame = tile.part.CFrame
- return part
- end
- local function showNeighbors(tiles, tile)
- local main = highlightTile(tile, Color3.new(1, 0, 0))
- main.Parent = workspace
- local neighborParts = {}
- for _, position in tile.neighbors do
- local part = highlightTile(tiles[position.x][position.y], Color3.new(0, 0, 1))
- part.Parent = workspace
- table.insert(neighborParts, part)
- end
- task.wait()
- main:Destroy()
- for _, part in neighborParts do
- part:Destroy()
- end
- end
- -- game wow
- local restartTask
- local function restart(spawnCF, width, height, numMines)
- restartTask = task.delay(RESTART_TIME, function()
- restartTask = nil
- stopGame(currentGame)
- currentGame = createGame(spawnCF, width, height, numMines)
- end)
- end
- function createGame(spawnCF, width, height, numMines)
- local gameObject = {}
- local gameSettings = table.clone(settings)
- gameObject.settings = gameSettings
- local model = Instance.new("Model")
- model.Name = "Minesweeper"
- gameObject.model = model
- local tiles = {}
- gameObject.tiles = tiles
- gameObject.active = true
- gameObject.didFirstClick = false
- gameObject.players = {}
- local function layMines(clickedTile)
- local validPositions = {}
- -- filter out start field
- for x, y, tile in iterTiles(tiles) do
- if math.abs(x - clickedTile.x) <= FIELD_RADIUS and math.abs(y - clickedTile.y) <= FIELD_RADIUS then
- continue
- end
- table.insert(validPositions, { x = x, y = y })
- end
- for i = 1, math.min(numMines, #validPositions) do
- local pos = table.remove(validPositions, math.random(#validPositions))
- local tile = tiles[pos.x][pos.y]
- tile.isMine = true
- if gameSettings.debug then
- tile.tileTexture.Color3 = Color3.new(1, 0.5, 0.5)
- end
- end
- -- count mines around tiles
- for x, y, tile in iterTiles(tiles) do
- for _, position in tile.neighbors do
- if tiles[position.x][position.y].isMine then
- tile.minesAround += 1
- end
- end
- if gameSettings.debug then
- showNeighbors(tiles, tile)
- end
- end
- end
- local function onLose(plr, tile)
- gameObject.active = false
- for x, y, tile in iterTiles(tiles) do
- if tile.enabled then
- disableTile(tile)
- end
- if tile.isMine then
- tile.tileTexture.Texture = MINE_TEX
- end
- end
- tile.part.CFrame *= CFrame.new(0, 1, 0)
- tile.part.Anchored = false
- tile.part.Velocity = Vector3.new(-3 + math.random()*6, math.random(20, 30), -3 + math.random()*6)
- tile.part.RotVelocity = Vector3.new(math.random(-10, 10), math.random(-10, 10), math.random(-10, 10))
- playSound(tile.part, ALARM_SOUND, 1).TimePosition = 0.35
- playSound(tile.part, EXPLODE_SOUND, 1)
- local explod = Instance.new("Explosion")
- explod.BlastPressure = 0
- explod.BlastRadius = 0
- explod.Position = tile.part.Position
- explod.Parent = workspace
- flashTilesWave(tiles, tile, width, height, false, Color3.new(1, 0.5, 0.5))
- restart(spawnCF, width, height, numMines)
- end
- local function onWin(tile)
- for x, y, tile in iterTiles(tiles) do
- if tile.enabled then
- disableTile(tile)
- end
- end
- playSound(tile.part, CORRECT_SOUND, 1)
- playSound(tile.part, YAY_SOUND, 1)
- flashTilesWave(tiles, tile, width, height, true, WIN_MINE_COLOR)
- restart(spawnCF, width, height, numMines)
- end
- local mineTile -- scream
- local function chordTile(plr, tile)
- local unflaggedTiles = {}
- local numFlagged = 0
- for _, position in tile.neighbors do
- local otherTile = tiles[position.x][position.y]
- if otherTile.opened then continue end
- if otherTile.isFlagged then
- numFlagged += 1
- else
- table.insert(unflaggedTiles, otherTile)
- end
- end
- if numFlagged == tile.minesAround then
- for _, otherTile in unflaggedTiles do
- mineTile(plr, otherTile)
- end
- end
- end
- function mineTile(plr, tile)
- if not gameObject.active then
- return
- end
- if tile.isMine then
- onLose(plr, tile)
- return
- end
- if tile.opened then
- chordTile(plr, tile)
- return
- end
- if not table.find(gameObject.players, plr.Name) then
- table.insert(gameObject.players, plr.Name)
- end
- if tile.isFlagged then
- tile.isFlagged = false
- unflagTile(tile)
- end
- tile.opened = true
- tile.tileTexture.Texture = OPENED_TEX
- if tile.minesAround == 0 then
- disableTile(tile)
- for _, position in tile.neighbors do
- local otherTile = tiles[position.x][position.y]
- if otherTile.opened then continue end
- mineTile(plr, otherTile)
- end
- else
- displayNumber(tile)
- end
- end
- local function checkWin()
- local numNonMines = 0
- local numOpened = 0
- for x, y, tile in iterTiles(tiles) do
- if not tile.isMine then
- numNonMines += 1
- end
- if tile.opened then
- numOpened += 1
- end
- end
- return numNonMines == numOpened
- end
- local function onLeftClick(tile)
- return function(plr)
- if tile.isFlagged then
- return
- end
- if not gameObject.didFirstClick then
- gameObject.didFirstClick = true
- layMines(tile)
- end
- playSound(tile.part, DIG_SOUND, 0.9 + math.random()*0.2)
- mineTile(plr, tile)
- if checkWin() then
- onWin(tile)
- end
- end
- end
- local function onRightClick(tile)
- return function(plr)
- if tile.opened then
- return
- end
- tile.isFlagged = not tile.isFlagged
- playSound(tile.part, FLAG_SOUND, 0.8 + math.random()*0.4)
- if tile.isFlagged then
- if gameSettings.use3DFlags then
- -- not implemented
- else
- tile.flagInstance = createFlagDecal(tile.part)
- end
- else
- unflagTile(tile)
- end
- end
- end
- local originCF = spawnCF * CFrame.new(-width/2*gameSettings.tileWidth, 0, -height/2*gameSettings.tileWidth)
- for x = 1, width do
- local row = {}
- for y = 1, height do
- local tileCF = originCF * CFrame.new(x*gameSettings.tileWidth, 0, y*gameSettings.tileWidth)
- local part = createTilePart(tileCF, gameSettings.tileWidth)
- --part.CanCollide = false
- --part.Transparency = 1
- local self = {
- x = x,
- y = y,
- enabled = true,
- opened = false,
- isMine = false,
- isFlagged = false,
- neighbors = {}, -- {x = num, y = num}
- minesAround = 0, -- decided by layMines
- part = part,
- tileTexture = part.TileTexture,
- clickDetector = part.ClickDetector,
- flagInstance = nil, -- decal or instance
- leftClickConnection = nil,
- rightClickConnection = nil,
- }
- self.leftClickConnection = self.clickDetector.MouseClick:Connect(onLeftClick(self))
- self.rightClickConnection = self.clickDetector.RightMouseClick:Connect(onRightClick(self))
- for xOffset = -1, 1 do
- for yOffset = -1, 1 do
- if xOffset == 0 and yOffset == 0 then continue end
- local x2 = x + xOffset
- local y2 = y + yOffset
- if x2 < 1 or x2 > width then continue end
- if y2 < 1 or y2 > height then continue end
- table.insert(self.neighbors, { x = x2, y = y2 })
- end
- end
- part.Parent = model
- --local delayTime = (y - 1)*(width)*0.00005 + x*0.00005
- --TweenService:Create(part, TweenInfo.new(0.15 + math.random()*0.15, Enum.EasingStyle.Quad, Enum.EasingDirection.In), {
- -- Transparency = 0,
- -- CFrame = tileCF,
- -- CanCollide = true
- --}):Play()
- row[y] = self
- end
- tiles[x] = row
- end
- model.Parent = workspace
- return gameObject
- end
- function stopGame(gameObject)
- for x, y, tile in iterTiles(gameObject.tiles) do
- if tile.enabled then
- disableTile(tile)
- end
- end
- gameObject.model:Destroy()
- end
- -- currentGame = createGame(CFrame.new(0, 5, 0), settings.width, settings.height, settings.mineCount)
- local function getRootPos()
- local humanoid = owner.Character and owner.Character:FindFirstChildOfClass("Humanoid")
- if humanoid and humanoid.RootPart then
- return humanoid.RootPart.CFrame.Position
- end
- end
- owner.Chatted:Connect(function(msg)
- local cmdString = msg:match("ms/(.+)")
- if not cmdString then return end
- local args = cmdString:split("/")
- local cmdName = table.remove(args, 1)
- if cmdName == "size" then
- if args[2] then
- settings.width = tonumber(args[1])
- settings.height = tonumber(args[2])
- printf(`set size to <b>{settings.width}x{settings.height}</b>`)
- else
- local size = tonumber(args[1])
- if not size then
- return printf("<i>pls provide size</i>")
- end
- settings.width = size
- settings.height = size
- printf(`set size to <b>{size}x{size}</b>`)
- end
- elseif cmdName == "mines" then
- local mineCount = tonumber(args[1])
- if not mineCount then
- return printf("<i>pls provide minecount</i>")
- end
- settings.mineCount = mineCount
- printf(`set mine count to <b>{settings.mineCount}</b>`)
- elseif cmdName == "minefreq" then
- local freq = tonumber(args[1])
- if not freq then
- return printf("<i>pls provide freq</i>")
- end
- settings.mineCount = math.floor(settings.width*settings.height*freq)
- printf(`set mine count to <b>{settings.mineCount}</b>`)
- elseif cmdName == "game" then
- local rootPos = getRootPos()
- if not rootPos then
- return printf("<i>could not find rootpos</i>")
- end
- if currentGame then
- stopGame(currentGame)
- end
- currentGame = createGame(CFrame.new(rootPos + Vector3.new(0, -1.75, 0)), settings.width, settings.height, settings.mineCount)
- printf("<i>started game</i>")
- elseif cmdName == "stop" then
- if restartTask then
- task.cancel(restartTask)
- restartTask = nil
- end
- if currentGame then
- stopGame(currentGame)
- else
- printf("<i>no game active</i>")
- end
- elseif cmdName == "debug" then
- settings.debug = not settings.debug
- printf(`<i>debug mode {settings.debug}</i>`)
- elseif cmdName == "cmds" then
- printf([[
- <b>ms/size/[width]/[height]</b> set board size to (width, height)
- <b>ms/size/<[sideLength]</b> set board size to (sideLength, sideLength)
- <b>ms/mines/[mineCount]</b> set mine count to mineCount
- <b>ms/minefreq/[mineFrequency]</b> set mine count to width*height*mineFrequency
- <b>ms/game</b> start game
- <b>ms/stop</b> end game
- <b>ms/cmds</b> this thing
- ]])
- else
- printf("<i>invalid ms/ command</i>")
- end
- end)
- print("ms/cmds for list of commands (works with /e)")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement