Advertisement
skypop

CC Laser sentry

Aug 21st, 2018
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.19 KB | None | 0 0
  1. -- Laser sentry based mob farm
  2. -- by SukaiPoppuGo
  3. --
  4. -- Aim and kill mobs inside a darkroom surrounding mob_spawner
  5. -- Manage lighting to prevent spawn
  6. -- Laser-proof materials : obsidian
  7. -- Laser-proof up to 4.9 potency : mob_spawner, iron_bars, iron_block, emerald_block, diamond_block...
  8. -- Blocks by hardness source : https://minecraft.gamepedia.com/Breaking#Blocks_by_hardness
  9. --
  10. --------------------------------------------------
  11. -- Setup caution:
  12. -- Laser sentry require mob_spawner relative position (from the laser position).
  13. -- Install block scanner module, or create a settings file "mob_spawnerPosition" with each relative coordinates:
  14. -- {
  15. --   mob_spawner.x = number,
  16. --   mob_spawner.y = number,
  17. --   mob_spawner.z = number,
  18. -- }
  19. -- Example:
  20. -- You place the laser in front of mob_spawner with 4 blocks space between.
  21. -- Take place behind the laser, look in direction of mob_spawner and press F3
  22. -- Note the axis indicator. For example :
  23. --   "Facing: south (Towards positive Z)" your setup is {x = 0, y = 0, z = 5}
  24. --   "Facing: west (Towards negative X)" your setup is {x = -5, y = 0, z = 0}
  25. -- If your are not confortable with this procedure, add a block scanner module
  26. -- for an automatic setup. When this settings is saved, you can remove it.
  27. --
  28. -- The author decline all responsability about injuries or grieffing caused by
  29. -- laser beam. You should test your system before in creative mode, then config
  30. -- and setup carefully.
  31. --
  32. --------------------------------------------------
  33. -- inspired/based : https://squiddev-cc.github.io/plethora/examples/laser-sentry.html
  34. -- This program finds hostile mobs and fires lasers at them, acting like a sentry tower.
  35. -- Credit: SquidDev-CC
  36. --
  37.  
  38.  
  39. --------------------------------------------------
  40. --
  41. local SETTINGS_FILE = "mob_spawnerPosition"
  42.  
  43. --------------------------------------------------
  44. -- Display manager
  45. os.loadAPI("api/LaserDisplay.lua")
  46. assert(LaserDisplay, "Require LaserDisplay API\npastebin get zYhzrKEg api/LaserDisplay.lua")
  47.  
  48. --------------------------------------------------
  49. -- init modules
  50. local modules = peripheral.find("manipulator")
  51. if not modules then
  52.     error("Cannot find manipulator", 0)
  53. end
  54. -- We require an entity sensor to find mobs and a laser to shoot at them. We error if neither exists.
  55. if not modules.hasModule("plethora:laser") then error("Cannot find laser", 0) end
  56. if not modules.hasModule("plethora:sensor") then error("Cannot find entity sensor", 0) end
  57.  
  58. --------------------------------------------------
  59. -- Laser potency
  60. -- deal 4 damage / potency
  61. -- mine 1 hardness / potency
  62. local MAX_POTENCY = 4.9 -- Maximum potency (mob_spawner hardeness = 5)
  63. local MIN_POTENCY = 0.5 -- Minimum potency
  64. local MIN_POTENCY_RECOVERY = 0.2 --delay in seconds
  65.  
  66. local DEBUG_MODE = false
  67.  
  68. --------------------------------------------------
  69. -- Config mob_spawner relative position
  70. os.loadAPI("api/LaserConfig.lua")
  71. assert(LaserConfig, "Require LaserConfig API\npastebin get GJhqHVcX api/LaserConfig.lua")
  72. LaserConfig.file.set(SETTINGS_FILE)
  73. local mob_spawner = LaserConfig.init()
  74.  
  75. --------------------------------------------------
  76. -- Avoid to shoot outside this range
  77. -- Example for mob_spawner = {x = 0, y = 0, z = 5}
  78. --local RANGE_RESTRICT = {
  79. --  x1 =  5, y1 =  2, z1 = 10,
  80. --  x2 = -4, y2 = -4, z2 =  1,
  81. --}
  82. --
  83. local RANGE_RESTRICT = {
  84.     x1 = mob_spawner.x+5, y1 = mob_spawner.y+2, z1 = mob_spawner.z+5,
  85.     x2 = mob_spawner.x-4, y2 = mob_spawner.y-4, z2 = mob_spawner.z-4,
  86. }
  87.  
  88.  
  89. --------------------------------------------------
  90. -- Init Entity whitelist
  91. local entityWhitelist = settings.get("mob_spawner.whiteList", false)
  92. if not entityWhitelist then
  93.     entityWhitelist = LaserConfig.getWhiteList()
  94. end
  95. entityWhitelist["SukaiPoppuGo"] = false --safety first
  96.  
  97.  
  98. --------------------------------------------------
  99. -- Max/Min range of mob positions
  100. local stats = {
  101.     maxX = 0, minX = math.huge,
  102.     maxY = 0, minY = math.huge,
  103.     maxZ = 0, minZ = math.huge,
  104. }
  105.  
  106. --------------------------------------------------
  107. -- function stats.update
  108. -- Update Max/Min range of mob positions
  109. --
  110. -- param number x   Current mob X position
  111. -- param number y   Current mob Y position
  112. -- param number z   Current mob Z position
  113. function stats.update(x,y,z)
  114.     LaserDisplay.status("stats.update")
  115.     stats.maxX = math.max(x, stats.maxX)
  116.     stats.minX = math.min(x, stats.minX)
  117.     stats.maxY = math.max(y, stats.maxY)
  118.     stats.minY = math.min(y, stats.minY)
  119.     stats.maxZ = math.max(z, stats.maxZ)
  120.     stats.minZ = math.min(z, stats.minZ)
  121. end
  122.  
  123. --------------------------------------------------
  124. -- function lights
  125. -- Redstone Mgr
  126. --
  127. -- param boolean    state   (opt) True set lights On, False set lights Off, nil toggle lights
  128. local function lights(state)
  129.     LaserDisplay.status("lights")
  130.     state = state or not rs.getOutput("bottom")
  131.     rs.setOutput("left",  state)
  132.     rs.setOutput("right", state)
  133.     rs.setOutput("bottom", state)
  134.     rs.setOutput("top", true)
  135. end
  136. -- init
  137. lights(true)
  138.  
  139.  
  140. --------------------------------------------------
  141. -- Display group
  142. -- window
  143. --
  144.  
  145. function update()
  146.     LaserDisplay.status("update")
  147.     LaserDisplay.range(stats.maxX, stats.minX, stats.maxY, stats.minY, stats.maxZ, stats.minZ)
  148.     LaserDisplay.update()
  149. end
  150.  
  151.  
  152. --------------------------------------------------
  153. -- function keyTip
  154. -- Formate tips about keys functionality
  155. --
  156. -- param number k   Key code from keys table
  157. -- param string tip Information for users
  158. -- return string    Formated information
  159. local function keyTip(k, tip)
  160.     local sK = string.len(keys.getName(k)) > 1 and keys.getName(k) or string.upper(keys.getName(k))
  161.     return string.format("press [%s] %s", sK, tip)
  162. end
  163.  
  164. --------------------------------------------------
  165. -- Action group for user
  166. local action = {}
  167.  
  168.  
  169. --------------------------------------------------
  170. -- function action.toggleLights
  171. -- turn On / shutdown lights
  172. function action.toggleLights()
  173.     LaserDisplay.status("toggleLights")
  174.     lights()
  175. end
  176.  
  177.  
  178. --------------------------------------------------
  179. -- function action.toggleLaser
  180. -- enable/disable Laser
  181. local laserState = false
  182. function action.toggleLaser()
  183.     LaserDisplay.status("toggleLaser")
  184.     laserState = not laserState
  185. end
  186.  
  187. --------------------------------------------------
  188. -- function control
  189. -- Restore control inputs between delay
  190. --
  191. -- param: duration  number  delay length in seconds
  192. local function control(duration)
  193.     LaserDisplay.status("control")
  194.     local delay = os.startTimer(duration)
  195.     repeat
  196.         local e = {os.pullEvent()}
  197.         if e[1] == "mouse_click" and e[2] == 1 and e[4] == 1 then
  198.             lights()
  199.             LaserDisplay.header("Toggle lights")
  200.         elseif not term.isColor() and e[1] == "key" then
  201.             local _,k = os.pullEvent("key_up")
  202.             if e[2] == k then
  203.                
  204.             end
  205.         end
  206.     until e[1] == "timer" and e[2] == delay
  207. end
  208.  
  209. --------------------------------------------------
  210. -- function fire
  211. -- Perform a shoot
  212. --
  213. -- We define a function which fires a laser towards an entity. This is a very naive implementation
  214. -- as it does not account for the entity moving between firing and impact.
  215. -- You could use the motionX, motionY and motionZ fields if you wish to add such functionality.
  216. -- CFG: damage=4 The damage done to an entity for each potency.
  217. --
  218. -- x, y, z  number  Relative position
  219. -- param: potency   number
  220. local function fire(x, y, z, potency)
  221.     LaserDisplay.status("fire")
  222.     local pitch = -math.atan2(y, math.sqrt(x * x + z * z))
  223.     local yaw = math.atan2(-x, z)
  224.     modules.fire(math.deg(yaw), math.deg(pitch), potency)
  225. end
  226.  
  227. --------------------------------------------------
  228. -- function inRange
  229. -- Range restrictions
  230. --
  231. -- param x number   Relative position X
  232. -- param y number   Relative position Y
  233. -- param z number   Relative position Z
  234. -- return boolean   Coordinate are inside LaserDisplay.range
  235. local function inRange(x,y,z)
  236.     LaserDisplay.status("inRange")
  237.     if x >= -1 and x <= 1 and z >= -1 and z <= 1 then
  238.         return false, false, false -- secure computer
  239.     end
  240.     local r = RANGE_RESTRICT
  241.     local _x = (x >= math.min(r.x1, r.x2) and x <= math.max(r.x1, r.x2))
  242.     local _y = (y >= math.min(r.y1, r.y2) and y <= math.max(r.y1, r.y2))
  243.     local _z = (z >= math.min(r.z1, r.z2) and z <= math.max(r.z1, r.z2))
  244.     if DEBUG_MODE and not(_x and _y and _z) then --debug
  245.         LaserDisplay.output.print(tostring(_x), ":", x, ">=", math.min(r.x1, r.x2), "and <=", math.max(r.x1, r.x2))
  246.         LaserDisplay.output.print(tostring(_y), ":", y, ">=", math.min(r.y1, r.y2), "and <=", math.max(r.y1, r.y2))
  247.         LaserDisplay.output.print(tostring(_z), ":", z, ">=", math.min(r.z1, r.z2), "and <=", math.max(r.z1, r.z2))
  248.         LaserDisplay.output.print("-Press any key-")
  249.         os.pullEvent("key") os.pullEvent("key_up")
  250.     end
  251.     return _x and _y and _z
  252. end
  253.  
  254. --------------------------------------------------
  255. -- function fireInRange
  256. -- Manage Firing in good conditions
  257. -- Perform cooldown delay and LaserDisplay.output informations
  258. --
  259. -- param  entity    table   Item result from modules.sense()
  260. -- return boolean   fired   A shoot sequence were done
  261. local function fireInRange(entity)
  262.     LaserDisplay.status("fireInRange")
  263.     --init
  264.     local fired = false
  265.     local mob = modules.getMetaByID(entity.id)
  266.    
  267.     -- Mob is alive
  268.     if mob and mob.health and mob.health > 0 then
  269.         --Fire sequence to death
  270.         while mob and mob.health and mob.health > 0 do
  271.             -- Precise coordinates
  272.             local x = mob.x + (mob.motionX or 0)
  273.             local y = mob.y + (mob.motionY or 0)
  274.             local z = mob.z + (mob.motionZ or 0)
  275.             -- Max range statistics
  276.             stats.update(x,y,z)
  277.            
  278.             -- Target in range
  279.             if inRange(x,y,z) then
  280.                
  281.                 local potency = math.min(MAX_POTENCY, math.max(MIN_POTENCY, math.ceil(mob.health*10/4)/10))
  282.                 local delay = math.max(potency * .1 + .1, MIN_POTENCY_RECOVERY)
  283.                 -- Display
  284.                 LaserDisplay.output.print(
  285.                     "--\nFire mob at X:", math.floor(x*10+5)/10,
  286.                     "Y:", math.floor(y*10+5)/10,
  287.                     "Z:",math.floor(z*10+5)/10,
  288.                     "\n",
  289.                     "heatlh:", math.floor(mob.health*10+5)/10,
  290.                     "potency:", potency,
  291.                     "delay:", delay
  292.                 )
  293.                 --FIRE!
  294.                 fire(x, y, z, potency)
  295.                 fired = true
  296.                 --Delay
  297.                 control(delay)
  298.            
  299.             -- Out of range
  300.             else
  301.                 -- Display
  302.                 LaserDisplay.output.print(
  303.                     "--\nMob at X:", math.floor(x*10+5)/10,
  304.                     "Y:", math.floor(y*10+5)/10,
  305.                     "Z:",math.floor(z*10+5)/10
  306.                 )
  307.                 LaserDisplay.output.printError("Out of range")
  308.                 break
  309.             end
  310.            
  311.             -- refresh mob datas
  312.             mob = modules.getMetaByID(entity.id)
  313.         end
  314.    
  315.     -- Mob is dead
  316.     else
  317.         -- Display
  318.         LaserDisplay.output.print(
  319.             "--\nMob at X:", math.floor(x*10+5)/10,
  320.             "Y:", math.floor(y*10+5)/10,
  321.             "Z:",math.floor(z*10+5)/10
  322.         )
  323.         LaserDisplay.output.printError("Is already dead")
  324.     end
  325.     return fired
  326. end
  327.  
  328. --------------------------------------------------
  329. -- Main
  330. term.setCursorPos(1,2)
  331. term.clear()
  332. LaserDisplay.init()
  333. LaserDisplay.status("ready")
  334. while true do
  335.     --Update display
  336.     update()
  337.     --Check lighting
  338.     if rs.getOutput("bottom") then
  339.         LaserDisplay.header("Laser off")
  340.     else
  341.         LaserDisplay.header("Laser on")
  342.         -- List entities
  343.         local mobs = modules.sense()
  344.        
  345.         -- Fire first target
  346.         local fired = false
  347.         for i = 1, #mobs do
  348.             local mob = mobs[i]
  349.             if mob and entityWhitelist[mob.name] and mob.id then
  350.                 fired = fireInRange(mob)
  351.                 if fired then break end
  352.             end
  353.         end
  354.     end
  355.     control(1)
  356. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement