spider.lua 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. local S = mobs.intllib
  2. local get_velocity = function(self)
  3. local v = self.object:get_velocity()
  4. -- sanity check
  5. if not v then return 0 end
  6. return (v.x * v.x + v.z * v.z) ^ 0.5
  7. end
  8. local spider_types = {
  9. { nodes = {"default:snow", "default:snowblock", "default:dirt_with_snow"},
  10. skins = {"mobs_spider_snowy.png"},
  11. docile = true,
  12. drops = nil
  13. },
  14. { nodes = {"default:dirt_with_rainforest_litter", "default:jungletree"},
  15. skins = {"mobs_spider_orange.png"},
  16. docile = true,
  17. drops = nil,
  18. shoot = true
  19. },
  20. { nodes = {"default:stone", "default:gravel"},
  21. skins = {"mobs_spider_grey.png"},
  22. docile = nil,
  23. drops = nil,
  24. small = true
  25. },
  26. { nodes = {"default:mese", "default:stone_with_mese"},
  27. skins = {"mobs_spider_mese.png"},
  28. docile = nil,
  29. drops = {
  30. {name = "farming:string", chance = 1, min = 0, max = 2},
  31. {name = "default:mese_crystal_fragment", chance = 2, min = 1, max = 4}}
  32. },
  33. { nodes = {"ethereal:crystal_dirt", "ethereal:crystal_spike"},
  34. skins = {"mobs_spider_crystal.png"},
  35. docile = true,
  36. drops = {
  37. {name = "farming:string", chance = 1, min = 0, max = 2},
  38. {name = "ethereal:crystal_spike", chance = 15, min = 1, max = 2}}
  39. }
  40. }
  41. -- Spider by AspireMint (CC-BY-SA 3.0 license)
  42. mobs:register_mob("mobs_monster:spider", {
  43. --docile_by_day = true,
  44. group_attack = true,
  45. type = "monster",
  46. passive = false,
  47. attack_type = "dogfight",
  48. reach = 2,
  49. damage = 3,
  50. hp_min = 10,
  51. hp_max = 30,
  52. armor = 200,
  53. collisionbox = {-0.8, -0.5, -0.8, 0.8, 0, 0.8},
  54. visual_size = {x = 1, y = 1},
  55. visual = "mesh",
  56. mesh = "mobs_spider.b3d",
  57. textures = {
  58. {"mobs_spider_mese.png"},
  59. {"mobs_spider_orange.png"},
  60. {"mobs_spider_snowy.png"},
  61. {"mobs_spider_grey.png"},
  62. {"mobs_spider_crystal.png"},
  63. },
  64. makes_footstep_sound = false,
  65. sounds = {
  66. random = "mobs_spider",
  67. attack = "mobs_spider",
  68. },
  69. walk_velocity = 1,
  70. run_velocity = 3,
  71. jump = true,
  72. view_range = 15,
  73. floats = 0,
  74. drops = {
  75. {name = "farming:string", chance = 1, min = 0, max = 2},
  76. },
  77. water_damage = 5,
  78. lava_damage = 5,
  79. light_damage = 0,
  80. animation = {
  81. speed_normal = 15,
  82. speed_run = 20,
  83. stand_start = 0,
  84. stand_end = 0,
  85. walk_start = 1,
  86. walk_end = 21,
  87. run_start = 1,
  88. run_end = 21,
  89. punch_start = 25,
  90. punch_end = 45,
  91. },
  92. -- check surrounding nodes and spawn a specific spider
  93. on_spawn = function(self)
  94. local pos = self.object:get_pos() ; pos.y = pos.y - 1
  95. local tmp
  96. for n = 1, #spider_types do
  97. tmp = spider_types[n]
  98. if minetest.find_node_near(pos, 1, tmp.nodes) then
  99. self.base_texture = tmp.skins
  100. self.object:set_properties({textures = tmp.skins})
  101. self.docile_by_day = tmp.docile
  102. if tmp.drops then
  103. self.drops = tmp.drops
  104. end
  105. if tmp.shoot then
  106. self.attack_type = "dogshoot"
  107. self.arrow = "mobs_monster:cobweb"
  108. self.dogshoot_switch = 1
  109. self.dogshoot_count_max = 60
  110. self.dogshoot_count2_max = 20
  111. self.shoot_interval = 2
  112. self.shoot_offset = 2
  113. end
  114. if tmp.small then
  115. self.object:set_properties({
  116. collisionbox = {-0.2, -0.2, -0.2, 0.2, 0, 0.2},
  117. visual_size = {x = 0.25, y = 0.25}
  118. })
  119. end
  120. return true
  121. end
  122. end
  123. return true -- run only once, false/nil runs every activation
  124. end,
  125. -- custom function to make spiders climb vertical facings
  126. do_custom = function(self, dtime)
  127. -- quarter second timer
  128. self.spider_timer = (self.spider_timer or 0) + dtime
  129. if self.spider_timer < 0.25 then
  130. return
  131. end
  132. self.spider_timer = 0
  133. -- need to be stopped to go onwards
  134. if get_velocity(self) > 0.5 then
  135. self.disable_falling = nil
  136. return
  137. end
  138. local pos = self.object:get_pos()
  139. local yaw = self.object:get_yaw()
  140. -- sanity check
  141. if not yaw then return end
  142. pos.y = pos.y + self.collisionbox[2] - 0.2
  143. local dir_x = -math.sin(yaw) * (self.collisionbox[4] + 0.5)
  144. local dir_z = math.cos(yaw) * (self.collisionbox[4] + 0.5)
  145. local nod = minetest.get_node_or_nil({
  146. x = pos.x + dir_x,
  147. y = pos.y + 0.5,
  148. z = pos.z + dir_z
  149. })
  150. -- get current velocity
  151. local v = self.object:get_velocity()
  152. -- can only climb solid facings
  153. if not nod or not minetest.registered_nodes[nod.name]
  154. or not minetest.registered_nodes[nod.name].walkable then
  155. self.disable_falling = nil
  156. v.y = 0
  157. self.object:set_velocity(v)
  158. return
  159. end
  160. --print ("----", nod.name, self.disable_falling, dtime)
  161. -- turn off falling if attached to facing
  162. self.disable_falling = true
  163. -- move up facing
  164. v.x = 0 ; v.y = 0
  165. v.y = self.jump_height
  166. mobs:set_animation(self, "jump")
  167. self.object:set_velocity(v)
  168. end,
  169. -- make spiders jump at you on attack
  170. custom_attack = function(self, pos)
  171. local vel = self.object:get_velocity()
  172. self.object:set_velocity({
  173. x = vel.x * self.run_velocity,
  174. y = self.jump_height * 1.5,
  175. z = vel.z * self.run_velocity
  176. })
  177. self.pausetimer = 0.5
  178. return true -- continue rest of attack function
  179. end
  180. })
  181. if not mobs.custom_spawn_monster then
  182. -- above ground spawn
  183. mobs:spawn({
  184. name = "mobs_monster:spider",
  185. nodes = {
  186. "default:dirt_with_rainforest_litter", "default:snowblock",
  187. "default:snow", "ethereal:crystal_dirt", "ethereal:cold_dirt"
  188. },
  189. min_light = 0,
  190. max_light = 8,
  191. chance = 7000,
  192. active_object_count = 1,
  193. min_height = 25,
  194. max_height = 31000,
  195. })
  196. -- below ground spawn
  197. mobs:spawn({
  198. name = "mobs_monster:spider",
  199. nodes = {"default:stone_with_mese", "default:mese", "default:stone"},
  200. min_light = 0,
  201. max_light = 7,
  202. chance = 7000,
  203. active_object_count = 1,
  204. min_height = -31000,
  205. max_height = -40,
  206. })
  207. end
  208. mobs:register_egg("mobs_monster:spider", S("Spider"), "mobs_cobweb.png", 1)
  209. mobs:alias_mob("mobs_monster:spider2", "mobs_monster:spider") -- compatibility
  210. mobs:alias_mob("mobs:spider", "mobs_monster:spider")
  211. -- cobweb
  212. minetest.register_node(":mobs:cobweb", {
  213. description = S("Cobweb"),
  214. drawtype = "plantlike",
  215. visual_scale = 1.2,
  216. tiles = {"mobs_cobweb.png"},
  217. inventory_image = "mobs_cobweb.png",
  218. paramtype = "light",
  219. sunlight_propagates = true,
  220. liquid_viscosity = 11,
  221. liquidtype = "source",
  222. liquid_alternative_flowing = "mobs:cobweb",
  223. liquid_alternative_source = "mobs:cobweb",
  224. liquid_renewable = false,
  225. liquid_range = 0,
  226. walkable = false,
  227. groups = {snappy = 1, disable_jump = 1},
  228. drop = "farming:string",
  229. sounds = default.node_sound_leaves_defaults()
  230. })
  231. minetest.register_craft({
  232. output = "mobs:cobweb",
  233. recipe = {
  234. {"farming:string", "", "farming:string"},
  235. {"", "farming:string", ""},
  236. {"farming:string", "", "farming:string"},
  237. }
  238. })
  239. local web_place = function(pos)
  240. local pos2 = minetest.find_node_near(pos, 1, {"air", "group:leaves"}, true)
  241. if pos2 then
  242. minetest.swap_node(pos2, {name = "mobs:cobweb"})
  243. end
  244. end
  245. mobs:register_arrow("mobs_monster:cobweb", {
  246. visual = "sprite",
  247. visual_size = {x = 1, y = 1},
  248. textures = {"mobs_cobweb.png"},
  249. collisionbox = {-0.1, -0.1, -0.1, 0.1, 0.1, 0.1},
  250. velocity = 15,
  251. tail = 1,
  252. tail_texture = "mobs_cobweb.png",
  253. tail_size = 5,
  254. glow = 2,
  255. expire = 0.1,
  256. hit_player = function(self, player)
  257. player:punch(self.object, 1.0, {
  258. full_punch_interval = 2.0,
  259. damage_groups = {fleshy = 3},
  260. }, nil)
  261. web_place(self.object:get_pos())
  262. end,
  263. hit_node = function(self, pos, node)
  264. web_place(pos)
  265. end,
  266. hit_mob = function(self, player)
  267. player:punch(self.object, 1.0, {
  268. full_punch_interval = 2.0,
  269. damage_groups = {fleshy = 3},
  270. }, nil)
  271. end
  272. })