· 4 years ago · Feb 25, 2021, 04:14 AM
1-- // different dato
2local ReplicatedStorage = game:GetService("ReplicatedStorage")
3local TS = game:GetService(("TweenService"))
4local Players = game:GetService("Players")
5local ServerScriptService = game:GetService("ServerScriptService")
6local DataStoreService = game:GetService("DataStoreService")
7local ServerStorage = game:GetService("ServerStorage")
8
9local DamageBlock = ReplicatedStorage:WaitForChild(("DamageBlock"))
10
11-- // Data Storage
12local PlayerData = require(ServerStorage.PlayerData)
13
14-- // init
15local r = Random.new()
16local positionStarter
17local randomNumber, pos
18local blockFolder
19local CurrentMine
20local block_name, block_chance
21
22
23-- // config
24local mines = game.Workspace.Mines
25local blockSize = 5
26local autoSaveTimer = 15
27-- // mine properties
28Mines = {
29 Stone = {
30 BlockPriority = {
31 {"Coal", 3},
32 {"Stone", 100}
33 },
34 blockCount = 0,
35 Size = 10
36 },
37 Diamond = {
38 BlockPriority = {
39 {"Diamond", 5},
40 {"Coal", 50},
41 {"Stone", 100}
42 },
43 blockCount = 0,
44 Size = 20
45 }
46}
47
48Ores = {
49 Stone = {
50 Weight = 1
51 },
52 Coal = {
53 Weight = 1.5
54 },
55 Diamond = {
56 Weight = 5
57 },
58 Emerald = {
59 Weight = 25
60 }
61}
62
63
64-- storage
65OccupiedLocations = {
66 Stone = {},
67 Diamond = {}
68}
69
70
71function calculateCurrentWeight(player)
72 local weight = 0
73
74 for k, v in pairs(PlayerData.sessionData["Player_" .. player.UserId]["Ores"]) do
75 weight += Ores[k].Weight * v
76 end
77
78 return weight
79end
80
81-- [ Picks a random block based on priority ]
82-- @param mine_name : mine_name used to retrieve the block priority
83function randomBlock(mine_name)
84 randomNumber = r:NextInteger(1, 100)
85 for i, k in ipairs(Mines[mine_name].BlockPriority) do
86 block_name = k[1]
87 block_chance = k[2]
88
89 if(randomNumber <= block_chance) then
90 return block_name
91 end
92 end
93end
94
95-- [ Check whether or not string is in a table
96-- @param tbl : table you want to search
97-- @param str : string you want look for
98function SearchTable(tbl, str)
99 local l = 1
100 local r = #tbl
101 local m
102 while (l <= r) do
103 m = math.floor((l+r)/2)
104 if str > tbl[m] then
105 l = m+1
106 elseif str < tbl[m] then
107 r = m-1
108 else
109 return m
110 end
111 end
112 return -1
113end
114
115-- [ Tween the position of a part ]
116-- @param Part : The part you want to tween the size of
117-- @param tweenTime,
118function tweenSize(Part, tweenTime)
119 if Part == nil then return end
120
121 local tweenInfo = TweenInfo.new(tweenTime,Enum.EasingStyle.Quad,Enum.EasingDirection.Out)
122 local tween = TS:Create(Part, tweenInfo, {Size = Vector3.new(0.1,0.1,0.1)})
123 local tweenOpacity = TS:Create(Part, tweenInfo, {Transparency = 0.9})
124
125 tweenOpacity:Play()
126 tween:Play()
127
128 Part.Transparency = 0.2
129 Part.Color = Color3.new(1, 1, 1)
130 Part.CanCollide = false
131
132 local sound = workspace.breakSound
133 sound.MaxDistance = 20
134 sound:Play()
135
136 wait(tweenTime)
137end
138
139-- [ Teleport player out of mine ]
140-- @param mine_name : name of mine
141function TeleportPlayersToReturnPoint(mine_name)
142 local mine = game.Workspace.Mines[mine_name]
143 local ReturnPoint = mine.info.ReturnPoint.Position
144 local PS = mine.info.PositionStarter.Position
145
146 for i, player in ipairs(game.Players:GetChildren()) do
147 if player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
148 local HRP_pos = player.Character.HumanoidRootPart.Position
149 if (HRP_pos.x < PS.x+(blockSize*(Mines[mine_name].Size+1)) and
150 HRP_pos.x > PS.x-blockSize and
151 HRP_pos.z < PS.z+(blockSize*(Mines[mine_name].Size+1)) and
152 HRP_pos.z > PS.z-blockSize) then
153 player.Character.HumanoidRootPart.Position = Vector3.new(ReturnPoint.x, ReturnPoint.y + 15, ReturnPoint.z)
154 end
155 end
156 end
157end
158
159-- [ re-generate a mine ]
160-- @param mine_name: name of the mine that is getting re-generated
161function generateMine(mine_name)
162 local size = Mines[mine_name].Size-1
163 for x = 0, size, 1 do
164 for z = 0, size, 1 do
165 positionStarter = mines:WaitForChild(mine_name).info.PositionStarter.Position
166 pos = Vector3.new(positionStarter.x + x*blockSize,positionStarter.y,positionStarter.z + z*blockSize)
167
168 local BlockName = randomBlock(mine_name)
169
170 blockFolder = workspace.Blocks[BlockName]:Clone()
171 blockFolder.Parent = workspace.Mines[mine_name]:FindFirstChild("Blocks").BreakableBlocks
172 blockFolder.Name = pos.x .. "," .. pos.y .. "," .. pos.z
173 blockFolder[BlockName].Size = Vector3.new(blockSize, blockSize, blockSize)
174 blockFolder[BlockName].Position = pos
175
176 table.insert(OccupiedLocations[mine_name], pos.x .. "," .. pos.y .. "," .. pos.z)
177 table.sort(OccupiedLocations[mine_name])
178 Mines[mine_name].blockCount += 1
179 end
180 end
181end
182
183-- [ validate the position of the border block
184-- @param x,y,z : coordinates
185-- @param target : starter block (used for positioning:y)
186function CheckBorder(x,y,z, target)
187 if(target.Position.y < positionStarter.y) then
188 createBlock("Blocker", Vector3.new(x,y,z), blockSize, CurrentMine)
189 end
190end
191
192-- [ Create new blocks to surround the corresponding destroyed block ]
193-- @param target : Block that will be destroyed
194function fillBlocks(target)
195 local tarPos = target.Position
196 CurrentMine = workspace.Mines[target.Parent.Parent.Parent.Parent.Name].Name
197 local positionStarter = mines:WaitForChild(CurrentMine).info.PositionStarter.Position
198
199 table.sort(OccupiedLocations[CurrentMine])
200
201 -- [+y] // if block exists and potential new block position (old+blockSizxe) is less lower than starting position
202 if SearchTable(OccupiedLocations[CurrentMine], tarPos.x..","..tarPos.y+blockSize..","..tarPos.z) == -1 and tarPos.y+blockSize < positionStarter.y then
203 createBlock("", Vector3.new(tarPos.x, tarPos.y+blockSize, tarPos.z), blockSize, CurrentMine)
204 end
205
206 -- -y
207 if SearchTable(OccupiedLocations[CurrentMine],tarPos.x..","..tarPos.y-blockSize..","..tarPos.z) == -1 then
208 createBlock("", Vector3.new(tarPos.x, tarPos.y-blockSize, tarPos.z), blockSize, CurrentMine)
209 end
210
211 -- +x
212 if SearchTable(OccupiedLocations[CurrentMine],tarPos.x+blockSize..","..tarPos.y..","..tarPos.z) == -1 and tarPos.x+blockSize < positionStarter.x+(blockSize*(Mines[CurrentMine].Size)) then
213 createBlock("", Vector3.new(tarPos.x+blockSize, tarPos.y, tarPos.z), blockSize, CurrentMine)
214 elseif tarPos.x+blockSize >= positionStarter.x+(blockSize*(Mines[CurrentMine].Size)) then
215 CheckBorder(positionStarter.x+(blockSize*(Mines[CurrentMine].Size)),tarPos.y, tarPos.z, target)
216
217 end
218
219 -- -x
220 if SearchTable(OccupiedLocations[CurrentMine],tarPos.x-blockSize..","..tarPos.y..","..tarPos.z) == -1 and tarPos.x-blockSize > positionStarter.x-blockSize then
221 createBlock("", Vector3.new(tarPos.x-blockSize, tarPos.y, tarPos.z), blockSize, CurrentMine, target)
222 elseif tarPos.x-blockSize <= positionStarter.x-blockSize then
223 CheckBorder(positionStarter.x-blockSize,tarPos.y, tarPos.z, target)
224 end
225
226 -- +z
227 if SearchTable(OccupiedLocations[CurrentMine],tarPos.x..","..tarPos.y..","..tarPos.z+blockSize) == -1 and tarPos.z+blockSize < positionStarter.z+(blockSize*(Mines[CurrentMine].Size)) then
228 createBlock("", Vector3.new(tarPos.x, tarPos.y, tarPos.z+blockSize), blockSize, CurrentMine)
229 elseif tarPos.z+blockSize >= positionStarter.z+(blockSize*(Mines[CurrentMine].Size)) then
230 CheckBorder(tarPos.x,tarPos.y, positionStarter.z+blockSize*(Mines[CurrentMine].Size),target)
231 end
232
233 -- -z
234 if SearchTable(OccupiedLocations[CurrentMine],tarPos.x..","..tarPos.y..","..tarPos.z-blockSize) == -1 and tarPos.z-blockSize > positionStarter.z-blockSize then
235 createBlock("", Vector3.new(tarPos.x, tarPos.y, tarPos.z-blockSize), blockSize, CurrentMine)
236 elseif tarPos.z-blockSize <= positionStarter.z-blockSize then
237 CheckBorder(tarPos.x, tarPos.y, positionStarter.z-blockSize, target)
238 end
239
240end
241
242-- [ Reset Mine ]
243-- @param mine_name : The name of the mine you want to reset
244function resetMine(mine_name)
245 TeleportPlayersToReturnPoint(mine_name)
246 workspace.Mines[mine_name].Blocks.Blockers:Destroy()
247 workspace.Mines[mine_name].Blocks.BreakableBlocks:Destroy()
248
249 local temp = Instance.new("Folder")
250 temp.Name = "Blockers"
251 temp.Parent = workspace.Mines[mine_name].Blocks
252
253 temp = Instance.new("Folder")
254 temp.Name = "BreakableBlocks"
255 temp.Parent = workspace.Mines[mine_name].Blocks
256
257
258 positionStarter = game.Workspace.Mines[mine_name].info.PositionStarter.Position
259 Mines[mine_name].blockCount = 0
260
261 OccupiedLocations[mine_name] = {}
262 generateMine(mine_name)
263end
264
265-- [ Create a block ]
266-- @param BlockName : The name of the block (Remains blank unless 'Blocker')
267-- @param pos : The position you want the new block to be placed
268-- @param size : Size of block (size, size, size)
269-- @param mine_name : Name of the mine
270function createBlock(BlockName, pos, size, mine_name)
271
272 if(SearchTable(OccupiedLocations[mine_name], pos.X .. "," .. pos.Y .. "," .. pos.Z) ~= -1) then
273 print(SearchTable(OccupiedLocations[mine_name], pos.X .. "," .. pos.Y .. "," .. pos.Z))
274 return false
275 end
276
277 -- reset the mine after a certain amount of generated blocks
278 if (Mines[mine_name].blockCount >= 800) then
279 resetMine(mine_name)
280 return
281 end
282
283 if BlockName == "Blocker" then
284 blockFolder = workspace.Blocks[BlockName]:Clone()
285 blockFolder.Name = "Blocker"
286 blockFolder.Parent = workspace.Mines[mine_name].Blocks.Blockers
287 else
288 BlockName = randomBlock(mine_name)
289 blockFolder = workspace.Blocks[BlockName]:Clone()
290 blockFolder.Parent = workspace.Mines[mine_name]:FindFirstChild("Blocks").BreakableBlocks
291 blockFolder.Name = pos.X .. "," .. pos.Y .. "," .. pos.Z
292 table.insert(OccupiedLocations[mine_name], pos.X .. "," .. pos.Y .. "," .. pos.Z)
293 end
294
295 blockFolder[BlockName].Size = Vector3.new(size,size,size)
296 blockFolder[BlockName].Position = pos
297 Mines[mine_name].blockCount += 1
298end
299
300local queue = {}
301
302-- [ DamageBlock Event ]
303-- @param player : the player who hit the block
304-- @param block : the block that was hit
305-- @param damage : how much damage the player strikes (temp)
306DamageBlock.OnServerEvent:Connect(function(player, block, damage)
307 if(block == nil) then
308 return
309 end
310
311 local positionFolder = block.Parent.Name
312 local CurrentHealth
313 local MaxHealth
314
315 -- check whether or not the decendants exist
316 for i, v in ipairs(block:GetDescendants()) do
317 if(v.Name == "CurrentHealth" or v.Name == "MaxHealth") then
318 CurrentHealth = block.CurrentHealth
319 MaxHealth = block.MaxHealth
320 end
321 end
322
323 if CurrentHealth == nil or MaxHealth == nil then
324 return
325 end
326
327 -- increase damage taken
328 CurrentHealth.Value += damage
329
330 if (CurrentHealth.Value >= MaxHealth.Value)
331 then
332 if (table.find(queue, positionFolder)) then
333 print("already added")
334 return
335 else
336 table.insert(queue, positionFolder)
337 end
338
339 PlayerData:ChangeStat(player, "Level", 1)
340
341 if PlayerData.sessionData["Player_" .. player.UserId]["Ores"][block.Name] then
342 PlayerData.sessionData["Player_" .. player.UserId]["Ores"][block.Name] += 1
343 end
344
345 fillBlocks(block)
346 tweenSize(block, 0.3)
347
348 table.remove(queue, table.find(queue, positionFolder))
349 block:Destroy()
350 end
351
352 player.Inventory.Stats.CurrentWeight.Value = calculateCurrentWeight(player)
353
354 PlayerData.updateStats(player)
355end)
356
357
358-- generate mines when the server starts
359for _, v in ipairs(mines:GetChildren()) do
360 generateMine(v.Name, blockSize)
361end
362
363
364game.Players.PlayerAdded:Connect(function(player)
365 repeat wait() until player:FindFirstChild("Inventory")
366
367 local stat = Instance.new("Folder")
368 stat.Name = "Stats"
369 stat.Parent = player.Inventory
370
371 local spaceLevel = Instance.new("IntValue")
372 spaceLevel.Name = "Space"
373 spaceLevel.Value = 15
374 spaceLevel.Parent = stat
375
376 local maxWeight = Instance.new("IntValue")
377 maxWeight.Name = "MaxWeight"
378 maxWeight.Value = 400
379 maxWeight.Parent = stat
380
381 local currentWeight = Instance.new("IntValue")
382 currentWeight.Name = "CurrentWeight"
383 currentWeight.Value = calculateCurrentWeight(player)
384 currentWeight.Parent = stat
385end)
386
387