Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Laser sentry based mob farm
- -- by SukaiPoppuGo
- --
- -- Aim and kill mobs inside a darkroom surrounding mob_spawner
- -- Manage lighting to prevent spawn
- -- Laser-proof materials : obsidian
- -- Laser-proof up to 4.9 potency : mob_spawner, iron_bars, iron_block, emerald_block, diamond_block...
- -- Blocks by hardness source : https://minecraft.gamepedia.com/Breaking#Blocks_by_hardness
- --
- --------------------------------------------------
- -- Setup caution:
- -- Laser sentry require mob_spawner relative position (from the laser position).
- -- Install block scanner module, or create a settings file "mob_spawnerPosition" with each relative coordinates:
- -- {
- -- mob_spawner.x = number,
- -- mob_spawner.y = number,
- -- mob_spawner.z = number,
- -- }
- -- Example:
- -- You place the laser in front of mob_spawner with 4 blocks space between.
- -- Take place behind the laser, look in direction of mob_spawner and press F3
- -- Note the axis indicator. For example :
- -- "Facing: south (Towards positive Z)" your setup is {x = 0, y = 0, z = 5}
- -- "Facing: west (Towards negative X)" your setup is {x = -5, y = 0, z = 0}
- -- If your are not confortable with this procedure, add a block scanner module
- -- for an automatic setup. When this settings is saved, you can remove it.
- --
- -- The author decline all responsability about injuries or grieffing caused by
- -- laser beam. You should test your system before in creative mode, then config
- -- and setup carefully.
- --
- --------------------------------------------------
- -- inspired/based : https://squiddev-cc.github.io/plethora/examples/laser-sentry.html
- -- This program finds hostile mobs and fires lasers at them, acting like a sentry tower.
- -- Credit: SquidDev-CC
- --
- --------------------------------------------------
- --
- local SETTINGS_FILE = "mob_spawnerPosition"
- --------------------------------------------------
- -- Display manager
- os.loadAPI("api/LaserDisplay.lua")
- assert(LaserDisplay, "Require LaserDisplay API\npastebin get zYhzrKEg api/LaserDisplay.lua")
- --------------------------------------------------
- -- init modules
- local modules = peripheral.find("manipulator")
- if not modules then
- error("Cannot find manipulator", 0)
- end
- -- We require an entity sensor to find mobs and a laser to shoot at them. We error if neither exists.
- if not modules.hasModule("plethora:laser") then error("Cannot find laser", 0) end
- if not modules.hasModule("plethora:sensor") then error("Cannot find entity sensor", 0) end
- --------------------------------------------------
- -- Laser potency
- -- deal 4 damage / potency
- -- mine 1 hardness / potency
- local MAX_POTENCY = 4.9 -- Maximum potency (mob_spawner hardeness = 5)
- local MIN_POTENCY = 0.5 -- Minimum potency
- local MIN_POTENCY_RECOVERY = 0.2 --delay in seconds
- local DEBUG_MODE = false
- --------------------------------------------------
- -- Config mob_spawner relative position
- os.loadAPI("api/LaserConfig.lua")
- assert(LaserConfig, "Require LaserConfig API\npastebin get GJhqHVcX api/LaserConfig.lua")
- LaserConfig.file.set(SETTINGS_FILE)
- local mob_spawner = LaserConfig.init()
- --------------------------------------------------
- -- Avoid to shoot outside this range
- -- Example for mob_spawner = {x = 0, y = 0, z = 5}
- --local RANGE_RESTRICT = {
- -- x1 = 5, y1 = 2, z1 = 10,
- -- x2 = -4, y2 = -4, z2 = 1,
- --}
- --
- local RANGE_RESTRICT = {
- x1 = mob_spawner.x+5, y1 = mob_spawner.y+2, z1 = mob_spawner.z+5,
- x2 = mob_spawner.x-4, y2 = mob_spawner.y-4, z2 = mob_spawner.z-4,
- }
- --------------------------------------------------
- -- Init Entity whitelist
- local entityWhitelist = settings.get("mob_spawner.whiteList", false)
- if not entityWhitelist then
- entityWhitelist = LaserConfig.getWhiteList()
- end
- entityWhitelist["SukaiPoppuGo"] = false --safety first
- --------------------------------------------------
- -- Max/Min range of mob positions
- local stats = {
- maxX = 0, minX = math.huge,
- maxY = 0, minY = math.huge,
- maxZ = 0, minZ = math.huge,
- }
- --------------------------------------------------
- -- function stats.update
- -- Update Max/Min range of mob positions
- --
- -- param number x Current mob X position
- -- param number y Current mob Y position
- -- param number z Current mob Z position
- function stats.update(x,y,z)
- LaserDisplay.status("stats.update")
- stats.maxX = math.max(x, stats.maxX)
- stats.minX = math.min(x, stats.minX)
- stats.maxY = math.max(y, stats.maxY)
- stats.minY = math.min(y, stats.minY)
- stats.maxZ = math.max(z, stats.maxZ)
- stats.minZ = math.min(z, stats.minZ)
- end
- --------------------------------------------------
- -- function lights
- -- Redstone Mgr
- --
- -- param boolean state (opt) True set lights On, False set lights Off, nil toggle lights
- local function lights(state)
- LaserDisplay.status("lights")
- state = state or not rs.getOutput("bottom")
- rs.setOutput("left", state)
- rs.setOutput("right", state)
- rs.setOutput("bottom", state)
- rs.setOutput("top", true)
- end
- -- init
- lights(true)
- --------------------------------------------------
- -- Display group
- -- window
- --
- function update()
- LaserDisplay.status("update")
- LaserDisplay.range(stats.maxX, stats.minX, stats.maxY, stats.minY, stats.maxZ, stats.minZ)
- LaserDisplay.update()
- end
- --------------------------------------------------
- -- function keyTip
- -- Formate tips about keys functionality
- --
- -- param number k Key code from keys table
- -- param string tip Information for users
- -- return string Formated information
- local function keyTip(k, tip)
- local sK = string.len(keys.getName(k)) > 1 and keys.getName(k) or string.upper(keys.getName(k))
- return string.format("press [%s] %s", sK, tip)
- end
- --------------------------------------------------
- -- Action group for user
- local action = {}
- --------------------------------------------------
- -- function action.toggleLights
- -- turn On / shutdown lights
- function action.toggleLights()
- LaserDisplay.status("toggleLights")
- lights()
- end
- --------------------------------------------------
- -- function action.toggleLaser
- -- enable/disable Laser
- local laserState = false
- function action.toggleLaser()
- LaserDisplay.status("toggleLaser")
- laserState = not laserState
- end
- --------------------------------------------------
- -- function control
- -- Restore control inputs between delay
- --
- -- param: duration number delay length in seconds
- local function control(duration)
- LaserDisplay.status("control")
- local delay = os.startTimer(duration)
- repeat
- local e = {os.pullEvent()}
- if e[1] == "mouse_click" and e[2] == 1 and e[4] == 1 then
- lights()
- LaserDisplay.header("Toggle lights")
- elseif not term.isColor() and e[1] == "key" then
- local _,k = os.pullEvent("key_up")
- if e[2] == k then
- end
- end
- until e[1] == "timer" and e[2] == delay
- end
- --------------------------------------------------
- -- function fire
- -- Perform a shoot
- --
- -- We define a function which fires a laser towards an entity. This is a very naive implementation
- -- as it does not account for the entity moving between firing and impact.
- -- You could use the motionX, motionY and motionZ fields if you wish to add such functionality.
- -- CFG: damage=4 The damage done to an entity for each potency.
- --
- -- x, y, z number Relative position
- -- param: potency number
- local function fire(x, y, z, potency)
- LaserDisplay.status("fire")
- local pitch = -math.atan2(y, math.sqrt(x * x + z * z))
- local yaw = math.atan2(-x, z)
- modules.fire(math.deg(yaw), math.deg(pitch), potency)
- end
- --------------------------------------------------
- -- function inRange
- -- Range restrictions
- --
- -- param x number Relative position X
- -- param y number Relative position Y
- -- param z number Relative position Z
- -- return boolean Coordinate are inside LaserDisplay.range
- local function inRange(x,y,z)
- LaserDisplay.status("inRange")
- if x >= -1 and x <= 1 and z >= -1 and z <= 1 then
- return false, false, false -- secure computer
- end
- local r = RANGE_RESTRICT
- local _x = (x >= math.min(r.x1, r.x2) and x <= math.max(r.x1, r.x2))
- local _y = (y >= math.min(r.y1, r.y2) and y <= math.max(r.y1, r.y2))
- local _z = (z >= math.min(r.z1, r.z2) and z <= math.max(r.z1, r.z2))
- if DEBUG_MODE and not(_x and _y and _z) then --debug
- LaserDisplay.output.print(tostring(_x), ":", x, ">=", math.min(r.x1, r.x2), "and <=", math.max(r.x1, r.x2))
- LaserDisplay.output.print(tostring(_y), ":", y, ">=", math.min(r.y1, r.y2), "and <=", math.max(r.y1, r.y2))
- LaserDisplay.output.print(tostring(_z), ":", z, ">=", math.min(r.z1, r.z2), "and <=", math.max(r.z1, r.z2))
- LaserDisplay.output.print("-Press any key-")
- os.pullEvent("key") os.pullEvent("key_up")
- end
- return _x and _y and _z
- end
- --------------------------------------------------
- -- function fireInRange
- -- Manage Firing in good conditions
- -- Perform cooldown delay and LaserDisplay.output informations
- --
- -- param entity table Item result from modules.sense()
- -- return boolean fired A shoot sequence were done
- local function fireInRange(entity)
- LaserDisplay.status("fireInRange")
- --init
- local fired = false
- local mob = modules.getMetaByID(entity.id)
- -- Mob is alive
- if mob and mob.health and mob.health > 0 then
- --Fire sequence to death
- while mob and mob.health and mob.health > 0 do
- -- Precise coordinates
- local x = mob.x + (mob.motionX or 0)
- local y = mob.y + (mob.motionY or 0)
- local z = mob.z + (mob.motionZ or 0)
- -- Max range statistics
- stats.update(x,y,z)
- -- Target in range
- if inRange(x,y,z) then
- local potency = math.min(MAX_POTENCY, math.max(MIN_POTENCY, math.ceil(mob.health*10/4)/10))
- local delay = math.max(potency * .1 + .1, MIN_POTENCY_RECOVERY)
- -- Display
- LaserDisplay.output.print(
- "--\nFire mob at X:", math.floor(x*10+5)/10,
- "Y:", math.floor(y*10+5)/10,
- "Z:",math.floor(z*10+5)/10,
- "\n",
- "heatlh:", math.floor(mob.health*10+5)/10,
- "potency:", potency,
- "delay:", delay
- )
- --FIRE!
- fire(x, y, z, potency)
- fired = true
- --Delay
- control(delay)
- -- Out of range
- else
- -- Display
- LaserDisplay.output.print(
- "--\nMob at X:", math.floor(x*10+5)/10,
- "Y:", math.floor(y*10+5)/10,
- "Z:",math.floor(z*10+5)/10
- )
- LaserDisplay.output.printError("Out of range")
- break
- end
- -- refresh mob datas
- mob = modules.getMetaByID(entity.id)
- end
- -- Mob is dead
- else
- -- Display
- LaserDisplay.output.print(
- "--\nMob at X:", math.floor(x*10+5)/10,
- "Y:", math.floor(y*10+5)/10,
- "Z:",math.floor(z*10+5)/10
- )
- LaserDisplay.output.printError("Is already dead")
- end
- return fired
- end
- --------------------------------------------------
- -- Main
- term.setCursorPos(1,2)
- term.clear()
- LaserDisplay.init()
- LaserDisplay.status("ready")
- while true do
- --Update display
- update()
- --Check lighting
- if rs.getOutput("bottom") then
- LaserDisplay.header("Laser off")
- else
- LaserDisplay.header("Laser on")
- -- List entities
- local mobs = modules.sense()
- -- Fire first target
- local fired = false
- for i = 1, #mobs do
- local mob = mobs[i]
- if mob and entityWhitelist[mob.name] and mob.id then
- fired = fireInRange(mob)
- if fired then break end
- end
- end
- end
- control(1)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement