init.lua 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. local textures =
  2. {
  3. "eg_goats_torso.png", --torso
  4. "eg_goats_leg.png", --legs
  5. "eg_goats_head.png", --head
  6. "eg_goats_mouth.png", --mouth
  7. "blank.png", --unihorn
  8. "eg_goats_horns.png", --horns
  9. }
  10. local function hq_follow_until_near(self, prty, tgtobj)
  11. local tgtpos = tgtobj:get_pos()
  12. local func = function()
  13. if mobkit.timer(self, 0.5)
  14. then
  15. if not mobkit.exists(tgtobj)
  16. then
  17. return true
  18. end
  19. tgtpos = tgtobj:get_pos()
  20. if vector.distance(self.object:get_pos(), tgtpos) < 5
  21. then
  22. return true
  23. end
  24. end
  25. if mobkit.is_queue_empty_low(self) and self.isonground
  26. then
  27. eg_moblib.goto_next_waypoint(self, tgtpos, 0.3)
  28. end
  29. end
  30. mobkit.queue_high(self, func, prty)
  31. end
  32. local function hq_gather(self, prty, attempts)
  33. local follow
  34. local func = function()
  35. if mobkit.timer(self, 2)
  36. then
  37. if not mobkit.exists(follow)
  38. then
  39. follow = mobkit.get_nearby_entity(self, self.name)
  40. return
  41. end
  42. hq_follow_until_near(self, prty + 1, follow)
  43. attempts = attempts - 1
  44. end
  45. return attempts < 1
  46. end
  47. mobkit.queue_high(self, func, prty)
  48. end
  49. local function defend(self)
  50. --get two random nearby players and select the worse one
  51. local nearbies = {mobkit.get_nearby_player(self), mobkit.get_nearby_player(self)}
  52. local badness = 0
  53. local worse
  54. for i, nearby in ipairs(nearbies)
  55. do
  56. local new_badness = self.enemy[nearby:get_player_name()]
  57. if new_badness and new_badness > badness
  58. then
  59. badness = new_badness
  60. worse = nearby
  61. end
  62. end
  63. if worse
  64. then
  65. if badness < 2
  66. then
  67. --forgive
  68. return
  69. elseif badness < self.hp * 1.5 --TODO: fine tune
  70. then
  71. --attack
  72. mobkit.hq_hunt(self, 20, worse)
  73. else
  74. --run
  75. mobkit.clear_queue_high(self)
  76. mobkit.clear_queue_low(self)
  77. mobkit.hq_runfrom(self, 21, worse)
  78. end
  79. end
  80. end
  81. local function lq_sleep(self, time)
  82. mobkit.animate(self, "sleep")
  83. local func = function()
  84. if mobkit.timer(self, 3) and math.random(5) == 1
  85. then
  86. mobkit.heal(self, 1)
  87. mobkit.make_sound(self, "snore")
  88. if math.random(5) == 1
  89. then
  90. --slowly forgive enemies
  91. for k, v in pairs(self.enemy)
  92. do
  93. v = v - 1
  94. self.enemy[k] = v > 0 and v or nil
  95. end
  96. end
  97. end
  98. if math.random(10) == 1
  99. then
  100. defend(self)
  101. end
  102. time = time - self.dtime
  103. return time <= 0
  104. end
  105. mobkit.queue_low(self, func)
  106. end
  107. local function is_day()
  108. local tod = minetest.get_timeofday()
  109. return tod > 0.25 and tod < 0.75
  110. end
  111. local function hq_sleep(self, prty)
  112. hq_gather(self, prty + 1, 5)
  113. local func = function()
  114. if mobkit.is_queue_empty_low(self)
  115. then
  116. lq_sleep(self, 3)
  117. return is_day()
  118. end
  119. end
  120. mobkit.queue_high(self, func, prty)
  121. end
  122. local function hq_eat(self, prty)
  123. local func = function()
  124. --TODO
  125. end
  126. mobkit.queue_high(self, func, prty)
  127. end
  128. local function alert_danger(self, attacker, damage)
  129. for i, obj in ipairs(self.nearby_objects)
  130. do
  131. local luae = obj:get_luaentity()
  132. if luae and luae.name == self.name
  133. then
  134. if attacker:is_player()
  135. then
  136. local name = attacker:get_player_name()
  137. luae.enemy[name] = (luae.enemy[name] or 0) + damage
  138. defend(luae)
  139. end
  140. end
  141. end
  142. end
  143. minetest.register_entity("eg_goats:goat",
  144. {
  145. initial_properties =
  146. {
  147. physical = true,
  148. collide_with_objects = true,
  149. collisionbox = {-0.3, 0, -0.3, 0.3, 1, 0.3},
  150. visual = "mesh",
  151. mesh = "eg_goats_goat.b3d",
  152. backface_culling = false,
  153. },
  154. timeout = 0,
  155. buoyancy = 0.5,
  156. lung_capacity = 5, --more than 5 is a waste after all
  157. max_hp = 30,
  158. on_step = mobkit.stepfunc,
  159. on_activate = function(self, staticdata, dtime_s)
  160. mobkit.actfunc(self, staticdata, dtime_s)
  161. --set textures
  162. local props = self.object:get_properties()
  163. props.textures = textures
  164. self.object:set_properties(props)
  165. --load enemy table and set it to be saved again
  166. self.enemy = mobkit.recall(self, "enemy") or {}
  167. mobkit.remember(self, "enemy", self.enemy)
  168. --start doing something
  169. if is_day()
  170. then
  171. mobkit.hq_roam(self, 1)
  172. else
  173. hq_sleep(self, 10)
  174. end
  175. end,
  176. get_staticdata = mobkit.statfunc,
  177. logic = function(self)
  178. if not mobkit.is_alive(self)
  179. then
  180. mobkit.clear_queue_high(self)
  181. mobkit.clear_queue_low(self)
  182. mobkit.hq_die(self, 100)
  183. return
  184. end
  185. if mobkit.timer(self, 1)
  186. then
  187. local prty = mobkit.get_queue_priority(self)
  188. if self.isinliquid and prty < 30
  189. then
  190. mobkit.hq_liquid_recovery(self, 30)
  191. end
  192. if is_day()
  193. then
  194. if prty < 20
  195. then
  196. defend(self)
  197. end
  198. if mobkit.is_queue_empty_high(self)
  199. then
  200. mobkit.hq_roam(self, 1)
  201. end
  202. else
  203. if prty < 10
  204. then
  205. hq_sleep(self, 10)
  206. end
  207. end
  208. end
  209. end,
  210. on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
  211. local hvel = vector.multiply(vector.normalize({x=dir.x,y=0,z=dir.z}),4)
  212. self.object:set_velocity({x=hvel.x,y=2,z=hvel.z})
  213. local dmg = tool_capabilities.damage_groups.fleshy or 1
  214. mobkit.hurt(self, dmg)
  215. if mobkit.is_alive(self)
  216. then
  217. if puncher:is_player()
  218. then
  219. local name = puncher:get_player_name()
  220. self.enemy[name] = (self.enemy[name] or 0) + dmg
  221. defend(self)
  222. end
  223. alert_danger(self, puncher, dmg)
  224. mobkit.make_sound(self, "hurt")
  225. end
  226. end,
  227. --TODO: animation
  228. --TODO: sounds
  229. max_speed = 12,
  230. jump_height = 2,
  231. view_range = 30,
  232. attack =
  233. {
  234. range = 1,
  235. damage_groups = {fleshy = 4},
  236. },
  237. armor_groups = {fleshy = 4},
  238. })