Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --==VARIABLES==--
- --Phrase to start trial
- startPhrase = "i accept the trial"
- --modem
- modem = peripheral.find("modem")
- --monitor + window
- mon = peripheral.find("monitor")
- mon.clear()
- mon.setTextScale(1)
- mon.setBackgroundColor(colors.black)
- mon.setTextColor(colors.white)
- monX,monY = mon.getSize()
- win = window.create(mon,2,2,monX-2,monY-2,true)
- --sensors
- sensors = {
- "manipulator_15",
- "manipulator_16",
- "manipulator_17",
- "manipulator_18"
- }
- --essence tank
- tank = peripheral.wrap("industrialforegoing:black_hole_tank_tile_9")
- --mob-tool / tape chest
- chestName = "projecte:alchemical_chest_1094"
- chest = peripheral.wrap(chestName)
- --tape drive
- tape = "tape_drive_17"
- --block name for spawners
- blockName = "industrialforegoing:mob_duplicator_tile_"
- --spawner IDs, split into rings
- spawners = {
- -- Ring 1
- {
- "8",
- "11",
- "5",
- "29",
- "9",
- "32",
- "10",
- "31"
- },
- -- Ring 2
- {
- "14",
- "17",
- "7",
- "30",
- "15",
- "18",
- "16",
- "20"
- },
- -- Ring 3
- {
- "21",
- "25",
- "23",
- "26",
- "22",
- "28",
- "24",
- "27"
- }
- }
- --add block name to spawner IDs
- for ring,group in pairs(spawners) do
- for spawner,id in pairs(group) do
- spawners[ring][spawner] = blockName..id
- end
- end
- waves = {
- [1] = {["Husk"] = 4},
- [2] = {["quark:dweller"] = 4},
- [3] = {["quark:ashen"] = 1,["Stray"] = 1},
- [4] = {["WitherSkeleton"] = 2},
- [5] = {["quark:ashen"] = 1,["Stray"] = 1},
- [6] = {["WitherSkeleton"] = 2},
- [7] = {["VindicationIllager"] = 2},
- [8] = {["EvocationIllager"] = 1,["Witch"] = 1},
- [9] = {["VindicationIllager"] = 2},
- [10] = {["EvocationIllager"] = 1,["Witch"] = 1}
- }
- function initVars()
- --mobs
- mobs = {
- ["Zombie"] = 0,
- ["ZombieVillager"] = 0,
- ["quark:dweller"] = 0,
- ["Husk"] = 0,
- ["PigZombie"] = 0,
- ["Skeleton"] = 0,
- ["Stray"] = 0,
- ["quark:ashen"] = 0,
- ["WitherSkeleton"] = 0,
- ["quark:foxhound"] = 0,
- ["Blaze"] = 0,
- ["Ghast"] = 0,
- ["Witch"] = 0,
- ["VindicationIllager"] = 0,
- ["EvocationIllager"] = 0,
- }
- --flags
- queue = {}
- alive = {}
- wave = 0
- player = nil
- time = 0
- scores = {{},{},{},{},{}}
- running = false
- end
- initVars()
- --==FUNCTIONS==--
- ----------------------------------------------------
- --functions for managing timers
- function getTime()
- h = os.date("%H")
- m = os.date("%M")
- s = os.date("%S")
- return ((h*60*60)+(m*60)+s)
- end
- function timeString(timeInt)
- return string.format("%sm%ss", math.floor(timeInt/60),timeInt%60)
- end
- ----------------------------------------------------
- --functions for given terminal/monitor/window object
- --write text for given terminal/monitor/window object
- --takes string, x (or alignment) and y, and colours
- function advWrite(obj,str,x,y,fg,bg)
- if fg then
- ofg = obj.getTextColor()
- obj.setTextColor(fg)
- end
- if bg then
- obg = obj.getBackgroundColor()
- obj.setBackgroundColor(bg)
- end
- maxX = obj.getSize()
- if x == "c" then x = (1+maxX-#str)/2
- elseif x == "r" then x = (1+maxX-#str) end
- obj.setCursorPos(x,y)
- obj.write(str)
- if fg then obj.setTextColor(ofg) end
- if bg then obj.setBackgroundColour(obg) end
- end
- --colour for given terminal/monitor/window object
- --sets text and background simultaneously
- function setColour(obj,fg,bg)
- if fg then obj.setTextColor(fg) end
- if bg then obj.setBackgroundColor(bg) end
- end
- function clearLine(obj,y)
- obj.setCursorPos(1,y)
- obj.clearLine()
- end
- function monitorBorder()
- --draw monitor border
- setColour(mon,colors.black,colors.gray)
- for a = 1,monX do
- if (a == 1) or (a == monX) then
- advWrite(mon,string.char(7),a,1,colors.green,colors.black)
- advWrite(mon,string.char(7),a,monY,colors.green,colors.black)
- else
- advWrite(mon,"-",a,1)
- advWrite(mon,"-",a,monY)
- end
- end
- for b = 2,monY-1 do
- advWrite(mon,"|",1,b)
- advWrite(mon,"|",monX,b)
- end
- setColour(mon,colors.white,colors.black)
- end
- function displayScoreboard()
- if fs.exists("scores") then
- file = fs.open("scores","r")
- scores = textutils.unserialise(file.readAll())
- file.close()
- else
- file = fs.open("scores","w")
- file.write(textutils.serialise(scores))
- end
- win.clear()
- advWrite(win,"Leaderboard:","c",2,colors.green,colors.gray)
- for i = 1,5 do
- if #scores[i] == 2 then
- p = scores[i][1]
- t = timeString(scores[i][2])
- else
- p = "#"
- t = "#m#s"
- end
- clearLine(win,(2+(2*i)))
- advWrite(win,string.format("%s. %s - %s",i,p,t),"c",(2+(2*i)),colors.orange)
- end
- end
- ----------------------------------------------------
- --main arena management functions
- function initWave()
- wave = wave + 1
- modem.transmit(wave,100,"")
- clearLine(win, 2)
- advWrite(win,string.format("Wave %s",wave),"c",2,colors.green,colors.gray)
- for w,exists in pairs(waves) do
- if w == wave then
- for m,c in pairs(exists) do
- mobs[m] = mobs[m] + c
- end
- if wave == 10 then running = false end
- end
- end
- for mob,count in pairs(mobs) do
- if count > 0 then
- for _ = 1,count do
- table.insert(queue,mob)
- if not alive[mob] then
- alive[mob] = {}
- end
- end
- end
- end
- end
- function checkSpawned(mobQueued)
- for _,sensorID in pairs(sensors) do
- sensor = peripheral.wrap(sensorID)
- for _,found in pairs(sensor.sense()) do
- if found.name == mobQueued then
- if #alive[mobQueued] > 0 then
- for _,mobID in pairs(alive[mobQueued]) do
- if found.id == mobID then
- mobExists = true
- end
- end
- end
- if not mobExists then
- table.insert(alive[mobQueued],found.id)
- return true
- end
- end
- if mobExists then mobExists = false end
- end
- end
- return false
- end
- function checkAlive(totalCount)
- isAlive = false
- for m,ids in pairs(alive) do
- for n,id in pairs(ids) do
- for i,sensor in pairs(sensors) do
- if peripheral.wrap(sensor).getMetaByID(id) then
- isAlive = true
- end
- end
- if not isAlive then
- table.remove(alive[m],n)
- else
- isAlive = false
- end
- end
- if (#alive[m] + #queue) == 0 then
- alive[m] = nil
- end
- numAlive = 0
- for _,ids in pairs(alive) do numAlive = numAlive + #ids end
- waveProg = math.floor(((numAlive+#queue)/totalCount)*100)
- if waveProg ~= lastCheck then
- modem.transmit(wave,waveProg,"")
- lastCheck = waveProg
- end
- if (numAlive + #queue) == 0 then waveOver = true end
- end
- return waveOver
- end
- function checkPlayers(runOnce)
- while (player and runOnce) or (player and running) do
- playerAlive = false
- for i,sensor in pairs(sensors) do
- playerData = peripheral.wrap(sensor).getMetaByName(player)
- if player and playerData then
- playerAlive = true
- if running then
- clearLine(win,1)
- hearts = (math.ceil(playerData.health))/2
- for i = 1,math.floor(hearts) do
- advWrite(win,string.char(3),i,1,colors.red)
- end
- if hearts ~= math.floor(hearts) then
- advWrite(win,string.char(7),math.ceil(hearts),1,colors.red)
- end
- if math.ceil(hearts) < 10 then
- for i = math.ceil(hearts)+1,10 do
- advWrite(win,string.char(7),i,1,colors.gray)
- end
- end
- advWrite(win,timeString(getTime()-sTime),"r",1,colors.orange)
- end
- end
- end
- if not playerAlive then player = nil end
- if runOnce then runOnce = false end
- end
- end
- function spawn(r,s,m)
- tank.pushFluid(spawners[r][s],8000,"essence")
- spawner = peripheral.wrap(spawners[r][s])
- item = 0
- for slot,_ in pairs(chest.list()) do
- if string.match(chest.getItem(slot).getMetadata().displayName,m) then
- item = slot
- break
- end
- end
- if not (item == 0) then
- spawner.pullItems(chestName,item)
- spawned = false
- while not checkSpawned(m) do
- sleep()
- end
- spawner.pushItems(chestName,7)
- end
- end
- function displayWave()
- currentY = 3
- for mob,count in pairs(mobs) do
- if count > 0 then
- if alive[mob] then live = #alive[mob] else live = 0 end
- for _,m in pairs(queue) do
- if m == mob then live = live + 1 end
- end
- currentY = currentY + 1
- clearLine(win, currentY)
- if string.find(mob,":") then
- mobStr = string.sub(mob,string.find(mob,":")+1,#mob)
- mobStr = string.upper(string.sub(mobStr,1,1))..string.sub(mobStr,2,#mobStr)
- else mobStr = mob end
- advWrite(win,string.format("%s: %s/%s",mobStr,live,count),"c",currentY,colors.orange)
- end
- end
- end
- function trial()
- running = true
- while running and player do
- --initialise next wave
- initWave()
- --reset ring/spawner flag
- cRing = 1
- cSpwner = 0
- --list all mobs in wave on monitor
- currentY = 3
- totalCount = 0
- for mob,count in pairs(mobs) do
- if count > 0 then
- currentY = currentY + 1
- clearLine(win, currentY)
- if string.find(mob,":") then
- mobStr = string.sub(mob,string.find(mob,":")+1,#mob)
- mobStr = string.upper(string.sub(mobStr,1,1))..string.sub(mobStr,2,#mobStr)
- else mobStr = mob end
- advWrite(win,string.format("%s: %s/%s",mobStr,count,count),"c",currentY,colors.orange)
- end
- totalCount = totalCount + count
- end
- --for each mob queued
- while ((#queue > 0) and player) do
- mobQueued = queue[#queue]
- --if ring full
- if cSpwner == #spawners[cRing] then
- --increment ring
- cRing = cRing + 1
- --reset spawner to start
- cSpwner = 1
- else
- --otherwise increment spawner
- cSpwner = cSpwner + 1
- end
- --spawn next mob in queue
- spawn(cRing,cSpwner,mobQueued)
- --check mobs still alive
- checkAlive(totalCount)
- --remove mob from queue
- table.remove(queue,#queue)
- --update monitor display
- displayWave()
- end
- --check alive mobs until none
- while ((not waveOver) and player) do
- waveOver = checkAlive(totalCount)
- displayWave()
- end
- waveOver=false
- waveProg = ""
- if player then
- _,currentY = mon.getCursorPos()
- advWrite(win,"Wave Cleared!","c",currentY+2)
- --if trial still in progress
- if running then
- --pause 5 seconds before next wave
- sleep(5)
- end
- end
- win.clear()
- end
- end
- ----------------------------------------------------
- --==RUNTIME==--
- monitorBorder()
- displayScoreboard()
- while true do
- --wait for chat message event
- evt = {os.pullEvent("chat_message")}
- player = string.sub(evt[2],3)
- checkPlayers(true)
- if ((string.match(string.lower(evt[3]),startPhrase)) and player) then
- playerName = player
- --look through chest
- for slot,item in pairs(chest.list()) do
- --find tape
- if ((item.name == "computronics:tape") and (chest.getItemMeta(slot).media.label == "d&d Battle music (48000)")) then
- --give tape to drive
- chest.pushItems(tape,slot)
- end
- end
- --wait 5 seconds
- sleep(5)
- --start trial if player still present
- checkPlayers(true)
- if player then
- win.clear()
- sTime = getTime()
- parallel.waitForAll(trial,checkPlayers)
- end
- modem.transmit(1,1,"end")
- chest.pullItems(tape,1)
- if player then
- time = getTime() - sTime
- win.clear()
- advWrite(win,"Trial Completed!","c",2)
- advWrite(win,string.format("Time: %s",timeString(time)),"c",3)
- sleep(5)
- scoreExists = false
- for i,v in pairs(scores) do
- if #v == 2 then
- if v[1] == player and time < v[2] then
- table.remove(scores,i)
- elseif v[1] == player then
- scoreExists = true
- end
- end
- end
- if not scoreExists then
- for i,v in pairs(scores) do
- if #v == 2 then
- if v[2] > time then
- table.insert(scores,i,{player,time})
- break
- end
- else
- scores[i] = {player,time}
- break
- end
- end
- if #scores > 5 then
- table.remove(scores,6)
- end
- end
- fs.delete("scores")
- file = fs.open("scores","w")
- file.write(textutils.serialise(scores))
- file.close()
- elseif wave > 0 then
- advWrite(win,string.format("Trial failed by %s!", playerName),"c",2)
- advWrite(win,string.format("Wave Reached: %s", wave),"c",3)
- end
- playerName = nil
- end
- initVars()
- sleep(5)
- win.clear()
- displayScoreboard()
- end
Advertisement
Add Comment
Please, Sign In to add comment