if not nrequire then return end local meta = FindMetaTable("Player") local rockdata = { {nil,0}, {"Stone" , 15}, {"Copper" , 30}, {"Tin" , 60}, {"Iron" , 120}, {"Coal" , 180}, } local skil = nrequire("sh_skillcommon.lua") skil.RegisterSkill({"Forageing","Mineing"}) local function printpuzzle(puzzle) Msg("========================") for y = 0, puzzle.height-1 do for x = 0, puzzle.width-1 do Msg(puzzle.tiles[x][y]) end Msg("\n") end end local function findmatchesfortile(puzzle,x,y) printpuzzle(puzzle) local matches = {} local pt = puzzle.tiles local t = pt[x][y] --Find horizontal matches local matcheshoizontal = 1 local cursor = x + 1 local pot = {{x,y}} while cursor < puzzle.width and pt[cursor][y] == t do matcheshoizontal = matcheshoizontal + 1 pot[#pot + 1] = {cursor,y} cursor = cursor + 1 end cursor = x - 1 while cursor >= 0 and pt[cursor][y] == t do matcheshoizontal = matcheshoizontal + 1 pot[#pot + 1] = {cursor,y} cursor = cursor - 1 end if matcheshoizontal > 2 then for k,v in ipairs(pot) do matches[#matches+1] = v end end --Find verticle matches local matchesverticle = 1 cursor = y + 1 pot = {{x,y}} while cursor < puzzle.height and pt[x][cursor] == t do matchesverticle = matchesverticle + 1 pot[#pot + 1] = {x,cursor} cursor = cursor + 1 end cursor = y - 1 while cursor >= 0 and pt[x][cursor] == t do matchesverticle = matchesverticle + 1 pot[#pot + 1] = {x,cursor} cursor = cursor - 1 end if matchesverticle > 2 then for k,v in ipairs(pot) do matches[#matches+1] = v end end return matches end local function canswitch(puzzle,x1,y1,x2,y2) if x1 == x2 and (y1 + 1 == y2 or y1 - 1 == y2) or y1 == y2 and (x1 + 1 == x2 or x1 - 1 == x2) then local v1 = puzzle.tiles[x1][y1] local v2 = puzzle.tiles[x2][y2] local tcpy = table.Copy(puzzle) tcpy.tiles[x2][y2] = v1 tcpy.tiles[x1][y1] = v2 printpuzzle(tcpy) local m1 = findmatchesfortile(tcpy,x1,y1) local m2 = findmatchesfortile(tcpy,x2,y2) return #m1 > 0 or #m2 > 0 end return false end local oremap = { [0] = "materials/svg/faithtoken/originals/svg/000000/transparent/ore.svg", "materials/svg/lorc/originals/svg/000000/transparent/rock.svg", "materials/svg/lorc/originals/svg/000000/transparent/stone-block.svg", "materials/svg/faithtoken/originals/svg/000000/transparent/minerals.svg", "materials/svg/delapouite/originals/svg/000000/transparent/stone-pile.svg", "materials/svg/lorc/originals/svg/000000/transparent/fossil.svg" } if SERVER then local itm = nrequire("item.lua") for k,v in pairs(oremap) do resource.AddSingleFile(v) end util.AddNetworkString("artery_mine_rock_start") util.AddNetworkString("artery_mine_rock_new") util.AddNetworkString("artery_mine_rock_quit") util.AddNetworkString("artery_mine_rock_action") util.AddNetworkString("artery_mine_rocks_update") local function genpuzzle(width,height,variety) local puzzle = {} puzzle.width = width puzzle.height = height puzzle.variety = variety puzzle.tiles = {} for i = 0,puzzle.width do puzzle.tiles[i] = {} for j = 0,puzzle.height do puzzle.tiles[i][j] = math.random(0,puzzle.variety) end end return puzzle end local function del_and_replace(puzzle,matches) local tp = puzzle.tiles local function dropcolumn(x,y,spaces) print("dropping ", x,y) for ty = y, 0, -1 do tp[x][ty] = tp[x][ty - spaces] or math.random(0,puzzle.variety) end end for k,v in pairs(matches) do dropcolumn(v[1],v[2],1) end end local function findmatchesfor(puzzle) local duped = {} for i = 0, puzzle.width-1 do duped [i] = {} end for y = 0,puzzle.height-1 do for x = 0, puzzle.width-1 do local matches = findmatchesfortile(puzzle,x,y) for k,v in pairs(matches) do duped[v[1]][v[2]] = true end end end local m = {} for y = 0,puzzle.height-1 do for x = 0, puzzle.width-1 do if duped[x][y] then m[#m+1] = {x,y} end end end return m end local puzzles = {} local scores = {} function meta:MineRock() local p = genpuzzle(5,5,4) local m = findmatchesfor(p) while #m > 0 do del_and_replace(p,m) m = findmatchesfor(p) end puzzles[self] = p scores[self] = 0 self:StartAnimation("stranded_mine_rocks") net.Start("artery_mine_rock_start") net.WriteTable(p) net.Send(self) end local function kick_cheating_player(who) error(who:Nick() .. " was cheating!") end net.Receive("artery_mine_rock_action",function(ln,ply) local p = puzzles[ply] local x1 = net.ReadUInt(8) local y1 = net.ReadUInt(8) local x2 = net.ReadUInt(8) local y2 = net.ReadUInt(8) if not canswitch(p,x1,y1,x2,y2) then kick_cheating_player(ply) end local v1,v2 = p.tiles[x1][y1],p.tiles[x2][y2] p.tiles[x2][y2] = v1 p.tiles[x1][y1] = v2 local m = findmatchesfor(p) while #m > 0 do scores[ply] = scores[ply] + #m del_and_replace(p,m) m = findmatchesfor(p) end printpuzzle(p) net.Start("artery_mine_rocks_update") net.WriteTable(p) net.WriteDouble(scores[ply]) net.Send(ply) ply:StartAnimation("stranded_mine_rock") end) net.Receive("artery_mine_rock_quit",function(ln,ply) local s = scores[ply] local cursor = 1 while cursor <= #rockdata and s >= rockdata[cursor][2] do cursor = cursor + 1 end local n = rockdata[cursor-1][1] if n == nil then return end local togive = itm.GetItemByName(n) ply:GiveItem(togive) ply:AddSkill("Mineing",s) ply:StopAnimation("stranded_mine_rock") end) else local svg = nrequire("cl_svg.lua") local mine = {} local tbl local puzzleview local rocks = {} local oremats = {} for k,v in pairs(oremap) do oremats[k] = svg.MaterialFromSVG(v,nil,"rgb(0,0,0);") end local oremats_selected = {} for k,v in pairs(oremap) do oremats_selected[k] = svg.MaterialFromSVG(v,"rgb(100,100,200);","rgb(255,255,255);") end net.Receive("artery_mine_rock_start",function() tbl = net.ReadTable() puzzleview = vgui.Create( "DFrame" ) puzzleview:SetSize( ScrW()*0.5, ScrH()*0.5 ) puzzleview:Center() puzzleview:SetTitle( "Mine Rocks..." ) puzzleview:SetDraggable( true ) puzzleview:MakePopup() puzzleview.OnClose = function(self) net.Start("artery_mine_rock_quit") net.SendToServer() end local puzzlepane = vgui.Create( "DPanel", puzzleview ) puzzlepane:Dock(FILL) local help = vgui.Create("DLabel",puzzlepane) help:SetText("Click two cells to switch them.\nCreate runs of 3 or more to clear them from the board\nNew numbers come in from the top\nQuit at any time to receive the resource you have worked towards.") help:SetDark(true) help:SizeToContents() help:Dock(RIGHT) local rocklayout = vgui.Create("DPanel",puzzlepane) rocklayout:Dock(BOTTOM) local rockprogress = vgui.Create( "DProgress",rocklayout ) rockprogress:Dock(FILL) local rocknameleft = vgui.Create("DLabel",rocklayout) rocknameleft:Dock(LEFT) rocknameleft:SetDark(true) rocknameleft:SetText("") local rocknameright = vgui.Create("DLabel",rocklayout) rocknameright:Dock(RIGHT) rocknameright:SetDark(true) rocknameright:SetText(rockdata[2][1]) rocks = {rockprogress,rocknameleft,rocknameright} local puzzlegrid = vgui.Create( "DGrid", puzzlepane ) puzzlegrid:SetCols(tbl.width) puzzlegrid:Dock(TOP) local selected for y = 0,tbl.height-1 do for x = 0,tbl.width-1 do local tile = vgui.Create("DImageButton") mine[x] = mine[x] or {} mine[x][y] = tile local tmat = oremats[tbl.tiles[x][y]] if tmat.material then tile:SetMaterial(tmat.material) end tile:SetStretchToFit( true ) tile.position = {x,y} tile:SetWidth(32) tile:SetHeight(32) tile:SetIsToggle(true) tile.OnToggled = function(self,state) if state then self:SetMaterial(oremats_selected[tbl.tiles[x][y]].material) else self:SetMaterial(oremats[tbl.tiles[x][y]].material) end end tile.DoClick = function(self) if selected == nil then selected = self self:SetToggle(true) self:OnToggled(true) elseif selected ~= self then --Check if we can switch local sp = selected.position local tp = self.position if canswitch(tbl,sp[1],sp[2],tp[1],tp[2]) then net.Start("artery_mine_rock_action") net.WriteUInt(sp[1],8) net.WriteUInt(sp[2],8) net.WriteUInt(tp[1],8) net.WriteUInt(tp[2],8) net.SendToServer() local v1,v2 = selected:GetText(),self:GetText() selected:SetText(v2) self:SetText(v1) selected:SetToggle(false) selected:OnToggled(false) selected = nil end else selected:SetToggle(false) selected:OnToggled(false) selected = nil end end puzzlegrid:AddItem(tile) end end end) net.Receive("artery_mine_rocks_update",function() tbl = net.ReadTable() local score = net.ReadDouble() puzzleview:SetTitle("Mine Rocks... (" .. score .. ")") printpuzzle(tbl) for y = 0, tbl.height-1 do for x = 0, tbl.width-1 do mine[x][y]:SetMaterial(oremats[(tbl.tiles[x][y])].material) end end if score > rockdata[#rockdata][2] then puzzleview:Close() return end for k,v in ipairs(rockdata) do if score >= v[2] then local l = v[2] local n = rockdata[k+1][2] local frac = (score-l) / (n - l) rocks[1]:SetFraction(frac) rocks[2]:SetText(v[1] or "") rocks[3]:SetText(rockdata[k+1][1]) end end end) end