spawner.lua 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. -- mob spawner
  2. local spawner_default = "mobs:pumba 10 15 0"
  3. minetest.register_node("mobs:spawner", {
  4. tiles = {"mob_spawner.png"},
  5. drawtype = "glasslike",
  6. paramtype = "light",
  7. walkable = true,
  8. description = "Mob Spawner",
  9. groups = {cracky = 1},
  10. on_construct = function(pos)
  11. local meta = minetest.get_meta(pos)
  12. -- text entry formspec
  13. meta:set_string("formspec", "field[text;mob_name min_light max_light amount;${command}]")
  14. meta:set_string("infotext", "Spawner Not Active (enter settings)")
  15. meta:set_string("command", spawner_default)
  16. end,
  17. on_right_click = function(pos, placer)
  18. local meta = minetest.get_meta(pos)
  19. end,
  20. on_receive_fields = function(pos, formname, fields, sender)
  21. if not fields.text or fields.text == "" then
  22. return
  23. end
  24. local meta = minetest.get_meta(pos)
  25. local comm = fields.text:split(" ")
  26. local name = sender:get_player_name()
  27. if minetest.is_protected(pos, name) then
  28. minetest.record_protection_violation(pos, name)
  29. return
  30. end
  31. local mob = comm[1]
  32. local mlig = tonumber(comm[2])
  33. local xlig = tonumber(comm[3])
  34. local num = tonumber(comm[4])
  35. if mob and mob ~= ""
  36. and num and num >= 0 and num <= 10
  37. and mlig and mlig >= 0 and mlig <= 15
  38. and xlig and xlig >= 0 and xlig <= 15 then
  39. meta:set_string("command", fields.text)
  40. meta:set_string("infotext", "Spawner Active (" .. mob .. ")")
  41. else
  42. minetest.chat_send_player(name, "Mob Spawner settings failed!")
  43. end
  44. end,
  45. })
  46. -- spawner abm
  47. minetest.register_abm({
  48. nodenames = {"mobs:spawner"},
  49. interval = 10,
  50. chance = 4,
  51. catch_up = false,
  52. action = function(pos, node, active_object_count, active_object_count_wider)
  53. -- check objects inside 9x9 area around spawner
  54. local objs = minetest.get_objects_inside_radius(pos, 9)
  55. -- get meta and command
  56. local meta = minetest.get_meta(pos)
  57. local comm = meta:get_string("command"):split(" ")
  58. -- get settings from command
  59. local mob = comm[1]
  60. local mlig = tonumber(comm[2])
  61. local xlig = tonumber(comm[3])
  62. local num = tonumber(comm[4])
  63. -- if amount is 0 then do nothing
  64. if num == 0 then
  65. return
  66. end
  67. local count = 0
  68. local ent = nil
  69. -- count objects of same type in area
  70. for k, obj in pairs(objs) do
  71. ent = obj:get_luaentity()
  72. if ent and ent.name == mob then
  73. count = count + 1
  74. end
  75. end
  76. -- is there too many of same type?
  77. if count >= num then
  78. return
  79. end
  80. -- find air blocks within 5 nodes of spawner
  81. local air = minetest.find_nodes_in_area(
  82. {x = pos.x - 5, y = pos.y, z = pos.z - 5},
  83. {x = pos.x + 5, y = pos.y, z = pos.z + 5},
  84. {"air"})
  85. -- spawn in random air block
  86. if air and #air > 0 then
  87. local pos2 = air[math.random(#air)]
  88. local lig = minetest.get_node_light(pos2)
  89. pos2.y = pos2.y + 0.5
  90. -- only if light levels are within range
  91. if lig and lig >= mlig and lig <= xlig then
  92. minetest.add_entity(pos2, mob)
  93. end
  94. end
  95. end
  96. })