foragers.lua 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. local function forager_overview(obj)
  2. local scale = (obj.inv/25) * 3
  3. local formspec =
  4. kobo.unit_inv..
  5. 'textarea[3.25,0;7.5,1;;;Forager]'..
  6. 'image[0,0;3,3;kobo_forager_snap.png]'..
  7. 'textarea[3.25,.75;7.5,2.25;;;Forager state: '..obj.state..'.\n'..
  8. 'Forager inventory: '..obj.inv..' food.]'..
  9. 'image[0,4.5;'..scale..',.25;kobo_inv_fg.png]'
  10. return formspec
  11. end
  12. core.register_entity('kobo:forager', {
  13. initial_properties = {
  14. visual = 'mesh',
  15. mesh = 'kobo_worker.obj',
  16. visual_size = {x=10, y=10},
  17. physical = true,
  18. collide_with_objects = false,
  19. collisionbox = {-.125, -.5, -.125, .125, 0, .125},
  20. textures = {'kobo_forager.png'},
  21. automatic_face_movement_dir = 0.0,
  22. },
  23. on_activate = function(self, staticdata, dtime_s)
  24. local data = core.deserialize(staticdata)
  25. if data then
  26. self.node_timer = data.node_timer
  27. self.owner = data.owner
  28. self.home = data.home
  29. self.state = data.state
  30. self.path = data.path
  31. self.step = data.step
  32. self.inv = data.inv
  33. self.last_job = data.last_job
  34. end
  35. end,
  36. get_staticdata = function(self)
  37. local data ={}
  38. data.node_timer = self.node_timer
  39. data.owner = self.owner
  40. data.home = self.home
  41. data.state = self.state
  42. data.path = self.path
  43. data.step = self.step
  44. data.inv = self.inv
  45. data.last_job = self.last_job
  46. return core.serialize(data)
  47. end,
  48. on_step = function(self, dtime, moveresults)
  49. self.node_timer = (self.node_timer or 0) + dtime
  50. if self.node_timer > 1 then
  51. self.node_timer = 0
  52. if self.state == 'idle' then --Find the lazybones some work.
  53. local last_job = self.last_job
  54. if not last_job then
  55. local self_pos = self.object:get_pos()
  56. local food = core.find_node_near(self_pos, 10, 'group:food')
  57. if food then
  58. local node = core.get_node(self_pos)
  59. local def = core.registered_nodes[node.name]
  60. if def.walkable then
  61. self_pos = vector.add(self_pos, {x=0, y=1, z=0})
  62. end
  63. local path = core.find_path(self_pos, vector.add(food, {x=0, y=1, z=0}), 5, 1, 1)
  64. if path then
  65. self.path = path
  66. self.step = 2
  67. self.state = 'traveling'
  68. else --Make the unit wander around for a while.
  69. self.state = 'idle'
  70. end
  71. else
  72. local buildings = core.find_node_near(self_pos, 10, 'group:storage')
  73. if buildings then
  74. local node = core.get_node(self_pos)
  75. local def = core.registered_nodes[node.name]
  76. if def.walkable then
  77. self_pos = vector.add(self_pos, {x=0, y=1, z=0})
  78. end
  79. local path = core.find_path(self_pos, vector.add(buildings, {x=0, y=1, z=0}), 5, 1, 1)
  80. if path then
  81. self.path = path
  82. self.step = 2
  83. self.state = 'traveling'
  84. end
  85. else --Make the unit wander around for a while.
  86. self.state = 'idle'
  87. end
  88. end
  89. else
  90. local food = core.find_node_near(last_job, 1, 'group:food', true)
  91. if food then
  92. local self_pos = self.object:get_pos()
  93. local node = core.get_node(self_pos)
  94. local def = core.registered_nodes[node.name]
  95. if def.walkable then
  96. self_pos = vector.add(self_pos, {x=0, y=1, z=0})
  97. end
  98. local path = core.find_path(self_pos, vector.add(food, {x=0, y=1, z=0}), 5, 1, 1)
  99. if path then
  100. self.path = path
  101. self.step = 2
  102. self.state = 'traveling'
  103. end
  104. else --Make the unit wander around for a while.
  105. self.last_job = nil
  106. self.state = 'idle'
  107. end
  108. end
  109. elseif self.state == 'traveling' then
  110. if #self.path > (self.step - 1) then
  111. local pos = self.object:get_pos()
  112. local perhaps = vector.direction(pos, self.path[self.step])
  113. self.object:set_velocity({x = perhaps.x, y = 0, z = perhaps.z})
  114. self.step = self.step + 1
  115. else
  116. local self_pos = vector.round(self.object:get_pos())
  117. local food = core.find_node_near(self_pos, 1, 'group:food', true)
  118. if food then
  119. self.object:set_velocity({x=0, y=0, z=0})
  120. self.state = 'working'
  121. self.last_job = food
  122. elseif core.find_node_near(self_pos, 1, 'group:storage', true) then
  123. local resources = kobo.resources[self.owner]
  124. resources.food = resources.food + self.inv
  125. self.inv = 0
  126. local player = core.get_player_by_name(self.owner)
  127. kobo.hud_refresh(player)
  128. self.state = 'idle'
  129. else
  130. self.state = 'idle'
  131. end
  132. end
  133. elseif self.state == 'working' then --Harvesting food!!!
  134. local inventory_count = self.inv
  135. if inventory_count < 25 then
  136. self.inv = self.inv + 1
  137. local pos = self.last_job
  138. local node = core.get_node(pos)
  139. local meta = core.get_meta(pos)
  140. local remaining = meta:get_int('remaining')
  141. if remaining == 0 then
  142. local def = minetest.registered_nodes[node.name]
  143. remaining = def._initial_count
  144. if remaining then
  145. meta:set_int('remaining', remaining - 1)
  146. end
  147. elseif remaining == 1 then
  148. if node.name == 'kobo:bush_food' then
  149. core.swap_node(pos, {name = 'kobo:bush', param2 = node.param2})
  150. local timer = core.get_node_timer(pos)
  151. timer:start(600)
  152. elseif node.name == 'kobo:farm_field' then
  153. core.swap_node(pos, {name = 'kobo:farm_field_empty', param2 = node.param2})
  154. local timer = core.get_node_timer(pos)
  155. timer:start(300)
  156. end
  157. self.state = 'idle'
  158. else
  159. meta:set_int('remaining', remaining - 1)
  160. end
  161. else
  162. local ran_x = math.random(1,10)/10
  163. local ran_z = math.random(1,10)/10
  164. local self_pos = vector.add(self.object:get_pos(), {x=0, y=1, z=0})
  165. local storage_point = core.find_node_near(self_pos, 10, 'group:storage')
  166. if storage_point then
  167. local path = core.find_path(self_pos, vector.add(storage_point, {x=ran_x, y=1, z=ran_z}), 5, 1, 1)
  168. if path then
  169. self.path = path
  170. self.step = 2
  171. self.state = 'traveling'
  172. else --Make the unit wander around for a while.
  173. self.state = 'idle'
  174. end
  175. else
  176. local path = core.find_path(self_pos, vector.add(self.home, {x=ran_x, y=1, z=ran_z}), 5, 1, 1)
  177. if path then
  178. self.path = path
  179. self.step = 2
  180. self.state = 'traveling'
  181. else --Make the unit wander around for a while.
  182. self.state = 'idle'
  183. end
  184. end
  185. end
  186. end
  187. elseif moveresults.collides then
  188. local hit_node = moveresults.collisions[1] and moveresults.collisions[1].type == 'node'
  189. if hit_node then
  190. local node_pos = moveresults.collisions[1].node_pos
  191. local node = core.get_node(node_pos)
  192. if core.get_item_group(node.name, 'storage') > 0 then
  193. local resources = kobo.resources[self.owner]
  194. resources.food = resources.food + self.inv
  195. self.inv = 0
  196. self.state = 'idle'
  197. local player = core.get_player_by_name(self.owner)
  198. kobo.hud_refresh(player)
  199. elseif core.get_item_group(node.name, 'food') > 0 then
  200. local node_pos = moveresults.collisions[1].node_pos
  201. local node = core.get_node(node_pos)
  202. local def = core.registered_nodes[node.name]
  203. local material = def._material
  204. self.object:set_velocity({x=0, y=0, z=0})
  205. self.last_job = node_pos
  206. self.state = 'working'
  207. end
  208. end
  209. end
  210. end,
  211. on_rightclick = function(self, clicker)
  212. local player_name = clicker:get_player_name()
  213. if self.owner == player_name or core.check_player_privs(clicker, {server = true}) then
  214. core.show_formspec(player_name, 'kobo:forager_overview', forager_overview(self))
  215. end
  216. end,
  217. })