seek.lua 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. -- Localize for performance.
  2. local math_random = math.random
  3. function pm.seek_flammable_node(self, pos)
  4. local minp = vector.add(pos, {x=-8, y=-8, z=-8})
  5. local maxp = vector.add(pos, {x=8, y=8, z=8})
  6. local positions = minetest.find_nodes_in_area_under_air(minp, maxp, "group:flammable")
  7. if #positions > 0 then
  8. local p2 = positions[math_random(1, #positions)]
  9. if not minetest.test_protection(p2, "") then
  10. return p2, nil
  11. end
  12. end
  13. return nil, nil
  14. end
  15. function pm.seek_player_or_mob_or_item(self, pos)
  16. local all = pm.get_nearby_objects(self, pos, pm.sight_range)
  17. -- Filter out anything that isn't a player or mob or dropped item.
  18. local objects = {}
  19. for i=1, #all, 1 do
  20. if all[i]:is_player() and all[i]:get_hp() > 0 then
  21. if not gdac.player_is_admin(all[i]) then
  22. objects[#objects+1] = all[i]
  23. end
  24. else
  25. local ent = all[i]:get_luaentity()
  26. if ent then
  27. if ent.mob or ent.name == "__builtin:item" then
  28. objects[#objects+1] = all[i]
  29. end
  30. end
  31. end
  32. end
  33. if #objects > 0 then
  34. return nil, objects[math_random(1, #objects)]
  35. end
  36. return nil, nil
  37. end
  38. function pm.seek_player_or_mob(self, pos)
  39. local all = pm.get_nearby_objects(self, pos, pm.sight_range)
  40. -- Filter out anything that isn't a player or mob or dropped item.
  41. local objects = {}
  42. for i=1, #all, 1 do
  43. if all[i]:is_player() and all[i]:get_hp() > 0 then
  44. if not gdac.player_is_admin(all[i]) then
  45. objects[#objects+1] = all[i]
  46. end
  47. else
  48. local ent = all[i]:get_luaentity()
  49. if ent then
  50. if ent.mob then
  51. objects[#objects+1] = all[i]
  52. end
  53. end
  54. end
  55. end
  56. if #objects > 0 then
  57. return nil, objects[math_random(1, #objects)]
  58. end
  59. return nil, nil
  60. end
  61. function pm.seek_player_or_mob_not_wisp(self, pos)
  62. local all = pm.get_nearby_objects(self, pos, pm.sight_range)
  63. -- Filter out anything that isn't a player or mob or dropped item.
  64. local objects = {}
  65. for i=1, #all, 1 do
  66. if all[i]:is_player() and all[i]:get_hp() > 0 then
  67. if not gdac.player_is_admin(all[i]) then
  68. objects[#objects+1] = all[i]
  69. end
  70. else
  71. local ent = all[i]:get_luaentity()
  72. if ent then
  73. if ent.mob then
  74. if ent.name ~= "pm:follower" then
  75. objects[#objects+1] = all[i]
  76. end
  77. end
  78. end
  79. end
  80. end
  81. if #objects > 0 then
  82. return nil, objects[math_random(1, #objects)]
  83. end
  84. return nil, nil
  85. end
  86. function pm.seek_player_or_item(self, pos)
  87. local all = pm.get_nearby_objects(self, pos, pm.sight_range)
  88. -- Filter out anything that isn't a player or mob or dropped item.
  89. local objects = {}
  90. for i=1, #all, 1 do
  91. if all[i]:is_player() and all[i]:get_hp() > 0 then
  92. if not gdac.player_is_admin(all[i]) then
  93. objects[#objects+1] = all[i]
  94. end
  95. else
  96. local ent = all[i]:get_luaentity()
  97. if ent then
  98. if ent.name == "__builtin:item" then
  99. objects[#objects+1] = all[i]
  100. end
  101. end
  102. end
  103. end
  104. if #objects > 0 then
  105. return nil, objects[math_random(1, #objects)]
  106. end
  107. return nil, nil
  108. end
  109. function pm.seek_player(self, pos)
  110. local all = pm.get_nearby_objects(self, pos, pm.sight_range)
  111. -- Filter out anything that isn't a player or mob or dropped item.
  112. local objects = {}
  113. for i=1, #all, 1 do
  114. if all[i]:is_player() and all[i]:get_hp() > 0 then
  115. if not gdac.player_is_admin(all[i]) then
  116. objects[#objects+1] = all[i]
  117. end
  118. end
  119. end
  120. if #objects > 0 then
  121. return nil, objects[math_random(1, #objects)]
  122. end
  123. return nil, nil
  124. end
  125. function pm.seek_node_with_meta(self, pos)
  126. local minp = vector.add(pos, {x=-16, y=-8, z=-16})
  127. local maxp = vector.add(pos, {x=16, y=8, z=16})
  128. local positions = minetest.find_nodes_with_meta(minp, maxp)
  129. if positions then
  130. if #positions > 0 then
  131. local pos = positions[math_random(1, #positions)]
  132. local minp = vector.add(pos, {x=-1, y=-1, z=-1})
  133. local maxp = vector.add(pos, {x=1, y=1, z=1})
  134. local airs = minetest.find_nodes_in_area(minp, maxp, "air")
  135. if airs and #airs > 0 then
  136. return airs[math_random(1, #airs)], nil
  137. end
  138. end
  139. end
  140. return nil, nil
  141. end
  142. function pm.seek_flora(self, pos)
  143. local minp = vector.add(pos, {x=-16, y=-8, z=-16})
  144. local maxp = vector.add(pos, {x=16, y=8, z=16})
  145. local positions = minetest.find_nodes_in_area(minp, maxp, "group:flora")
  146. if positions then
  147. if #positions > 0 then
  148. local pos = positions[math_random(1, #positions)]
  149. local minp = vector.add(pos, {x=-1, y=-1, z=-1})
  150. local maxp = vector.add(pos, {x=1, y=1, z=1})
  151. local airs = minetest.find_nodes_in_area(minp, maxp, "air")
  152. if airs and #airs > 0 then
  153. return airs[math_random(1, #airs)], nil
  154. end
  155. end
  156. end
  157. return nil, nil
  158. end
  159. function pm.seek_wisp(self, pos)
  160. local all = pm.get_nearby_objects(self, pos, pm.sight_range)
  161. -- Filter out anything that isn't a player or mob or dropped item.
  162. local objects = {}
  163. for i=1, #all, 1 do
  164. local ent = all[i]:get_luaentity()
  165. if ent then
  166. if ent.mob and ent._name and ent._name == "pm:follower" then
  167. objects[#objects+1] = all[i]
  168. end
  169. end
  170. end
  171. if #objects > 0 then
  172. local wisp = objects[math_random(1, #objects)]
  173. local p = wisp:get_pos()
  174. p.y = p.y - 3 -- Keep communal wisps from following each other into the sky.
  175. return p, wisp
  176. end
  177. return nil, nil
  178. end
  179. function pm.seek_solitude(self, pos)
  180. local all = pm.get_nearby_objects(self, pos, pm.sight_range)
  181. -- Filter out anything that isn't a player or mob or dropped item.
  182. local objects = {}
  183. for i=1, #all, 1 do
  184. if all[i]:is_player() then
  185. objects[#objects+1] = all[i]
  186. else
  187. local ent = all[i]:get_luaentity()
  188. if ent then
  189. if ent.mob then
  190. objects[#objects+1] = all[i]
  191. end
  192. end
  193. end
  194. end
  195. if #objects > 0 then
  196. -- Calculate average center of the group.
  197. local center = {x=0, y=0, z=0}
  198. for k, v in ipairs(objects) do
  199. local p = v:get_pos()
  200. center.x = center.x + p.x
  201. center.y = center.y + p.y
  202. center.z = center.z + p.z
  203. end
  204. center.x = center.x / #objects
  205. center.y = center.y / #objects
  206. center.z = center.z / #objects
  207. -- Find/return position away from the center of the group.
  208. local dir = vector.subtract(pos, center)
  209. dir = vector.normalize(dir)
  210. dir = vector.multiply(dir, 10)
  211. local air = minetest.find_node_near(vector.add(pos, dir), 11, "air", true)
  212. -- Don't go flying when looking for solitude, stay near ground.
  213. if air then
  214. while minetest.get_node(vector.add(air, {x=0, y=-1, z=0})).name == "air" do
  215. air.y = air.y - 1
  216. end
  217. end
  218. return air, nil
  219. end
  220. return nil, nil
  221. end