spider.lua 9.1 KB

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