sheep.lua 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. local S = mobs.intllib_animal
  2. local random = math.random
  3. local all_colours = {
  4. {"black", S("Black"), "#212121b0"}, -- referenced down in mobs:spawn
  5. {"blue", S("Blue"), "#015dbb70"},
  6. {"brown", S("Brown"), "#663300a0"}, -- referenced down in mobs:spawn
  7. {"cyan", S("Cyan"), "#00b4bf70"},
  8. {"dark_green", S("Dark Green"), "#005b0770"},
  9. {"dark_grey", S("Dark Grey"), "#444444b0"}, -- referenced down in mobs:spawn
  10. {"green", S("Green"), "#61ff0170"},
  11. {"grey", S("Grey"), "#919191b0"}, -- referenced down in mobs:spawn
  12. {"magenta", S("Magenta"), "#ed03ad70"},
  13. {"orange", S("Orange"), "#ff840170"},
  14. {"pink", S("Pink"), "#ff85c470"},
  15. {"red", S("Red"), "#ff0000a0"},
  16. {"violet", S("Violet"), "#5c00c970"},
  17. {"white", S("White"), "#ffffffc0"}, -- referenced down in mobs:spawn
  18. {"yellow", S("Yellow"), "#fff80070"}
  19. }
  20. -- Sheep by PilzAdam/K Pavel, texture converted to minetest by AMMOnym from Summerfield pack
  21. for _, col in ipairs(all_colours) do
  22. local drops_normal = {
  23. {name = "mobs:mutton_raw", chance = 1, min = 1, max = 2},
  24. {name = "wool:" .. col[1], chance = 1, min = 1, max = 1}
  25. }
  26. local drops_gotten = {
  27. {name = "mobs:mutton_raw", chance = 1, min = 1, max = 2}
  28. }
  29. local function horn_texture_sel(horns, gotten, colr)
  30. local base_text = "mobs_sheep_base.png"
  31. local wool_shave_text = "mobs_sheep_wool.png"
  32. local shav_text = "mobs_sheep_shaved.png"
  33. local horn_text = "mobs_sheep_horns.png"
  34. local col_override = colr and colr or col[3]
  35. local col_text = "^[multiply:" .. col_override
  36. if gotten then
  37. wool_shave_text = shav_text
  38. col_text = ""
  39. end
  40. -- results in unneccesary brackets for shaved but these are ignored by engine
  41. local textures = base_text .. "^(" .. wool_shave_text .. col_text .. ")"
  42. if horns then
  43. textures = base_text .. "^" .. horn_text .. "^(" .. wool_shave_text
  44. .. col_text .. ")"
  45. end
  46. return textures
  47. end
  48. mobs:register_mob("mobs_animal:sheep_" .. col[1], {
  49. stay_near = {"farming:straw", 10},
  50. stepheight = 0.6,
  51. type = "animal",
  52. passive = true,
  53. hp_min = 8,
  54. hp_max = 10,
  55. armor = 200,
  56. collisionbox = {-0.5, -1, -0.5, 0.5, 0.3, 0.5},
  57. visual = "mesh",
  58. mesh = "mobs_sheep.b3d",
  59. textures = {
  60. {"mobs_sheep_base.png^(mobs_sheep_wool.png^[multiply:" .. col[3] .. ")"}
  61. },
  62. gotten_texture = {"mobs_sheep_base.png^mobs_sheep_shaved.png"},
  63. makes_footstep_sound = true,
  64. sounds = {
  65. random = "mobs_sheep"
  66. },
  67. walk_velocity = 1,
  68. run_velocity = 2,
  69. runaway = true,
  70. jump = true,
  71. jump_height = 6,
  72. pushable = true,
  73. drops = drops_normal,
  74. water_damage = 0.01,
  75. lava_damage = 5,
  76. light_damage = 0,
  77. animation = {
  78. speed_normal = 15,
  79. speed_run = 15,
  80. stand_start = 0,
  81. stand_end = 80,
  82. walk_start = 81,
  83. walk_end = 100,
  84. die_start = 1, -- we dont have a specific death animation so we will
  85. die_end = 2, -- re-use 2 standing frames at a speed of 1 fps and
  86. die_speed = 1, -- have mob rotate when dying.
  87. die_loop = false,
  88. die_rotate = true
  89. },
  90. follow = {
  91. "farming:wheat", "default:grass_1", "farming:barley",
  92. "farming:oat", "farming:rye"
  93. },
  94. view_range = 8,
  95. replace_rate = 10,
  96. replace_what = {
  97. {"group:grass", "air", -1},
  98. {"default:dirt_with_grass", "default:dirt", -2}
  99. },
  100. fear_height = 3,
  101. on_replace = function(self, pos, oldnode, newnode)
  102. self.food = (self.food or 0) + 1
  103. -- if sheep replaces 8x grass then it regrows wool
  104. if self.food >= 8 then
  105. self.food = 0
  106. self.gotten = false
  107. self.drops = drops_normal
  108. local textures = horn_texture_sel(self.attribute_horns, self.gotten)
  109. self.object:set_properties({textures = {textures}})
  110. -- base_texture must be kept up to date for static_save so horns persist
  111. -- visually on server/game restart
  112. self.base_texture = {textures}
  113. end
  114. end,
  115. on_breed = function(parent1, parent2)
  116. -- simple truth table P1/P2 horns/no_horns
  117. local breed_out = {
  118. ["P1_N"] = {["P2_N"] = 5 ,["P2_H"] = 50},
  119. ["P1_H"] = {["P2_N"] = 50,["P2_H"] = 95}
  120. }
  121. local p1 = parent1.attribute_horns and "P1_H" or "P1_N"
  122. local p2 = parent2.attribute_horns and "P2_H" or "P2_N"
  123. local horn_chance = breed_out[p1][p2]
  124. local horns = random(100) <= horn_chance
  125. local pos = parent1.object:get_pos()
  126. -- can't see an easy way to pass horn attribute into
  127. -- child entity def, handle all spawning here, unfortunate
  128. -- code replication from mobs_redo api.lua line 1497+
  129. -- replace "self" with "parent1" and few other minor tweaks
  130. ----------------------------------------------------
  131. pos.y = pos.y + 0.5 -- spawn child a little higher
  132. local mob = minetest.add_entity(pos, parent1.name)
  133. local ent2 = mob:get_luaentity()
  134. -- remove horns from parents' texture string, lambs dont have horns
  135. local textures = string.gsub(parent1.base_texture[1],
  136. "%^mobs_sheep_horns.png", "")
  137. -- using specific child texture (if found)
  138. if parent1.child_texture then
  139. textures = parent1.child_texture[1]
  140. end
  141. -- and resize to half height
  142. mob:set_properties({
  143. textures = {textures},
  144. visual_size = {
  145. x = parent1.base_size.x * .5,
  146. y = parent1.base_size.y * .5
  147. },
  148. collisionbox = {
  149. parent1.base_colbox[1] * .5,
  150. parent1.base_colbox[2] * .5,
  151. parent1.base_colbox[3] * .5,
  152. parent1.base_colbox[4] * .5,
  153. parent1.base_colbox[5] * .5,
  154. parent1.base_colbox[6] * .5
  155. },
  156. selectionbox = {
  157. parent1.base_selbox[1] * .5,
  158. parent1.base_selbox[2] * .5,
  159. parent1.base_selbox[3] * .5,
  160. parent1.base_selbox[4] * .5,
  161. parent1.base_selbox[5] * .5,
  162. parent1.base_selbox[6] * .5
  163. }
  164. })
  165. -- tamed and owned by parents' owner
  166. ent2.child = true
  167. ent2.tamed = true
  168. ent2.owner = parent1.owner
  169. ent2.attribute_horns = horns
  170. -- stop mobs_redo api from spawning child
  171. return false
  172. end,
  173. on_grown = function(self)
  174. -- add the horns if we have horns when fully grown
  175. local textures = horn_texture_sel(self.attribute_horns, self.gotten)
  176. self.object:set_properties({textures = {textures}})
  177. self.base_texture = {textures}
  178. local pos = self.object:get_pos()
  179. pos.y = pos.y + (self.collisionbox[2] * -1) - 0.4
  180. self.object:set_pos(pos)
  181. -- jump slightly when fully grown so as not to fall into ground
  182. self.object:set_velocity({x = 0, y = 2, z = 0 })
  183. end,
  184. on_rightclick = function(self, clicker)
  185. -- are we feeding?
  186. if mobs:feed_tame(self, clicker, 8, true, true) then
  187. if not self.child then
  188. local textures = horn_texture_sel(self.attribute_horns, self.gotten)
  189. self.object:set_properties({textures = {textures}})
  190. self.base_texture = {textures}
  191. end
  192. --if fed 7 times then sheep regrows wool
  193. if self.food and self.food > 6 then
  194. self.gotten = false
  195. self.drops = drops_normal
  196. local textures = horn_texture_sel(self.attribute_horns, self.gotten)
  197. self.object:set_properties({textures = {textures}})
  198. self.base_texture = {textures}
  199. end
  200. return
  201. end
  202. local item = clicker:get_wielded_item()
  203. local itemname = item:get_name()
  204. local name = clicker:get_player_name()
  205. -- are we giving a haircut>
  206. if itemname == "mobs:shears" then
  207. if self.gotten ~= false
  208. or self.child ~= false
  209. or name ~= self.owner
  210. or not minetest.get_modpath("wool") then
  211. return
  212. end
  213. self.gotten = true -- shaved
  214. self.drops = drops_gotten
  215. local obj = minetest.add_item(
  216. self.object:get_pos(),
  217. ItemStack("wool:" .. col[1] .. " " .. random(3))
  218. )
  219. if obj then
  220. obj:set_velocity({
  221. x = random(-1, 1),
  222. y = 5,
  223. z = random(-1, 1)
  224. })
  225. end
  226. item:add_wear(650) -- 100 uses
  227. clicker:set_wielded_item(item)
  228. local textures = horn_texture_sel(self.attribute_horns, self.gotten)
  229. self.object:set_properties({textures = {textures}})
  230. self.base_texture = {textures}
  231. return
  232. end
  233. -- are we coloring?
  234. if itemname:find("dye:") then
  235. if self.gotten == false
  236. and self.child == false
  237. and self.tamed == true
  238. and name == self.owner then
  239. local colr = string.split(itemname, ":")[2]
  240. for _,c in pairs(all_colours) do
  241. -- only dye if colour option available and sheep not same colour
  242. if c[1] == colr
  243. and self.name ~= "mobs_animal:sheep_" .. colr then
  244. local pos = self.object:get_pos()
  245. -- add new coloured sheep
  246. local mob = minetest.add_entity(pos, "mobs_animal:sheep_" .. colr)
  247. local ent = mob:get_luaentity()
  248. if ent then
  249. -- add old sheep attributes
  250. ent.attribute_horns = self.attribute_horns
  251. ent.nametag = self.nametag
  252. ent.owner = name
  253. ent.tamed = true
  254. ent.protected = self.protected
  255. ent.fire_damage = self.fire_damage
  256. -- set sheep texture with colour override since we're
  257. -- calling function inside different sheep
  258. local textures = horn_texture_sel(
  259. self.attribute_horns, false, colr)
  260. ent.base_texture = {textures}
  261. ent.object:set_properties({
  262. textures = {textures},
  263. nametag = self.nametag
  264. })
  265. -- remove old sheep
  266. self.object:remove()
  267. -- take item
  268. if not mobs.is_creative(clicker:get_player_name()) then
  269. item:take_item()
  270. clicker:set_wielded_item(item)
  271. end
  272. break
  273. end
  274. end
  275. end
  276. end
  277. return
  278. end
  279. -- protect mod with mobs:protector item
  280. if mobs:protect(self, clicker) then return end
  281. --are we capturing?
  282. if mobs:capture_mob(self, clicker, 0, 5, 60, false, nil) then return end
  283. end
  284. })
  285. -- spawn egg
  286. mobs:register_egg("mobs_animal:sheep_"..col[1], S("@1 Sheep", col[2]),
  287. "wool_" .. col[1] .. ".png^mobs_sheep_inv.png")
  288. -- compatibility
  289. mobs:alias_mob("mobs:sheep_" .. col[1], "mobs_animal:sheep_" .. col[1])
  290. end
  291. if not mobs.custom_spawn_animal then
  292. local max_ht = 400
  293. local spawn_on = {"default:dirt_with_grass", "ethereal:green_dirt"}
  294. local mod_ethereal = minetest.get_modpath("ethereal")
  295. local spawn_chance = mod_ethereal and 12000 or 8000
  296. mobs:spawn({
  297. name = "mobs_animal:sheep_white",
  298. nodes = spawn_on,
  299. neighbors = {"group:grass"},
  300. min_light = 14,
  301. interval = 60,
  302. chance = spawn_chance,
  303. min_height = 0,
  304. max_height = max_ht,
  305. day_toggle = true,
  306. active_object_count = 3,
  307. -- custom function to spawn sheep herds around main mob
  308. on_spawn = function(self, pos)
  309. local nat_colors = {-- reference for all_colours table
  310. ["white"] = 14,
  311. ["grey"] = 8,
  312. ["dark_grey"] = 6,
  313. ["black"] = 1,
  314. ["brown"] = 3
  315. }
  316. local function random_sheep(pos, first)
  317. local types = "white"
  318. local color = all_colours[nat_colors["white"]][3]
  319. -- Random colour selection
  320. -- black(1/8), brown(1/16), dark_grey(1/32), grey(1/32), 6/8 white
  321. local ran_col = random(32)
  322. if ran_col <= 8 then
  323. if ran_col == 1 then
  324. types = "dark_grey"
  325. elseif ran_col == 2 then
  326. types = "grey"
  327. elseif ran_col >= 3 and ran_col <= 4 then
  328. types = "brown"
  329. else
  330. types = "black"
  331. end
  332. end
  333. -- 1/4 chance of lamb
  334. local lamb
  335. if not first then
  336. lamb = random(4) == 1
  337. end
  338. -- store returned entity data from mobs:add_mob, "nil" indicates the
  339. -- rules in mobs:add_mob stopped mob from being spawned/created.
  340. local entity = mobs:add_mob(pos,
  341. {name = "mobs_animal:sheep_" .. types, child = lamb})
  342. if entity and not lamb then
  343. -- Set horns attribute, lower height will be rarer.
  344. -- This wont affect mobs spawned by egg those only spawn hornless sheep.
  345. local horns = random(max_ht) <= pos.y
  346. if horns then
  347. local text = "mobs_sheep_base.png^mobs_sheep_horns.png"
  348. .."^(mobs_sheep_wool.png^[multiply:"
  349. .. all_colours[nat_colors[types]][3] .. ")"
  350. entity.object:set_properties({textures = {text}})
  351. entity.base_texture = {text}
  352. entity.attribute_horns = horns
  353. end
  354. end
  355. end
  356. -- First Sheep, Randomize color/horns
  357. self.object:remove()
  358. random_sheep(pos, true)
  359. -- Rest of herd
  360. local nods = minetest.find_nodes_in_area_under_air(
  361. {x = pos.x - 4, y = pos.y - 3, z = pos.z - 4},
  362. {x = pos.x + 4, y = pos.y + 3, z = pos.z + 4}, spawn_on)
  363. if nods and #nods > 0 then
  364. -- min herd of 3
  365. local iter = math.min(#nods, 3)
  366. for n = 1, iter do
  367. local pos2 = nods[random(#nods)]
  368. pos2.y = pos2.y + 2
  369. if minetest.get_node(pos2).name == "air" then
  370. -- Add a sheep or lamb
  371. random_sheep(pos2, false)
  372. end
  373. end
  374. end
  375. end
  376. })
  377. end
  378. mobs:alias_mob("mobs:sheep", "mobs_animal:sheep_white") -- compatibility
  379. -- raw mutton
  380. minetest.register_craftitem(":mobs:mutton_raw", {
  381. description = S("Raw Mutton"),
  382. inventory_image = "mobs_mutton_raw.png",
  383. on_use = minetest.item_eat(2),
  384. groups = {food_meat_raw = 1, food_mutton_raw = 1, flammable = 2}
  385. })
  386. -- cooked mutton
  387. minetest.register_craftitem(":mobs:mutton_cooked", {
  388. description = S("Cooked Mutton"),
  389. inventory_image = "mobs_mutton_cooked.png",
  390. on_use = minetest.item_eat(6),
  391. groups = {food_meat = 1, food_mutton = 1, flammable = 2}
  392. })
  393. minetest.register_craft({
  394. type = "cooking",
  395. output = "mobs:mutton_cooked",
  396. recipe = "mobs:mutton_raw",
  397. cooktime = 5
  398. })